LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2013 The Go Authors. All rights reserved. | 1 // Copyright 2013 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Garbage collector liveness bitmap generation. | 5 // Garbage collector liveness bitmap generation. |
6 | 6 |
7 // The command line flag -live causes this code to print debug information. | 7 // The command line flag -live causes this code to print debug information. |
8 // The levels are: | 8 // The levels are: |
9 // | 9 // |
10 // -live (aka -live=1): print liveness lists as code warnings at safe point
s | 10 // -live (aka -live=1): print liveness lists as code warnings at safe point
s |
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 | 576 |
577 // Sort the basic blocks by their depth first number. The | 577 // Sort the basic blocks by their depth first number. The |
578 // array is now a depth-first spanning tree with the first | 578 // array is now a depth-first spanning tree with the first |
579 // node being the root. | 579 // node being the root. |
580 arraysort(cfg, blockrpocmp); | 580 arraysort(cfg, blockrpocmp); |
581 bb = *(BasicBlock**)arrayget(cfg, 0); | 581 bb = *(BasicBlock**)arrayget(cfg, 0); |
582 | 582 |
583 // Unreachable control flow nodes are indicated by a -1 in the rpo | 583 // Unreachable control flow nodes are indicated by a -1 in the rpo |
584 // field. If we see these nodes something must have gone wrong in an | 584 // field. If we see these nodes something must have gone wrong in an |
585 // upstream compilation phase. | 585 // upstream compilation phase. |
586 » if(bb->rpo == -1) | 586 » if(bb->rpo == -1) { |
587 » » fatal("newcfg: unreferenced basic blocks"); | 587 » » print("newcfg: unreachable basic block for %P\n", bb->last); |
| 588 » » printcfg(cfg); |
| 589 » » fatal("newcfg: invalid control flow graph"); |
| 590 » } |
588 | 591 |
589 return cfg; | 592 return cfg; |
590 } | 593 } |
591 | 594 |
592 // Frees a control flow graph (an array of BasicBlock*s) and all of its leaf | 595 // Frees a control flow graph (an array of BasicBlock*s) and all of its leaf |
593 // data structures. | 596 // data structures. |
594 static void | 597 static void |
595 freecfg(Array *cfg) | 598 freecfg(Array *cfg) |
596 { | 599 { |
597 BasicBlock *bb; | 600 BasicBlock *bb; |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 BasicBlock *bb; | 952 BasicBlock *bb; |
950 int32 i; | 953 int32 i; |
951 | 954 |
952 for(i = 0; i < arraylength(lv->cfg); i++) { | 955 for(i = 0; i < arraylength(lv->cfg); i++) { |
953 bb = *(BasicBlock**)arrayget(lv->cfg, i); | 956 bb = *(BasicBlock**)arrayget(lv->cfg, i); |
954 livenessprintblock(lv, bb); | 957 livenessprintblock(lv, bb); |
955 } | 958 } |
956 } | 959 } |
957 | 960 |
958 static void | 961 static void |
959 checkauto(Node *fn, Prog *p, Node *n, char *where) | 962 checkauto(Node *fn, Prog *p, Node *n) |
960 { | 963 { |
961 » NodeList *ll; | 964 » NodeList *l; |
962 » int found; | 965 |
963 » char *fnname; | 966 » for(l = fn->dcl; l != nil; l = l->next) |
964 » char *nname; | 967 » » if(l->n->op == ONAME && l->n->class == PAUTO && l->n == n) |
965 | 968 » » » return; |
966 » found = 0; | 969 |
967 » for(ll = fn->dcl; ll != nil; ll = ll->next) { | 970 » print("checkauto %N: %N (%p; class=%d) not found in %P\n", curfn, n, n,
n->class, p); |
968 » » if(ll->n->op == ONAME && ll->n->class == PAUTO) { | 971 » for(l = fn->dcl; l != nil; l = l->next) |
969 » » » if(n == ll->n) { | 972 » » print("\t%N (%p; class=%d)\n", l->n, l->n, l->n->class); |
970 » » » » found = 1; | |
971 » » » » break; | |
972 » » » } | |
973 » » } | |
974 » } | |
975 » if(found) | |
976 » » return; | |
977 » fnname = fn->nname->sym->name ? fn->nname->sym->name : "<unknown>"; | |
978 » nname = n->sym->name ? n->sym->name : "<unknown>"; | |
979 » print("D_AUTO '%s' not found: name is '%s' function is '%s' class is %d\
n", where, nname, fnname, n->class); | |
980 » print("Here '%P'\nlooking for node %p\n", p, n); | |
981 » for(ll = fn->dcl; ll != nil; ll = ll->next) | |
982 » » print("node=%p, node->class=%d\n", (uintptr)ll->n, ll->n->class)
; | |
983 yyerror("checkauto: invariant lost"); | 973 yyerror("checkauto: invariant lost"); |
984 } | 974 } |
985 | 975 |
986 static void | 976 static void |
987 checkparam(Node *fn, Prog *p, Node *n, char *where) | 977 checkparam(Node *fn, Prog *p, Node *n) |
988 { | 978 { |
989 » NodeList *ll; | 979 » NodeList *l; |
990 » int found; | 980 » Node *a; |
991 » char *fnname; | 981 » int class; |
992 » char *nname; | |
993 | 982 |
994 if(isfunny(n)) | 983 if(isfunny(n)) |
995 return; | 984 return; |
996 » found = 0; | 985 » for(l = fn->dcl; l != nil; l = l->next) { |
997 » for(ll = fn->dcl; ll != nil; ll = ll->next) { | 986 » » a = l->n; |
998 » » if(ll->n->op == ONAME && ((ll->n->class & ~PHEAP) == PPARAM || | 987 » » class = l->n->class & ~PHEAP; |
999 » » » » » (ll->n->class & ~PHEAP) == PPARAMOUT))
{ | 988 » » if(a->op == ONAME && (class == PPARAM || class == PPARAMOUT) &&
a == n) |
1000 » » » if(n == ll->n) { | 989 » » » return; |
1001 » » » » found = 1; | 990 » } |
1002 » » » » break; | 991 |
1003 » » » } | 992 » print("checkparam %N: %N (%p; class=%d) not found in %P\n", curfn, n, n,
n->class, p); |
1004 » » } | 993 » for(l = fn->dcl; l != nil; l = l->next) |
1005 » } | 994 » » print("\t%N (%p; class=%d)\n", l->n, l->n, l->n->class); |
1006 » if(found) | |
1007 » » return; | |
1008 » if(n->sym) { | |
1009 » » fnname = fn->nname->sym->name ? fn->nname->sym->name : "<unknown
>"; | |
1010 » » nname = n->sym->name ? n->sym->name : "<unknown>"; | |
1011 » » print("D_PARAM '%s' not found: name='%s' function='%s' class is
%d\n", where, nname, fnname, n->class); | |
1012 » » print("Here '%P'\nlooking for node %p\n", p, n); | |
1013 » » for(ll = fn->dcl; ll != nil; ll = ll->next) | |
1014 » » » print("node=%p, node->class=%d\n", ll->n, ll->n->class); | |
1015 » } | |
1016 yyerror("checkparam: invariant lost"); | 995 yyerror("checkparam: invariant lost"); |
1017 } | 996 } |
1018 | 997 |
1019 static void | 998 static void |
1020 checkprog(Node *fn, Prog *p) | 999 checkprog(Node *fn, Prog *p) |
1021 { | 1000 { |
1022 if(p->from.type == D_AUTO) | 1001 if(p->from.type == D_AUTO) |
1023 » » checkauto(fn, p, p->from.node, "from"); | 1002 » » checkauto(fn, p, p->from.node); |
1024 if(p->from.type == D_PARAM) | 1003 if(p->from.type == D_PARAM) |
1025 » » checkparam(fn, p, p->from.node, "from"); | 1004 » » checkparam(fn, p, p->from.node); |
1026 if(p->to.type == D_AUTO) | 1005 if(p->to.type == D_AUTO) |
1027 » » checkauto(fn, p, p->to.node, "to"); | 1006 » » checkauto(fn, p, p->to.node); |
1028 if(p->to.type == D_PARAM) | 1007 if(p->to.type == D_PARAM) |
1029 » » checkparam(fn, p, p->to.node, "to"); | 1008 » » checkparam(fn, p, p->to.node); |
1030 } | 1009 } |
1031 | 1010 |
1032 // Check instruction invariants. We assume that the nodes corresponding to the | 1011 // Check instruction invariants. We assume that the nodes corresponding to the |
1033 // sources and destinations of memory operations will be declared in the | 1012 // sources and destinations of memory operations will be declared in the |
1034 // function. This is not strictly true, as is the case for the so-called funny | 1013 // function. This is not strictly true, as is the case for the so-called funny |
1035 // nodes and there are special cases to skip over that stuff. The analysis will | 1014 // nodes and there are special cases to skip over that stuff. The analysis will |
1036 // fail if this invariant blindly changes. | 1015 // fail if this invariant blindly changes. |
1037 static void | 1016 static void |
1038 checkptxt(Node *fn, Prog *firstp) | 1017 checkptxt(Node *fn, Prog *firstp) |
1039 { | 1018 { |
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1602 printvars("livein", livein, lv->vars); | 1581 printvars("livein", livein, lv->vars); |
1603 printvars("liveout", liveout, lv->vars); | 1582 printvars("liveout", liveout, lv->vars); |
1604 } | 1583 } |
1605 if(issafepoint(p)) { | 1584 if(issafepoint(p)) { |
1606 // Found an interesting instruction, record the | 1585 // Found an interesting instruction, record the |
1607 // corresponding liveness information.·· | 1586 // corresponding liveness information.·· |
1608 ································ | 1587 ································ |
1609 // Useful sanity check: on entry to the function
, | 1588 // Useful sanity check: on entry to the function
, |
1610 // the only things that can possibly be live are
the | 1589 // the only things that can possibly be live are
the |
1611 // input parameters. | 1590 // input parameters. |
1612 » » » » if(0 && p->as == ATEXT) { | 1591 » » » » if(p->as == ATEXT) { |
1613 for(j = 0; j < liveout->n; j++) { | 1592 for(j = 0; j < liveout->n; j++) { |
1614 if(!bvget(liveout, j)) | 1593 if(!bvget(liveout, j)) |
1615 continue; | 1594 continue; |
1616 n = *(Node**)arrayget(lv->vars,
j); | 1595 n = *(Node**)arrayget(lv->vars,
j); |
1617 if(n->class != PPARAM) | 1596 if(n->class != PPARAM) |
1618 » » » » » » » yyerrorl(p->lineno, "int
ernal error: %N %N recorded as live on entry", curfn->nname, n); | 1597 » » » » » » » yyerrorl(p->lineno, "int
ernal error: %N %lN recorded as live on entry", curfn->nname, n); |
1619 } | 1598 } |
1620 } | 1599 } |
1621 | 1600 |
1622 // Record live pointers. | 1601 // Record live pointers. |
1623 args = *(Bvec**)arrayget(lv->argslivepointers, p
os); | 1602 args = *(Bvec**)arrayget(lv->argslivepointers, p
os); |
1624 locals = *(Bvec**)arrayget(lv->livepointers, pos
); | 1603 locals = *(Bvec**)arrayget(lv->livepointers, pos
); |
1625 twobitlivepointermap(lv, liveout, lv->vars, args
, locals); | 1604 twobitlivepointermap(lv, liveout, lv->vars, args
, locals); |
1626 | 1605 |
1627 // Show live pointer bitmaps. | 1606 // Show live pointer bitmaps. |
1628 // We're interpreting the args and locals bitmap
instead of liveout so that we | 1607 // We're interpreting the args and locals bitmap
instead of liveout so that we |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1923 if(deadsym != nil) | 1902 if(deadsym != nil) |
1924 twobitwritesymbol(lv->deadvalues, deadsym, nil); | 1903 twobitwritesymbol(lv->deadvalues, deadsym, nil); |
1925 | 1904 |
1926 // Free everything. | 1905 // Free everything. |
1927 freeliveness(lv); | 1906 freeliveness(lv); |
1928 arrayfree(vars); | 1907 arrayfree(vars); |
1929 freecfg(cfg); | 1908 freecfg(cfg); |
1930 ········ | 1909 ········ |
1931 debuglive -= debugdelta; | 1910 debuglive -= debugdelta; |
1932 } | 1911 } |
LEFT | RIGHT |