github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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) // zeroed 290 return 1; 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 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->type = ll->type; 363 rr->xoffset += e->xoffset; 364 *out = list(*out, nod(OAS, ll, rr)); 365 } 366 } 367 } 368 return 1; 369 } 370 return 0; 371 } 372 373 static int 374 staticassign(Node *l, Node *r, NodeList **out) 375 { 376 Node *a, n1; 377 Type *ta; 378 InitPlan *p; 379 InitEntry *e; 380 int i; 381 382 switch(r->op) { 383 default: 384 //dump("not static", r); 385 break; 386 387 case ONAME: 388 if(r->class == PEXTERN && r->sym->pkg == localpkg) 389 return staticcopy(l, r, out); 390 break; 391 392 case OLITERAL: 393 if(iszero(r)) 394 return 1; 395 gdata(l, r, l->type->width); 396 return 1; 397 398 case OADDR: 399 switch(r->left->op) { 400 default: 401 //dump("not static addr", r); 402 break; 403 404 case ONAME: 405 gdata(l, r, l->type->width); 406 return 1; 407 } 408 409 case OPTRLIT: 410 switch(r->left->op) { 411 default: 412 //dump("not static ptrlit", r); 413 break; 414 415 case OARRAYLIT: 416 case OMAPLIT: 417 case OSTRUCTLIT: 418 // Init pointer. 419 a = staticname(r->left->type, 1); 420 r->nname = a; 421 gdata(l, nod(OADDR, a, N), l->type->width); 422 // Init underlying literal. 423 if(!staticassign(a, r->left, out)) 424 *out = list(*out, nod(OAS, a, r->left)); 425 return 1; 426 } 427 break; 428 429 case OARRAYLIT: 430 initplan(r); 431 if(isslice(r->type)) { 432 // Init slice. 433 ta = typ(TARRAY); 434 ta->type = r->type->type; 435 ta->bound = mpgetfix(r->right->val.u.xval); 436 a = staticname(ta, 1); 437 r->nname = a; 438 n1 = *l; 439 n1.xoffset = l->xoffset + Array_array; 440 gdata(&n1, nod(OADDR, a, N), widthptr); 441 n1.xoffset = l->xoffset + Array_nel; 442 gdata(&n1, r->right, widthint); 443 n1.xoffset = l->xoffset + Array_cap; 444 gdata(&n1, r->right, widthint); 445 // Fall through to init underlying array. 446 l = a; 447 } 448 // fall through 449 case OSTRUCTLIT: 450 initplan(r); 451 p = r->initplan; 452 n1 = *l; 453 for(i=0; i<p->len; i++) { 454 e = &p->e[i]; 455 n1.xoffset = l->xoffset + e->xoffset; 456 n1.type = e->expr->type; 457 if(e->expr->op == OLITERAL) 458 gdata(&n1, e->expr, n1.type->width); 459 else { 460 a = nod(OXXX, N, N); 461 *a = n1; 462 if(!staticassign(a, e->expr, out)) 463 *out = list(*out, nod(OAS, a, e->expr)); 464 } 465 } 466 return 1; 467 468 case OMAPLIT: 469 // TODO: Table-driven map insert. 470 break; 471 } 472 return 0; 473 } 474 475 /* 476 * from here down is the walk analysis 477 * of composite literals. 478 * most of the work is to generate 479 * data statements for the constant 480 * part of the composite literal. 481 */ 482 483 static void structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init); 484 static void arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init); 485 static void slicelit(int ctxt, Node *n, Node *var, NodeList **init); 486 static void maplit(int ctxt, Node *n, Node *var, NodeList **init); 487 488 static Node* 489 staticname(Type *t, int ctxt) 490 { 491 Node *n; 492 493 snprint(namebuf, sizeof(namebuf), "statictmp_%.4d", statuniqgen); 494 statuniqgen++; 495 n = newname(lookup(namebuf)); 496 if(!ctxt) 497 n->readonly = 1; 498 addvar(n, t, PEXTERN); 499 return n; 500 } 501 502 static int 503 isliteral(Node *n) 504 { 505 if(n->op == OLITERAL) 506 if(n->val.ctype != CTNIL) 507 return 1; 508 return 0; 509 } 510 511 static int 512 simplename(Node *n) 513 { 514 if(n->op != ONAME) 515 goto no; 516 if(!n->addable) 517 goto no; 518 if(n->class & PHEAP) 519 goto no; 520 if(n->class == PPARAMREF) 521 goto no; 522 return 1; 523 524 no: 525 return 0; 526 } 527 528 static void 529 litas(Node *l, Node *r, NodeList **init) 530 { 531 Node *a; 532 533 a = nod(OAS, l, r); 534 typecheck(&a, Etop); 535 walkexpr(&a, init); 536 *init = list(*init, a); 537 } 538 539 enum 540 { 541 MODEDYNAM = 1, 542 MODECONST = 2, 543 }; 544 545 static int 546 getdyn(Node *n, int top) 547 { 548 NodeList *nl; 549 Node *value; 550 int mode; 551 552 mode = 0; 553 switch(n->op) { 554 default: 555 if(isliteral(n)) 556 return MODECONST; 557 return MODEDYNAM; 558 case OARRAYLIT: 559 if(!top && n->type->bound < 0) 560 return MODEDYNAM; 561 case OSTRUCTLIT: 562 break; 563 } 564 565 for(nl=n->list; nl; nl=nl->next) { 566 value = nl->n->right; 567 mode |= getdyn(value, 0); 568 if(mode == (MODEDYNAM|MODECONST)) 569 break; 570 } 571 return mode; 572 } 573 574 static void 575 structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init) 576 { 577 Node *r, *a; 578 NodeList *nl; 579 Node *index, *value; 580 581 for(nl=n->list; nl; nl=nl->next) { 582 r = nl->n; 583 if(r->op != OKEY) 584 fatal("structlit: rhs not OKEY: %N", r); 585 index = r->left; 586 value = r->right; 587 588 switch(value->op) { 589 case OARRAYLIT: 590 if(value->type->bound < 0) { 591 if(pass == 1 && ctxt != 0) { 592 a = nod(ODOT, var, newname(index->sym)); 593 slicelit(ctxt, value, a, init); 594 } else 595 if(pass == 2 && ctxt == 0) { 596 a = nod(ODOT, var, newname(index->sym)); 597 slicelit(ctxt, value, a, init); 598 } else 599 if(pass == 3) 600 break; 601 continue; 602 } 603 a = nod(ODOT, var, newname(index->sym)); 604 arraylit(ctxt, pass, value, a, init); 605 continue; 606 607 case OSTRUCTLIT: 608 a = nod(ODOT, var, newname(index->sym)); 609 structlit(ctxt, pass, value, a, init); 610 continue; 611 } 612 613 if(isliteral(value)) { 614 if(pass == 2) 615 continue; 616 } else 617 if(pass == 1) 618 continue; 619 620 // build list of var.field = expr 621 a = nod(ODOT, var, newname(index->sym)); 622 a = nod(OAS, a, value); 623 typecheck(&a, Etop); 624 walkexpr(&a, init); 625 if(pass == 1) { 626 if(a->op != OAS) 627 fatal("structlit: not as"); 628 a->dodata = 2; 629 } 630 *init = list(*init, a); 631 } 632 } 633 634 static void 635 arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init) 636 { 637 Node *r, *a; 638 NodeList *l; 639 Node *index, *value; 640 641 for(l=n->list; l; l=l->next) { 642 r = l->n; 643 if(r->op != OKEY) 644 fatal("arraylit: rhs not OKEY: %N", r); 645 index = r->left; 646 value = r->right; 647 648 switch(value->op) { 649 case OARRAYLIT: 650 if(value->type->bound < 0) { 651 if(pass == 1 && ctxt != 0) { 652 a = nod(OINDEX, var, index); 653 slicelit(ctxt, value, a, init); 654 } else 655 if(pass == 2 && ctxt == 0) { 656 a = nod(OINDEX, var, index); 657 slicelit(ctxt, value, a, init); 658 } else 659 if(pass == 3) 660 break; 661 continue; 662 } 663 a = nod(OINDEX, var, index); 664 arraylit(ctxt, pass, value, a, init); 665 continue; 666 667 case OSTRUCTLIT: 668 a = nod(OINDEX, var, index); 669 structlit(ctxt, pass, value, a, init); 670 continue; 671 } 672 673 if(isliteral(index) && isliteral(value)) { 674 if(pass == 2) 675 continue; 676 } else 677 if(pass == 1) 678 continue; 679 680 // build list of var[index] = value 681 a = nod(OINDEX, var, index); 682 a = nod(OAS, a, value); 683 typecheck(&a, Etop); 684 walkexpr(&a, init); // add any assignments in r to top 685 if(pass == 1) { 686 if(a->op != OAS) 687 fatal("structlit: not as"); 688 a->dodata = 2; 689 } 690 *init = list(*init, a); 691 } 692 } 693 694 static void 695 slicelit(int ctxt, Node *n, Node *var, NodeList **init) 696 { 697 Node *r, *a; 698 NodeList *l; 699 Type *t; 700 Node *vstat, *vauto; 701 Node *index, *value; 702 int mode; 703 704 // make an array type 705 t = shallow(n->type); 706 t->bound = mpgetfix(n->right->val.u.xval); 707 t->width = 0; 708 t->sym = nil; 709 t->haspointers = 0; 710 dowidth(t); 711 712 if(ctxt != 0) { 713 // put everything into static array 714 vstat = staticname(t, ctxt); 715 arraylit(ctxt, 1, n, vstat, init); 716 arraylit(ctxt, 2, n, vstat, init); 717 718 // copy static to slice 719 a = nod(OSLICE, vstat, nod(OKEY, N, N)); 720 a = nod(OAS, var, a); 721 typecheck(&a, Etop); 722 a->dodata = 2; 723 *init = list(*init, a); 724 return; 725 } 726 727 // recipe for var = []t{...} 728 // 1. make a static array 729 // var vstat [...]t 730 // 2. assign (data statements) the constant part 731 // vstat = constpart{} 732 // 3. make an auto pointer to array and allocate heap to it 733 // var vauto *[...]t = new([...]t) 734 // 4. copy the static array to the auto array 735 // *vauto = vstat 736 // 5. assign slice of allocated heap to var 737 // var = [0:]*auto 738 // 6. for each dynamic part assign to the slice 739 // var[i] = dynamic part 740 // 741 // an optimization is done if there is no constant part 742 // 3. var vauto *[...]t = new([...]t) 743 // 5. var = [0:]*auto 744 // 6. var[i] = dynamic part 745 746 // if the literal contains constants, 747 // make static initialized array (1),(2) 748 vstat = N; 749 mode = getdyn(n, 1); 750 if(mode & MODECONST) { 751 vstat = staticname(t, ctxt); 752 arraylit(ctxt, 1, n, vstat, init); 753 } 754 755 // make new auto *array (3 declare) 756 vauto = temp(ptrto(t)); 757 758 // set auto to point at new temp or heap (3 assign) 759 if(n->esc == EscNone) { 760 a = nod(OAS, temp(t), N); 761 typecheck(&a, Etop); 762 *init = list(*init, a); // zero new temp 763 a = nod(OADDR, a->left, N); 764 } else { 765 a = nod(ONEW, N, N); 766 a->list = list1(typenod(t)); 767 } 768 a = nod(OAS, vauto, a); 769 typecheck(&a, Etop); 770 walkexpr(&a, init); 771 *init = list(*init, a); 772 773 if(vstat != N) { 774 // copy static to heap (4) 775 a = nod(OIND, vauto, N); 776 a = nod(OAS, a, vstat); 777 typecheck(&a, Etop); 778 walkexpr(&a, init); 779 *init = list(*init, a); 780 } 781 782 // make slice out of heap (5) 783 a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N))); 784 typecheck(&a, Etop); 785 walkexpr(&a, init); 786 *init = list(*init, a); 787 788 // put dynamics into slice (6) 789 for(l=n->list; l; l=l->next) { 790 r = l->n; 791 if(r->op != OKEY) 792 fatal("slicelit: rhs not OKEY: %N", r); 793 index = r->left; 794 value = r->right; 795 a = nod(OINDEX, var, index); 796 a->bounded = 1; 797 // TODO need to check bounds? 798 799 switch(value->op) { 800 case OARRAYLIT: 801 if(value->type->bound < 0) 802 break; 803 arraylit(ctxt, 2, value, a, init); 804 continue; 805 806 case OSTRUCTLIT: 807 structlit(ctxt, 2, value, a, init); 808 continue; 809 } 810 811 if(isliteral(index) && isliteral(value)) 812 continue; 813 814 // build list of var[c] = expr 815 a = nod(OAS, a, value); 816 typecheck(&a, Etop); 817 walkexpr(&a, init); 818 *init = list(*init, a); 819 } 820 } 821 822 static void 823 maplit(int ctxt, Node *n, Node *var, NodeList **init) 824 { 825 Node *r, *a; 826 NodeList *l; 827 int nerr; 828 int64 b; 829 Type *t, *tk, *tv, *t1; 830 Node *vstat, *index, *value; 831 Sym *syma, *symb; 832 833 USED(ctxt); 834 ctxt = 0; 835 836 // make the map var 837 nerr = nerrors; 838 839 a = nod(OMAKE, N, N); 840 a->list = list1(typenod(n->type)); 841 litas(var, a, init); 842 843 // count the initializers 844 b = 0; 845 for(l=n->list; l; l=l->next) { 846 r = l->n; 847 848 if(r->op != OKEY) 849 fatal("slicelit: rhs not OKEY: %N", r); 850 index = r->left; 851 value = r->right; 852 853 if(isliteral(index) && isliteral(value)) 854 b++; 855 } 856 857 if(b != 0) { 858 // build type [count]struct { a Tindex, b Tvalue } 859 t = n->type; 860 tk = t->down; 861 tv = t->type; 862 863 symb = lookup("b"); 864 t = typ(TFIELD); 865 t->type = tv; 866 t->sym = symb; 867 868 syma = lookup("a"); 869 t1 = t; 870 t = typ(TFIELD); 871 t->type = tk; 872 t->sym = syma; 873 t->down = t1; 874 875 t1 = t; 876 t = typ(TSTRUCT); 877 t->type = t1; 878 879 t1 = t; 880 t = typ(TARRAY); 881 t->bound = b; 882 t->type = t1; 883 884 dowidth(t); 885 886 // make and initialize static array 887 vstat = staticname(t, ctxt); 888 b = 0; 889 for(l=n->list; l; l=l->next) { 890 r = l->n; 891 892 if(r->op != OKEY) 893 fatal("slicelit: rhs not OKEY: %N", r); 894 index = r->left; 895 value = r->right; 896 897 if(isliteral(index) && isliteral(value)) { 898 // build vstat[b].a = key; 899 a = nodintconst(b); 900 a = nod(OINDEX, vstat, a); 901 a = nod(ODOT, a, newname(syma)); 902 a = nod(OAS, a, index); 903 typecheck(&a, Etop); 904 walkexpr(&a, init); 905 a->dodata = 2; 906 *init = list(*init, a); 907 908 // build vstat[b].b = value; 909 a = nodintconst(b); 910 a = nod(OINDEX, vstat, a); 911 a = nod(ODOT, a, newname(symb)); 912 a = nod(OAS, a, value); 913 typecheck(&a, Etop); 914 walkexpr(&a, init); 915 a->dodata = 2; 916 *init = list(*init, a); 917 918 b++; 919 } 920 } 921 922 // loop adding structure elements to map 923 // for i = 0; i < len(vstat); i++ { 924 // map[vstat[i].a] = vstat[i].b 925 // } 926 index = temp(types[TINT]); 927 928 a = nod(OINDEX, vstat, index); 929 a->bounded = 1; 930 a = nod(ODOT, a, newname(symb)); 931 932 r = nod(OINDEX, vstat, index); 933 r->bounded = 1; 934 r = nod(ODOT, r, newname(syma)); 935 r = nod(OINDEX, var, r); 936 937 r = nod(OAS, r, a); 938 939 a = nod(OFOR, N, N); 940 a->nbody = list1(r); 941 942 a->ninit = list1(nod(OAS, index, nodintconst(0))); 943 a->ntest = nod(OLT, index, nodintconst(t->bound)); 944 a->nincr = nod(OASOP, index, nodintconst(1)); 945 a->nincr->etype = OADD; 946 947 typecheck(&a, Etop); 948 walkstmt(&a); 949 *init = list(*init, a); 950 } 951 952 // put in dynamic entries one-at-a-time 953 for(l=n->list; l; l=l->next) { 954 r = l->n; 955 956 if(r->op != OKEY) 957 fatal("slicelit: rhs not OKEY: %N", r); 958 index = r->left; 959 value = r->right; 960 961 if(isliteral(index) && isliteral(value)) 962 continue; 963 964 // build list of var[c] = expr 965 a = nod(OINDEX, var, r->left); 966 a = nod(OAS, a, r->right); 967 typecheck(&a, Etop); 968 walkexpr(&a, init); 969 if(nerr != nerrors) 970 break; 971 972 *init = list(*init, a); 973 } 974 } 975 976 void 977 anylit(int ctxt, Node *n, Node *var, NodeList **init) 978 { 979 Type *t; 980 Node *a, *vstat, *r; 981 982 t = n->type; 983 switch(n->op) { 984 default: 985 fatal("anylit: not lit"); 986 987 case OPTRLIT: 988 if(!isptr[t->etype]) 989 fatal("anylit: not ptr"); 990 991 r = nod(ONEW, N, N); 992 r->typecheck = 1; 993 r->type = t; 994 r->esc = n->esc; 995 walkexpr(&r, init); 996 997 a = nod(OAS, var, r); 998 999 typecheck(&a, Etop); 1000 *init = list(*init, a); 1001 1002 var = nod(OIND, var, N); 1003 typecheck(&var, Erv | Easgn); 1004 anylit(ctxt, n->left, var, init); 1005 break; 1006 1007 case OSTRUCTLIT: 1008 if(t->etype != TSTRUCT) 1009 fatal("anylit: not struct"); 1010 1011 if(simplename(var)) { 1012 1013 if(ctxt == 0) { 1014 // lay out static data 1015 vstat = staticname(t, ctxt); 1016 structlit(ctxt, 1, n, vstat, init); 1017 1018 // copy static to var 1019 a = nod(OAS, var, vstat); 1020 typecheck(&a, Etop); 1021 walkexpr(&a, init); 1022 *init = list(*init, a); 1023 1024 // add expressions to automatic 1025 structlit(ctxt, 2, n, var, init); 1026 break; 1027 } 1028 structlit(ctxt, 1, n, var, init); 1029 structlit(ctxt, 2, n, var, init); 1030 break; 1031 } 1032 1033 // initialize of not completely specified 1034 if(count(n->list) < structcount(t)) { 1035 a = nod(OAS, var, N); 1036 typecheck(&a, Etop); 1037 walkexpr(&a, init); 1038 *init = list(*init, a); 1039 } 1040 structlit(ctxt, 3, n, var, init); 1041 break; 1042 1043 case OARRAYLIT: 1044 if(t->etype != TARRAY) 1045 fatal("anylit: not array"); 1046 if(t->bound < 0) { 1047 slicelit(ctxt, n, var, init); 1048 break; 1049 } 1050 1051 if(simplename(var)) { 1052 1053 if(ctxt == 0) { 1054 // lay out static data 1055 vstat = staticname(t, ctxt); 1056 arraylit(1, 1, n, vstat, init); 1057 1058 // copy static to automatic 1059 a = nod(OAS, var, vstat); 1060 typecheck(&a, Etop); 1061 walkexpr(&a, init); 1062 *init = list(*init, a); 1063 1064 // add expressions to automatic 1065 arraylit(ctxt, 2, n, var, init); 1066 break; 1067 } 1068 arraylit(ctxt, 1, n, var, init); 1069 arraylit(ctxt, 2, n, var, init); 1070 break; 1071 } 1072 1073 // initialize of not completely specified 1074 if(count(n->list) < t->bound) { 1075 a = nod(OAS, var, N); 1076 typecheck(&a, Etop); 1077 walkexpr(&a, init); 1078 *init = list(*init, a); 1079 } 1080 arraylit(ctxt, 3, n, var, init); 1081 break; 1082 1083 case OMAPLIT: 1084 if(t->etype != TMAP) 1085 fatal("anylit: not map"); 1086 maplit(ctxt, n, var, init); 1087 break; 1088 } 1089 } 1090 1091 int 1092 oaslit(Node *n, NodeList **init) 1093 { 1094 int ctxt; 1095 1096 if(n->left == N || n->right == N) 1097 goto no; 1098 if(n->left->type == T || n->right->type == T) 1099 goto no; 1100 if(!simplename(n->left)) 1101 goto no; 1102 if(!eqtype(n->left->type, n->right->type)) 1103 goto no; 1104 1105 // context is init() function. 1106 // implies generated data executed 1107 // exactly once and not subject to races. 1108 ctxt = 0; 1109 // if(n->dodata == 1) 1110 // ctxt = 1; 1111 1112 switch(n->right->op) { 1113 default: 1114 goto no; 1115 1116 case OSTRUCTLIT: 1117 case OARRAYLIT: 1118 case OMAPLIT: 1119 if(vmatch1(n->left, n->right)) 1120 goto no; 1121 anylit(ctxt, n->right, n->left, init); 1122 break; 1123 } 1124 n->op = OEMPTY; 1125 return 1; 1126 1127 no: 1128 // not a special composit literal assignment 1129 return 0; 1130 } 1131 1132 static int 1133 getlit(Node *lit) 1134 { 1135 if(smallintconst(lit)) 1136 return mpgetfix(lit->val.u.xval); 1137 return -1; 1138 } 1139 1140 int 1141 stataddr(Node *nam, Node *n) 1142 { 1143 int l; 1144 1145 if(n == N) 1146 goto no; 1147 1148 switch(n->op) { 1149 1150 case ONAME: 1151 *nam = *n; 1152 return n->addable; 1153 1154 case ODOT: 1155 if(!stataddr(nam, n->left)) 1156 break; 1157 nam->xoffset += n->xoffset; 1158 nam->type = n->type; 1159 return 1; 1160 1161 case OINDEX: 1162 if(n->left->type->bound < 0) 1163 break; 1164 if(!stataddr(nam, n->left)) 1165 break; 1166 l = getlit(n->right); 1167 if(l < 0) 1168 break; 1169 // Check for overflow. 1170 if(n->type->width != 0 && MAXWIDTH/n->type->width <= l) 1171 break; 1172 nam->xoffset += l*n->type->width; 1173 nam->type = n->type; 1174 return 1; 1175 } 1176 1177 no: 1178 return 0; 1179 } 1180 1181 int 1182 gen_as_init(Node *n) 1183 { 1184 Node *nr, *nl; 1185 Node nam, nod1; 1186 1187 if(n->dodata == 0) 1188 goto no; 1189 1190 nr = n->right; 1191 nl = n->left; 1192 if(nr == N) { 1193 if(!stataddr(&nam, nl)) 1194 goto no; 1195 if(nam.class != PEXTERN) 1196 goto no; 1197 goto yes; 1198 } 1199 1200 if(nr->type == T || !eqtype(nl->type, nr->type)) 1201 goto no; 1202 1203 if(!stataddr(&nam, nl)) 1204 goto no; 1205 1206 if(nam.class != PEXTERN) 1207 goto no; 1208 1209 switch(nr->op) { 1210 default: 1211 goto no; 1212 1213 case OCONVNOP: 1214 nr = nr->left; 1215 if(nr == N || nr->op != OSLICEARR) 1216 goto no; 1217 // fall through 1218 1219 case OSLICEARR: 1220 if(nr->right->op == OKEY && nr->right->left == N && nr->right->right == N) { 1221 nr = nr->left; 1222 goto slice; 1223 } 1224 goto no; 1225 1226 case OLITERAL: 1227 break; 1228 } 1229 1230 switch(nr->type->etype) { 1231 default: 1232 goto no; 1233 1234 case TBOOL: 1235 case TINT8: 1236 case TUINT8: 1237 case TINT16: 1238 case TUINT16: 1239 case TINT32: 1240 case TUINT32: 1241 case TINT64: 1242 case TUINT64: 1243 case TINT: 1244 case TUINT: 1245 case TUINTPTR: 1246 case TPTR32: 1247 case TPTR64: 1248 case TFLOAT32: 1249 case TFLOAT64: 1250 gdata(&nam, nr, nr->type->width); 1251 break; 1252 1253 case TCOMPLEX64: 1254 case TCOMPLEX128: 1255 gdatacomplex(&nam, nr->val.u.cval); 1256 break; 1257 1258 case TSTRING: 1259 gdatastring(&nam, nr->val.u.sval); 1260 break; 1261 } 1262 1263 yes: 1264 return 1; 1265 1266 slice: 1267 gused(N); // in case the data is the dest of a goto 1268 nl = nr; 1269 if(nr == N || nr->op != OADDR) 1270 goto no; 1271 nr = nr->left; 1272 if(nr == N || nr->op != ONAME) 1273 goto no; 1274 1275 // nr is the array being converted to a slice 1276 if(nr->type == T || nr->type->etype != TARRAY || nr->type->bound < 0) 1277 goto no; 1278 1279 nam.xoffset += Array_array; 1280 gdata(&nam, nl, types[tptr]->width); 1281 1282 nam.xoffset += Array_nel-Array_array; 1283 nodconst(&nod1, types[TINT], nr->type->bound); 1284 gdata(&nam, &nod1, widthint); 1285 1286 nam.xoffset += Array_cap-Array_nel; 1287 gdata(&nam, &nod1, widthint); 1288 1289 goto yes; 1290 1291 no: 1292 if(n->dodata == 2) { 1293 dump("\ngen_as_init", n); 1294 fatal("gen_as_init couldnt make data statement"); 1295 } 1296 return 0; 1297 } 1298 1299 static int iszero(Node*); 1300 static int isvaluelit(Node*); 1301 static InitEntry* entry(InitPlan*); 1302 static void addvalue(InitPlan*, vlong, Node*, Node*); 1303 1304 static void 1305 initplan(Node *n) 1306 { 1307 InitPlan *p; 1308 Node *a; 1309 NodeList *l; 1310 1311 if(n->initplan != nil) 1312 return; 1313 p = mal(sizeof *p); 1314 n->initplan = p; 1315 switch(n->op) { 1316 default: 1317 fatal("initplan"); 1318 case OARRAYLIT: 1319 for(l=n->list; l; l=l->next) { 1320 a = l->n; 1321 if(a->op != OKEY || !smallintconst(a->left)) 1322 fatal("initplan arraylit"); 1323 addvalue(p, n->type->type->width*mpgetfix(a->left->val.u.xval), N, a->right); 1324 } 1325 break; 1326 case OSTRUCTLIT: 1327 for(l=n->list; l; l=l->next) { 1328 a = l->n; 1329 if(a->op != OKEY || a->left->type == T) 1330 fatal("initplan structlit"); 1331 addvalue(p, a->left->type->width, N, a->right); 1332 } 1333 break; 1334 case OMAPLIT: 1335 for(l=n->list; l; l=l->next) { 1336 a = l->n; 1337 if(a->op != OKEY) 1338 fatal("initplan maplit"); 1339 addvalue(p, -1, a->left, a->right); 1340 } 1341 break; 1342 } 1343 } 1344 1345 static void 1346 addvalue(InitPlan *p, vlong xoffset, Node *key, Node *n) 1347 { 1348 int i; 1349 InitPlan *q; 1350 InitEntry *e; 1351 1352 USED(key); 1353 1354 // special case: zero can be dropped entirely 1355 if(iszero(n)) { 1356 p->zero += n->type->width; 1357 return; 1358 } 1359 1360 // special case: inline struct and array (not slice) literals 1361 if(isvaluelit(n)) { 1362 initplan(n); 1363 q = n->initplan; 1364 for(i=0; i<q->len; i++) { 1365 e = entry(p); 1366 *e = q->e[i]; 1367 e->xoffset += xoffset; 1368 } 1369 return; 1370 } 1371 1372 // add to plan 1373 if(n->op == OLITERAL) 1374 p->lit += n->type->width; 1375 else 1376 p->expr += n->type->width; 1377 1378 e = entry(p); 1379 e->xoffset = xoffset; 1380 e->expr = n; 1381 } 1382 1383 static int 1384 iszero(Node *n) 1385 { 1386 NodeList *l; 1387 1388 switch(n->op) { 1389 case OLITERAL: 1390 switch(n->val.ctype) { 1391 default: 1392 dump("unexpected literal", n); 1393 fatal("iszero"); 1394 1395 case CTNIL: 1396 return 1; 1397 1398 case CTSTR: 1399 return n->val.u.sval == nil || n->val.u.sval->len == 0; 1400 1401 case CTBOOL: 1402 return n->val.u.bval == 0; 1403 1404 case CTINT: 1405 case CTRUNE: 1406 return mpcmpfixc(n->val.u.xval, 0) == 0; 1407 1408 case CTFLT: 1409 return mpcmpfltc(n->val.u.fval, 0) == 0; 1410 1411 case CTCPLX: 1412 return mpcmpfltc(&n->val.u.cval->real, 0) == 0 && mpcmpfltc(&n->val.u.cval->imag, 0) == 0; 1413 } 1414 break; 1415 case OARRAYLIT: 1416 if(isslice(n->type)) 1417 break; 1418 // fall through 1419 case OSTRUCTLIT: 1420 for(l=n->list; l; l=l->next) 1421 if(!iszero(l->n->right)) 1422 return 0; 1423 return 1; 1424 } 1425 return 0; 1426 } 1427 1428 static int 1429 isvaluelit(Node *n) 1430 { 1431 return (n->op == OARRAYLIT && isfixedarray(n->type)) || n->op == OSTRUCTLIT; 1432 } 1433 1434 static InitEntry* 1435 entry(InitPlan *p) 1436 { 1437 if(p->len >= p->cap) { 1438 if(p->cap == 0) 1439 p->cap = 4; 1440 else 1441 p->cap *= 2; 1442 p->e = realloc(p->e, p->cap*sizeof p->e[0]); 1443 if(p->e == nil) 1444 fatal("out of memory"); 1445 } 1446 return &p->e[p->len++]; 1447 }