PageRenderTime 52ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/IronPython_Main/Runtime/Tests/LinqDlrTests/testenv/perl/lib/B/Bblock.pm

#
Perl | 180 lines | 141 code | 27 blank | 12 comment | 20 complexity | e9f93b2821faeef698ea7976e2320ffa MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  1. package B::Bblock;
  2. use Exporter ();
  3. @ISA = "Exporter";
  4. @EXPORT_OK = qw(find_leaders);
  5. use B qw(peekop walkoptree walkoptree_exec
  6. main_root main_start svref_2object
  7. OPf_SPECIAL OPf_STACKED );
  8. use B::Terse;
  9. use strict;
  10. my $bblock;
  11. my @bblock_ends;
  12. sub mark_leader {
  13. my $op = shift;
  14. if ($$op) {
  15. $bblock->{$$op} = $op;
  16. }
  17. }
  18. sub remove_sortblock{
  19. foreach (keys %$bblock){
  20. my $leader=$$bblock{$_};
  21. delete $$bblock{$_} if( $leader == 0);
  22. }
  23. }
  24. sub find_leaders {
  25. my ($root, $start) = @_;
  26. $bblock = {};
  27. mark_leader($start) if ( ref $start ne "B::NULL" );
  28. walkoptree($root, "mark_if_leader") if ((ref $root) ne "B::NULL") ;
  29. remove_sortblock();
  30. return $bblock;
  31. }
  32. # Debugging
  33. sub walk_bblocks {
  34. my ($root, $start) = @_;
  35. my ($op, $lastop, $leader, $bb);
  36. $bblock = {};
  37. mark_leader($start);
  38. walkoptree($root, "mark_if_leader");
  39. my @leaders = values %$bblock;
  40. while ($leader = shift @leaders) {
  41. $lastop = $leader;
  42. $op = $leader->next;
  43. while ($$op && !exists($bblock->{$$op})) {
  44. $bblock->{$$op} = $leader;
  45. $lastop = $op;
  46. $op = $op->next;
  47. }
  48. push(@bblock_ends, [$leader, $lastop]);
  49. }
  50. foreach $bb (@bblock_ends) {
  51. ($leader, $lastop) = @$bb;
  52. printf "%s .. %s\n", peekop($leader), peekop($lastop);
  53. for ($op = $leader; $$op != $$lastop; $op = $op->next) {
  54. printf " %s\n", peekop($op);
  55. }
  56. printf " %s\n", peekop($lastop);
  57. }
  58. print "-------\n";
  59. walkoptree_exec($start, "terse");
  60. }
  61. sub walk_bblocks_obj {
  62. my $cvref = shift;
  63. my $cv = svref_2object($cvref);
  64. walk_bblocks($cv->ROOT, $cv->START);
  65. }
  66. sub B::OP::mark_if_leader {}
  67. sub B::COP::mark_if_leader {
  68. my $op = shift;
  69. if ($op->label) {
  70. mark_leader($op);
  71. }
  72. }
  73. sub B::LOOP::mark_if_leader {
  74. my $op = shift;
  75. mark_leader($op->next);
  76. mark_leader($op->nextop);
  77. mark_leader($op->redoop);
  78. mark_leader($op->lastop->next);
  79. }
  80. sub B::LOGOP::mark_if_leader {
  81. my $op = shift;
  82. my $opname = $op->name;
  83. mark_leader($op->next);
  84. if ($opname eq "entertry") {
  85. mark_leader($op->other->next);
  86. } else {
  87. mark_leader($op->other);
  88. }
  89. }
  90. sub B::LISTOP::mark_if_leader {
  91. my $op = shift;
  92. my $first=$op->first;
  93. $first=$first->next while ($first->name eq "null");
  94. mark_leader($op->first) unless (exists( $bblock->{$$first}));
  95. mark_leader($op->next);
  96. if ($op->name eq "sort" and $op->flags & OPf_SPECIAL
  97. and $op->flags & OPf_STACKED){
  98. my $root=$op->first->sibling->first;
  99. my $leader=$root->first;
  100. $bblock->{$$leader} = 0;
  101. }
  102. }
  103. sub B::PMOP::mark_if_leader {
  104. my $op = shift;
  105. if ($op->name ne "pushre") {
  106. my $replroot = $op->pmreplroot;
  107. if ($$replroot) {
  108. mark_leader($replroot);
  109. mark_leader($op->next);
  110. mark_leader($op->pmreplstart);
  111. }
  112. }
  113. }
  114. # PMOP stuff omitted
  115. sub compile {
  116. my @options = @_;
  117. B::clearsym();
  118. if (@options) {
  119. return sub {
  120. my $objname;
  121. foreach $objname (@options) {
  122. $objname = "main::$objname" unless $objname =~ /::/;
  123. eval "walk_bblocks_obj(\\&$objname)";
  124. die "walk_bblocks_obj(\\&$objname) failed: $@" if $@;
  125. }
  126. }
  127. } else {
  128. return sub { walk_bblocks(main_root, main_start) };
  129. }
  130. }
  131. # Basic block leaders:
  132. # Any COP (pp_nextstate) with a non-NULL label
  133. # [The op after a pp_enter] Omit
  134. # [The op after a pp_entersub. Don't count this one.]
  135. # The ops pointed at by nextop, redoop and lastop->op_next of a LOOP
  136. # The ops pointed at by op_next and op_other of a LOGOP, except
  137. # for pp_entertry which has op_next and op_other->op_next
  138. # The op pointed at by op_pmreplstart of a PMOP
  139. # The op pointed at by op_other->op_pmreplstart of pp_substcont?
  140. # [The op after a pp_return] Omit
  141. 1;
  142. __END__
  143. =head1 NAME
  144. B::Bblock - Walk basic blocks
  145. =head1 SYNOPSIS
  146. perl -MO=Bblock[,OPTIONS] foo.pl
  147. =head1 DESCRIPTION
  148. This module is used by the B::CC back end. It walks "basic blocks".
  149. A basic block is a series of operations which is known to execute from
  150. start to finish, with no possiblity of branching or halting.
  151. =head1 AUTHOR
  152. Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
  153. =cut