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