laser 0.7.0.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +14 -0
- data/LICENSE +661 -0
- data/README.md +158 -0
- data/Rakefile +104 -0
- data/VERSION +1 -0
- data/bin/laser +7 -0
- data/design_docs/goals.md +57 -0
- data/design_docs/object_regex.md +426 -0
- data/design_docs/type_annotations.md +80 -0
- data/ext/laser/BasicBlock.cpp +572 -0
- data/ext/laser/BasicBlock.h +118 -0
- data/ext/laser/extconf.rb +3 -0
- data/features/laser.feature +25 -0
- data/features/step_definitions/laser_steps.rb +39 -0
- data/features/support/env.rb +14 -0
- data/features/support/testdata/1_input +1 -0
- data/features/support/testdata/1_output +1 -0
- data/features/support/testdata/2_input +4 -0
- data/features/support/testdata/2_output +4 -0
- data/features/support/testdata/3_input +8 -0
- data/features/support/testdata/3_output +11 -0
- data/features/support/testdata/4_input +5 -0
- data/features/support/testdata/4_output +5 -0
- data/features/support/testdata/5_input +13 -0
- data/laser.gemspec +382 -0
- data/lib/laser.rb +98 -0
- data/lib/laser/analysis/annotations.rb +95 -0
- data/lib/laser/analysis/annotations/annotation_config.yaml +3 -0
- data/lib/laser/analysis/annotations/comment_attachment_annotation.rb +66 -0
- data/lib/laser/analysis/annotations/node_pointers_annotation.rb +36 -0
- data/lib/laser/analysis/annotations/runtime_annotation.rb +55 -0
- data/lib/laser/analysis/argument_expansion.rb +132 -0
- data/lib/laser/analysis/arity.rb +34 -0
- data/lib/laser/analysis/bindings.rb +144 -0
- data/lib/laser/analysis/bootstrap/bootstrap.rb +298 -0
- data/lib/laser/analysis/bootstrap/laser_class.rb +106 -0
- data/lib/laser/analysis/bootstrap/laser_method.rb +255 -0
- data/lib/laser/analysis/bootstrap/laser_module.rb +403 -0
- data/lib/laser/analysis/bootstrap/laser_module_copy.rb +74 -0
- data/lib/laser/analysis/bootstrap/laser_object.rb +69 -0
- data/lib/laser/analysis/bootstrap/laser_proc.rb +150 -0
- data/lib/laser/analysis/bootstrap/laser_singleton_class.rb +44 -0
- data/lib/laser/analysis/comments.rb +35 -0
- data/lib/laser/analysis/control_flow.rb +28 -0
- data/lib/laser/analysis/control_flow/alias_analysis.rb +31 -0
- data/lib/laser/analysis/control_flow/basic_block.rb +105 -0
- data/lib/laser/analysis/control_flow/cfg_builder.rb +2505 -0
- data/lib/laser/analysis/control_flow/cfg_instruction.rb +190 -0
- data/lib/laser/analysis/control_flow/constant_propagation.rb +742 -0
- data/lib/laser/analysis/control_flow/control_flow_graph.rb +370 -0
- data/lib/laser/analysis/control_flow/lifetime_analysis.rb +91 -0
- data/lib/laser/analysis/control_flow/method_call_search.rb +26 -0
- data/lib/laser/analysis/control_flow/raise_properties.rb +25 -0
- data/lib/laser/analysis/control_flow/simulation.rb +385 -0
- data/lib/laser/analysis/control_flow/static_single_assignment.rb +185 -0
- data/lib/laser/analysis/control_flow/unreachability_analysis.rb +57 -0
- data/lib/laser/analysis/control_flow/unused_variables.rb +91 -0
- data/lib/laser/analysis/control_flow/yield_properties.rb +103 -0
- data/lib/laser/analysis/errors.rb +131 -0
- data/lib/laser/analysis/laser_utils.rb +18 -0
- data/lib/laser/analysis/lexical_analysis.rb +172 -0
- data/lib/laser/analysis/method_call.rb +68 -0
- data/lib/laser/analysis/protocol_registry.rb +30 -0
- data/lib/laser/analysis/scope.rb +118 -0
- data/lib/laser/analysis/sexp.rb +159 -0
- data/lib/laser/analysis/sexp_analysis.rb +40 -0
- data/lib/laser/analysis/sexp_extensions/constant_extraction.rb +115 -0
- data/lib/laser/analysis/sexp_extensions/source_location.rb +164 -0
- data/lib/laser/analysis/sexp_extensions/type_inference.rb +47 -0
- data/lib/laser/analysis/signature.rb +76 -0
- data/lib/laser/analysis/special_methods/send.rb +67 -0
- data/lib/laser/analysis/unused_methods.rb +21 -0
- data/lib/laser/analysis/visitor.rb +141 -0
- data/lib/laser/annotation_parser/annotations.treetop +126 -0
- data/lib/laser/annotation_parser/annotations_parser.rb +748 -0
- data/lib/laser/annotation_parser/class_annotations.treetop +82 -0
- data/lib/laser/annotation_parser/class_annotations_parser.rb +654 -0
- data/lib/laser/annotation_parser/overload.treetop +24 -0
- data/lib/laser/annotation_parser/overload_parser.rb +167 -0
- data/lib/laser/annotation_parser/parsers.rb +6 -0
- data/lib/laser/annotation_parser/structural.treetop +37 -0
- data/lib/laser/annotation_parser/structural_parser.rb +406 -0
- data/lib/laser/annotation_parser/useful_parsers.treetop +47 -0
- data/lib/laser/annotation_parser/useful_parsers_parser.rb +674 -0
- data/lib/laser/rake/task.rb +46 -0
- data/lib/laser/runner.rb +189 -0
- data/lib/laser/scanner.rb +169 -0
- data/lib/laser/standard_library/_thread.rb +110 -0
- data/lib/laser/standard_library/abbrev.rb +103 -0
- data/lib/laser/standard_library/array.rb +418 -0
- data/lib/laser/standard_library/base64.rb +91 -0
- data/lib/laser/standard_library/basic_object.rb +55 -0
- data/lib/laser/standard_library/benchmark.rb +556 -0
- data/lib/laser/standard_library/bignum.rb +185 -0
- data/lib/laser/standard_library/cgi.rb +275 -0
- data/lib/laser/standard_library/cgi/cookie.rb +147 -0
- data/lib/laser/standard_library/cgi/core.rb +791 -0
- data/lib/laser/standard_library/cgi/html.rb +1021 -0
- data/lib/laser/standard_library/cgi/session.rb +537 -0
- data/lib/laser/standard_library/cgi/session/pstore.rb +111 -0
- data/lib/laser/standard_library/cgi/util.rb +188 -0
- data/lib/laser/standard_library/class_definitions.rb +333 -0
- data/lib/laser/standard_library/comparable.rb +125 -0
- data/lib/laser/standard_library/complex.rb +162 -0
- data/lib/laser/standard_library/enumerable.rb +178 -0
- data/lib/laser/standard_library/exceptions.rb +135 -0
- data/lib/laser/standard_library/fixnum.rb +188 -0
- data/lib/laser/standard_library/float.rb +180 -0
- data/lib/laser/standard_library/hash.rb +237 -0
- data/lib/laser/standard_library/integer.rb +123 -0
- data/lib/laser/standard_library/laser_magic.rb +7 -0
- data/lib/laser/standard_library/nil_false_true.rb +113 -0
- data/lib/laser/standard_library/numbers.rb +192 -0
- data/lib/laser/standard_library/proc.rb +31 -0
- data/lib/laser/standard_library/set.rb +1348 -0
- data/lib/laser/standard_library/string.rb +666 -0
- data/lib/laser/standard_library/stringio.rb +2 -0
- data/lib/laser/standard_library/symbol.rb +125 -0
- data/lib/laser/standard_library/tsort.rb +242 -0
- data/lib/laser/support/acts_as_struct.rb +66 -0
- data/lib/laser/support/frequency.rb +55 -0
- data/lib/laser/support/inheritable_attributes.rb +145 -0
- data/lib/laser/support/module_extensions.rb +94 -0
- data/lib/laser/support/placeholder_object.rb +13 -0
- data/lib/laser/third_party/rgl/adjacency.rb +221 -0
- data/lib/laser/third_party/rgl/base.rb +228 -0
- data/lib/laser/third_party/rgl/bidirectional.rb +39 -0
- data/lib/laser/third_party/rgl/condensation.rb +47 -0
- data/lib/laser/third_party/rgl/connected_components.rb +138 -0
- data/lib/laser/third_party/rgl/control_flow.rb +170 -0
- data/lib/laser/third_party/rgl/depth_first_spanning_tree.rb +37 -0
- data/lib/laser/third_party/rgl/dominators.rb +124 -0
- data/lib/laser/third_party/rgl/dot.rb +93 -0
- data/lib/laser/third_party/rgl/graphxml.rb +51 -0
- data/lib/laser/third_party/rgl/implicit.rb +174 -0
- data/lib/laser/third_party/rgl/mutable.rb +117 -0
- data/lib/laser/third_party/rgl/rdot.rb +445 -0
- data/lib/laser/third_party/rgl/topsort.rb +72 -0
- data/lib/laser/third_party/rgl/transitivity.rb +180 -0
- data/lib/laser/third_party/rgl/traversal.rb +348 -0
- data/lib/laser/types/types.rb +433 -0
- data/lib/laser/version.rb +14 -0
- data/lib/laser/warning.rb +149 -0
- data/lib/laser/warning_sets/default.yml +13 -0
- data/lib/laser/warnings/assignment_in_condition.rb +20 -0
- data/lib/laser/warnings/comment_spacing.rb +31 -0
- data/lib/laser/warnings/extra_blank_lines.rb +30 -0
- data/lib/laser/warnings/extra_whitespace.rb +16 -0
- data/lib/laser/warnings/hash_symbol_18_warning.rb +63 -0
- data/lib/laser/warnings/hash_symbol_19_warning.rb +29 -0
- data/lib/laser/warnings/line_length.rb +115 -0
- data/lib/laser/warnings/misaligned_unindentation.rb +17 -0
- data/lib/laser/warnings/operator_spacing.rb +68 -0
- data/lib/laser/warnings/parens_on_declaration.rb +30 -0
- data/lib/laser/warnings/rescue_exception.rb +42 -0
- data/lib/laser/warnings/semicolon.rb +25 -0
- data/lib/laser/warnings/sexp_errors.rb +24 -0
- data/lib/laser/warnings/uncalled_method_warning.rb +7 -0
- data/lib/laser/warnings/useless_double_quotes.rb +38 -0
- data/spec/analysis_specs/annotations_spec.rb +47 -0
- data/spec/analysis_specs/annotations_specs/comment_attachment_spec.rb +68 -0
- data/spec/analysis_specs/annotations_specs/node_pointers_annotation_spec.rb +90 -0
- data/spec/analysis_specs/annotations_specs/runtime_annotation_spec.rb +135 -0
- data/spec/analysis_specs/annotations_specs/spec_helper.rb +33 -0
- data/spec/analysis_specs/argument_expansion_spec.rb +113 -0
- data/spec/analysis_specs/bindings_spec.rb +36 -0
- data/spec/analysis_specs/comment_spec.rb +93 -0
- data/spec/analysis_specs/control_flow_specs/cfg_instruction_spec.rb +111 -0
- data/spec/analysis_specs/control_flow_specs/constant_propagation_spec.rb +560 -0
- data/spec/analysis_specs/control_flow_specs/control_flow_graph_spec.rb +5 -0
- data/spec/analysis_specs/control_flow_specs/raise_properties_spec.rb +310 -0
- data/spec/analysis_specs/control_flow_specs/raise_type_inference_spec.rb +301 -0
- data/spec/analysis_specs/control_flow_specs/return_type_inference_spec.rb +431 -0
- data/spec/analysis_specs/control_flow_specs/simulation_spec.rb +158 -0
- data/spec/analysis_specs/control_flow_specs/spec_helper.rb +110 -0
- data/spec/analysis_specs/control_flow_specs/tuple_misuse_inference_spec.rb +125 -0
- data/spec/analysis_specs/control_flow_specs/unreachability_analysis_spec.rb +76 -0
- data/spec/analysis_specs/control_flow_specs/unused_variable_spec.rb +99 -0
- data/spec/analysis_specs/control_flow_specs/yield_properties_spec.rb +372 -0
- data/spec/analysis_specs/error_spec.rb +30 -0
- data/spec/analysis_specs/laser_class_spec.rb +322 -0
- data/spec/analysis_specs/lexical_analysis_spec.rb +184 -0
- data/spec/analysis_specs/protocol_registry_spec.rb +63 -0
- data/spec/analysis_specs/scope_annotation_spec.rb +1013 -0
- data/spec/analysis_specs/scope_spec.rb +126 -0
- data/spec/analysis_specs/sexp_analysis_spec.rb +30 -0
- data/spec/analysis_specs/sexp_extension_specs/constant_extraction_spec.rb +309 -0
- data/spec/analysis_specs/sexp_extension_specs/source_location_spec.rb +231 -0
- data/spec/analysis_specs/sexp_extension_specs/spec_helper.rb +1 -0
- data/spec/analysis_specs/sexp_extension_specs/type_inference_spec.rb +252 -0
- data/spec/analysis_specs/sexp_spec.rb +167 -0
- data/spec/analysis_specs/spec_helper.rb +27 -0
- data/spec/analysis_specs/unused_methods_spec.rb +65 -0
- data/spec/analysis_specs/visitor_spec.rb +64 -0
- data/spec/annotation_parser_specs/annotations_parser_spec.rb +89 -0
- data/spec/annotation_parser_specs/class_annotation_parser_spec.rb +120 -0
- data/spec/annotation_parser_specs/overload_parser_spec.rb +39 -0
- data/spec/annotation_parser_specs/parsers_spec.rb +14 -0
- data/spec/annotation_parser_specs/spec_helper.rb +1 -0
- data/spec/annotation_parser_specs/structural_parser_spec.rb +67 -0
- data/spec/laser_spec.rb +14 -0
- data/spec/rake_specs/spec_helper.rb +1 -0
- data/spec/rake_specs/task_spec.rb +67 -0
- data/spec/runner_spec.rb +207 -0
- data/spec/scanner_spec.rb +75 -0
- data/spec/spec_helper.rb +121 -0
- data/spec/standard_library/exceptions_spec.rb +19 -0
- data/spec/standard_library/globals_spec.rb +14 -0
- data/spec/standard_library/set_spec.rb +31 -0
- data/spec/standard_library/spec_helper.rb +1 -0
- data/spec/standard_library/standard_library_spec.rb +302 -0
- data/spec/support_specs/acts_as_struct_spec.rb +94 -0
- data/spec/support_specs/frequency_spec.rb +23 -0
- data/spec/support_specs/module_extensions_spec.rb +117 -0
- data/spec/support_specs/spec_helper.rb +1 -0
- data/spec/type_specs/spec_helper.rb +1 -0
- data/spec/type_specs/types_spec.rb +133 -0
- data/spec/warning_spec.rb +95 -0
- data/spec/warning_specs/assignment_in_condition_spec.rb +68 -0
- data/spec/warning_specs/comment_spacing_spec.rb +65 -0
- data/spec/warning_specs/extra_blank_lines_spec.rb +70 -0
- data/spec/warning_specs/extra_whitespace_spec.rb +33 -0
- data/spec/warning_specs/hash_symbol_18_warning_spec.rb +89 -0
- data/spec/warning_specs/hash_symbol_19_warning_spec.rb +63 -0
- data/spec/warning_specs/line_length_spec.rb +173 -0
- data/spec/warning_specs/misaligned_unindentation_spec.rb +35 -0
- data/spec/warning_specs/operator_spacing_spec.rb +104 -0
- data/spec/warning_specs/parens_on_declaration_spec.rb +57 -0
- data/spec/warning_specs/rescue_exception_spec.rb +105 -0
- data/spec/warning_specs/semicolon_spec.rb +58 -0
- data/spec/warning_specs/spec_helper.rb +1 -0
- data/spec/warning_specs/useless_double_quotes_spec.rb +74 -0
- data/status_reports/2010/12/2010-12-14.md +163 -0
- data/status_reports/2010/12/2010-12-23.md +298 -0
- data/status_reports/2010/12/2010-12-24.md +6 -0
- data/test/third_party_tests/rgl_tests/TestComponents.rb +65 -0
- data/test/third_party_tests/rgl_tests/TestCycles.rb +61 -0
- data/test/third_party_tests/rgl_tests/TestDirectedGraph.rb +125 -0
- data/test/third_party_tests/rgl_tests/TestDot.rb +18 -0
- data/test/third_party_tests/rgl_tests/TestEdge.rb +34 -0
- data/test/third_party_tests/rgl_tests/TestGraph.rb +71 -0
- data/test/third_party_tests/rgl_tests/TestGraphXML.rb +57 -0
- data/test/third_party_tests/rgl_tests/TestImplicit.rb +52 -0
- data/test/third_party_tests/rgl_tests/TestRdot.rb +863 -0
- data/test/third_party_tests/rgl_tests/TestTransitivity.rb +129 -0
- data/test/third_party_tests/rgl_tests/TestTraversal.rb +220 -0
- data/test/third_party_tests/rgl_tests/TestUnDirectedGraph.rb +102 -0
- data/test/third_party_tests/rgl_tests/examples/north/Graph.log +128 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.0.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.1.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.11.graphml +31 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.12.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.13.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.14.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.15.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.16.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.17.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.19.graphml +37 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.2.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.20.graphml +38 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.22.graphml +43 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.24.graphml +30 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.25.graphml +45 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.27.graphml +38 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.28.graphml +30 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.29.graphml +38 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.3.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.30.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.31.graphml +42 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.34.graphml +42 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.37.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.38.graphml +38 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.39.graphml +36 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.4.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.40.graphml +37 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.41.graphml +37 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.42.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.45.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.46.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.5.graphml +31 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.50.graphml +30 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.56.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.57.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.58.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.6.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.60.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.61.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.62.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.68.graphml +30 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.69.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.7.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.70.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.71.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.72.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.74.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.75.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.78.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.79.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.8.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.80.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.82.graphml +35 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.83.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.85.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.86.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.88.graphml +37 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.89.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.9.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.90.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.91.graphml +31 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.92.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.93.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.94.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.12.8.graphml +40 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.14.9.graphml +36 -0
- data/test/third_party_tests/rgl_tests/test_helper.rb +7 -0
- data/test/third_party_tests/test_inheritable_attributes.rb +187 -0
- metadata +470 -0
@@ -0,0 +1,370 @@
|
|
1
|
+
require 'laser/third_party/rgl/adjacency'
|
2
|
+
require 'laser/third_party/rgl/transitivity'
|
3
|
+
require 'laser/third_party/rgl/dominators'
|
4
|
+
module Laser
|
5
|
+
module Analysis
|
6
|
+
module ControlFlow
|
7
|
+
class ControlFlowGraph < RGL::ControlFlowGraph
|
8
|
+
include ConstantPropagation
|
9
|
+
include LifetimeAnalysis
|
10
|
+
include StaticSingleAssignment
|
11
|
+
include UnusedVariables
|
12
|
+
include UnreachabilityAnalysis
|
13
|
+
include AliasAnalysis
|
14
|
+
include YieldProperties
|
15
|
+
include MethodCallSearch
|
16
|
+
include RaiseProperties
|
17
|
+
include Simulation
|
18
|
+
|
19
|
+
RETURN_POSTDOMINATOR_NAME = 'Return'
|
20
|
+
YIELD_POSTDOMINATOR_NAME = 'YieldWithoutBlock'
|
21
|
+
EXCEPTION_POSTDOMINATOR_NAME = 'UncaughtException'
|
22
|
+
FAILURE_POSTDOMINATOR_NAME = 'Failure'
|
23
|
+
|
24
|
+
attr_accessor :root, :block_register, :final_exception, :final_return
|
25
|
+
attr_reader :formals, :uses, :definition, :constants, :live, :globals
|
26
|
+
attr_reader :yield_type, :raise_frequency, :in_ssa, :yield_arity
|
27
|
+
attr_reader :self_type, :formal_types, :block_type
|
28
|
+
attr_reader :all_cached_variables
|
29
|
+
# postdominator blocks for: all non-failed-yield exceptions, yield-failing
|
30
|
+
# exceptions, and all failure types.
|
31
|
+
|
32
|
+
# Initializes the control flow graph, potentially with a list of argument
|
33
|
+
# bindings. Those bindings will almost always be extracted from parsing
|
34
|
+
# an argument list of a method or block.
|
35
|
+
#
|
36
|
+
# formal_arguments: [ArgumentBinding]
|
37
|
+
def initialize(formal_arguments = [])
|
38
|
+
@in_ssa = false
|
39
|
+
@self_type = nil
|
40
|
+
@formal_types = nil
|
41
|
+
@block_type = nil
|
42
|
+
@block_register = nil
|
43
|
+
@all_cached_variables = Set.new
|
44
|
+
@live = Hash.new { |hash, temp| hash[temp] = Set.new }
|
45
|
+
@constants = {}
|
46
|
+
@globals = Set.new
|
47
|
+
@name_stack = Hash.new { |hash, temp| hash[temp] = [] }
|
48
|
+
@name_count = Hash.new { |hash, temp| hash[temp] = 0 }
|
49
|
+
@formals = formal_arguments
|
50
|
+
@yield_type = nil
|
51
|
+
@yield_arity = nil#Set.new([Arity::ANY])
|
52
|
+
@raise_frequency = Frequency::MAYBE
|
53
|
+
super()
|
54
|
+
end
|
55
|
+
|
56
|
+
def dup
|
57
|
+
copy = self.class.new
|
58
|
+
copy.initialize_dup(self)
|
59
|
+
copy
|
60
|
+
end
|
61
|
+
|
62
|
+
def initialize_dup(source)
|
63
|
+
@root = source.root
|
64
|
+
@in_ssa = source.in_ssa
|
65
|
+
@self_type = source.self_type
|
66
|
+
@formal_types = source.formal_types
|
67
|
+
@block_type = source.block_type
|
68
|
+
# we'll be duplicating temporaries, and since we need to know how
|
69
|
+
# our source data about temps (defs, uses, constants...) corresponds
|
70
|
+
# the duplicated temps, we'll need a hash to look them up.
|
71
|
+
temp_lookup = { Bootstrap::VISIBILITY_STACK => Bootstrap::VISIBILITY_STACK }
|
72
|
+
block_lookup = { source.enter => @enter, source.exit => @exit }
|
73
|
+
insn_lookup = Hash.new
|
74
|
+
# copy all vars defined in the body
|
75
|
+
source.all_cached_variables.each do |k|
|
76
|
+
copy = k.deep_dup
|
77
|
+
temp_lookup[k] = copy
|
78
|
+
@all_cached_variables << copy
|
79
|
+
end
|
80
|
+
self.block_register = temp_lookup[source.block_register]
|
81
|
+
self.final_exception = temp_lookup[source.final_exception]
|
82
|
+
self.final_return = temp_lookup[source.final_return]
|
83
|
+
# copy all formals and their mapping to initial bindings
|
84
|
+
@formals = source.formals.map do |formal|
|
85
|
+
temp_lookup[formal] = formal.deep_dup
|
86
|
+
end
|
87
|
+
|
88
|
+
new_blocks = source.vertices.reject { |v| TerminalBasicBlock === v }
|
89
|
+
new_blocks.map! do |block|
|
90
|
+
copy = block.duplicate_for_graph_copy(temp_lookup, insn_lookup)
|
91
|
+
block_lookup[block] = copy
|
92
|
+
copy
|
93
|
+
end
|
94
|
+
|
95
|
+
new_blocks.each do |new_block|
|
96
|
+
add_vertex new_block
|
97
|
+
end
|
98
|
+
source.each_edge do |u, v|
|
99
|
+
add_edge(block_lookup[u], block_lookup[v], u.get_flags(v))
|
100
|
+
end
|
101
|
+
|
102
|
+
# computed stuff we shouldn't lose:
|
103
|
+
# @globals
|
104
|
+
# @constants
|
105
|
+
# @live
|
106
|
+
# @formal_map
|
107
|
+
temp_lookup.each do |old, new|
|
108
|
+
new.definition = insn_lookup[old.definition]
|
109
|
+
new.uses = Set.new(old.uses.map { |insn| insn_lookup[insn] })
|
110
|
+
end
|
111
|
+
source.globals.each do |global|
|
112
|
+
@globals.add temp_lookup[global]
|
113
|
+
end
|
114
|
+
source.constants.each do |temp, value|
|
115
|
+
# no need to dup value, as these constants *MUST NOT* be mutated.
|
116
|
+
@constants[temp_lookup[temp]] = value
|
117
|
+
end
|
118
|
+
source.live.each do |temp, blocks|
|
119
|
+
@live[temp_lookup[temp]] = Set.new(blocks.map { |block| block_lookup[block] })
|
120
|
+
end
|
121
|
+
# Tiny hope this speeds anything up
|
122
|
+
temp_lookup.clear
|
123
|
+
block_lookup.clear
|
124
|
+
insn_lookup.clear
|
125
|
+
self
|
126
|
+
end
|
127
|
+
|
128
|
+
# Compares the graphs for equality. Relies on the basic blocks having unique
|
129
|
+
# names to simplify isomorphism comparisons. Unfortunately this means
|
130
|
+
# tests will have to know block names. Oh well.
|
131
|
+
def ==(other)
|
132
|
+
pairs = self.vertices.sort_by(&:name).zip(other.vertices.sort_by(&:name))
|
133
|
+
(pairs.all? do |v1, v2|
|
134
|
+
v1.name == v2.name && v1.instructions == v2.instructions
|
135
|
+
end) && (self.edges.sort == other.edges.sort)
|
136
|
+
end
|
137
|
+
|
138
|
+
def inspect
|
139
|
+
"<ControlFlowGraph num_verts=#{vertices.size}>"
|
140
|
+
end
|
141
|
+
|
142
|
+
def clear_analyses
|
143
|
+
all_variables.each do |temp|
|
144
|
+
temp.bind! UNDEFINED
|
145
|
+
temp.inferred_type = nil
|
146
|
+
end
|
147
|
+
vertices.each do |block|
|
148
|
+
block.successors.each do |succ|
|
149
|
+
block.remove_flag(succ, ControlFlowGraph::EDGE_EXECUTABLE)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def save_pretty_picture(fmt='png', dotfile='graph', params = {'shape' => 'box'})
|
155
|
+
write_to_graphic_file(fmt, dotfile, params)
|
156
|
+
end
|
157
|
+
|
158
|
+
def dotty(params = {'shape' => 'box'})
|
159
|
+
super
|
160
|
+
end
|
161
|
+
|
162
|
+
def raise_type
|
163
|
+
if !all_failure_postdominator || all_failure_postdominator.real_predecessors.empty?
|
164
|
+
Types::EMPTY
|
165
|
+
else
|
166
|
+
@final_exception.expr_type
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def return_type
|
171
|
+
if (@exit.normal_predecessors & @exit.real_predecessors).empty?
|
172
|
+
Types::EMPTY
|
173
|
+
else
|
174
|
+
@final_return.expr_type
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def real_self_type
|
179
|
+
@self_type || Types::TOP
|
180
|
+
end
|
181
|
+
|
182
|
+
def bind_self_type(new_self_type)
|
183
|
+
@self_type = new_self_type
|
184
|
+
end
|
185
|
+
|
186
|
+
def bound_argument_types?
|
187
|
+
!!@formal_types
|
188
|
+
end
|
189
|
+
|
190
|
+
def bound_arity
|
191
|
+
@formal_types.size
|
192
|
+
end
|
193
|
+
|
194
|
+
def real_formal_type(idx)
|
195
|
+
(@formal_types && @formal_types[idx]) || Types::TOP
|
196
|
+
end
|
197
|
+
|
198
|
+
def bind_formal_types(new_formal_types)
|
199
|
+
@formal_types = new_formal_types
|
200
|
+
end
|
201
|
+
|
202
|
+
def real_block_type
|
203
|
+
@block_type || Types::BLOCK
|
204
|
+
end
|
205
|
+
|
206
|
+
def bind_block_type(new_block_type)
|
207
|
+
@block_type = new_block_type
|
208
|
+
end
|
209
|
+
|
210
|
+
DEFAULT_ANALYSIS_OPTS = {optimize: true, simulate: true}
|
211
|
+
# Runs full analysis on the CFG. Puts it in SSA then searches for warnings.
|
212
|
+
def analyze(opts={})
|
213
|
+
opts = DEFAULT_ANALYSIS_OPTS.merge(opts)
|
214
|
+
# kill obvious dead code now.
|
215
|
+
perform_dead_code_discovery(true)
|
216
|
+
Laser.debug_puts('>>> Starting SSA Transformation <<<')
|
217
|
+
static_single_assignment_form unless @in_ssa
|
218
|
+
Laser.debug_puts('>>> Finished SSA Transformation <<<')
|
219
|
+
if @root.type == :program
|
220
|
+
Laser.debug_puts('>>> Starting Simulation <<<')
|
221
|
+
begin
|
222
|
+
simulate([], :mutation => true) if opts[:simulate]
|
223
|
+
rescue Simulation::NonDeterminismHappened => err
|
224
|
+
Laser.debug_puts('Note: Simulation was nondeterministic.')
|
225
|
+
rescue Simulation::SimulationNonterminationError => err
|
226
|
+
Laser.debug_puts('Note: Simulation was potentially nonterminating.')
|
227
|
+
end
|
228
|
+
Laser.debug_puts('>>> Finished Simulation <<<')
|
229
|
+
else
|
230
|
+
Laser.debug_puts('>>> Starting CP <<<')
|
231
|
+
perform_constant_propagation(opts)
|
232
|
+
Laser.debug_puts('>>> Finished CP <<<')
|
233
|
+
if opts[:optimize]
|
234
|
+
Laser.debug_puts('>>> Killing Unexecuted Edges <<<')
|
235
|
+
kill_unexecuted_edges
|
236
|
+
Laser.debug_puts('>>> Finished Killing Unexecuted Edges <<<')
|
237
|
+
Laser.debug_puts('>>> Pruning Totally Useless Blocks <<<')
|
238
|
+
prune_totally_useless_blocks
|
239
|
+
Laser.debug_puts('>>> Finished Pruning Totally Useless Blocks <<<')
|
240
|
+
Laser.debug_puts('>>> Dead Code Discovery <<<')
|
241
|
+
perform_dead_code_discovery
|
242
|
+
Laser.debug_puts('>>> Finished Dead Code Discovery <<<')
|
243
|
+
Laser.debug_puts('>>> Adding Unused Variable Warnings <<<')
|
244
|
+
add_unused_variable_warnings
|
245
|
+
Laser.debug_puts('>>> Finished Adding Unused Variable Warnings <<<')
|
246
|
+
|
247
|
+
if @root.type != :program
|
248
|
+
Laser.debug_puts('>>> Determining Yield Properties <<<')
|
249
|
+
find_yield_properties(opts)
|
250
|
+
Laser.debug_puts('>>> Finished Determining Yield Properties <<<')
|
251
|
+
end
|
252
|
+
Laser.debug_puts('>>> Determining Raise Properties <<<')
|
253
|
+
find_raise_properties
|
254
|
+
Laser.debug_puts('>>> Finished Determining Raise Properties <<<')
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def debug_dotty
|
260
|
+
Laser.debug_dotty(self)
|
261
|
+
end
|
262
|
+
|
263
|
+
def all_errors
|
264
|
+
self.root.all_errors
|
265
|
+
end
|
266
|
+
|
267
|
+
# Returns the names of all variables in the graph
|
268
|
+
def all_variables
|
269
|
+
return @all_cached_variables unless @all_cached_variables.empty?
|
270
|
+
return @all_variables if @all_variables
|
271
|
+
result = Set.new
|
272
|
+
vertices.each do |vert|
|
273
|
+
vert.variables.each do |var|
|
274
|
+
result << var
|
275
|
+
end
|
276
|
+
end
|
277
|
+
@all_variables = result
|
278
|
+
end
|
279
|
+
|
280
|
+
def var_named(name)
|
281
|
+
all_variables.find { |x| x.name.start_with?(name) }
|
282
|
+
end
|
283
|
+
|
284
|
+
def return_postdominator
|
285
|
+
vertex_with_name(RETURN_POSTDOMINATOR_NAME)
|
286
|
+
end
|
287
|
+
|
288
|
+
def yield_fail_postdominator
|
289
|
+
vertex_with_name(YIELD_POSTDOMINATOR_NAME)
|
290
|
+
end
|
291
|
+
|
292
|
+
def exception_postdominator
|
293
|
+
vertex_with_name(EXCEPTION_POSTDOMINATOR_NAME)
|
294
|
+
end
|
295
|
+
|
296
|
+
def all_failure_postdominator
|
297
|
+
vertex_with_name(FAILURE_POSTDOMINATOR_NAME)
|
298
|
+
end
|
299
|
+
|
300
|
+
# Yields reachable vertices via depth-first-search on real edges
|
301
|
+
def reachable_vertices
|
302
|
+
vertices = Set[]
|
303
|
+
worklist = Set[self.enter]
|
304
|
+
while worklist.any?
|
305
|
+
block = worklist.pop
|
306
|
+
yield block if block_given?
|
307
|
+
block.real_successors.each do |succ|
|
308
|
+
worklist.add(succ) if vertices.add?(succ)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
vertices
|
312
|
+
end
|
313
|
+
|
314
|
+
# Computes the variables reachable by DFSing the start node.
|
315
|
+
# This excludes variables defined in dead code.
|
316
|
+
def reachable_variables(block = @enter, visited = Set.new)
|
317
|
+
visited << block
|
318
|
+
block.real_successors.inject(block.variables) do |cur, succ|
|
319
|
+
if visited.include?(succ)
|
320
|
+
cur
|
321
|
+
else
|
322
|
+
cur | reachable_variables(succ, visited)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
# Removes blocks that are not reachable and which go nowhere: they
|
328
|
+
# have no effect on the program.
|
329
|
+
def prune_totally_useless_blocks
|
330
|
+
vertices = self.to_a
|
331
|
+
vertices.each do |vertex|
|
332
|
+
if degree(vertex).zero?
|
333
|
+
remove_vertex(vertex)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def prune_unexecuted_blocks
|
339
|
+
kill_unexecuted_edges(true) # be ruthless
|
340
|
+
unreachable_vertices.each do |block|
|
341
|
+
block.instructions.each do |insn|
|
342
|
+
insn.operands.each { |op| op.uses -= ::Set[insn] }
|
343
|
+
end
|
344
|
+
remove_vertex block
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
# Marks all edges that are not executable as fake edges. That way, the
|
349
|
+
# postdominance of Exit is preserved, but dead code analysis will ignore
|
350
|
+
# them.
|
351
|
+
def kill_unexecuted_edges(remove=false)
|
352
|
+
killable = Set.new
|
353
|
+
each_edge do |u, v|
|
354
|
+
if !(is_executable?(u, v) || is_fake?(u, v))
|
355
|
+
killable << [u, v]
|
356
|
+
end
|
357
|
+
end
|
358
|
+
killable.each do |u, v|
|
359
|
+
if remove
|
360
|
+
remove_edge(u, v)
|
361
|
+
else
|
362
|
+
u.add_flag(v, EDGE_FAKE)
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Laser
|
2
|
+
module Analysis
|
3
|
+
module ControlFlow
|
4
|
+
# Methods for computing the lifetime of the variables in
|
5
|
+
# the control flow graph.
|
6
|
+
module LifetimeAnalysis
|
7
|
+
# Calculates Live for all global temps. Also calculates LiveOut.
|
8
|
+
# p.136 Morgan
|
9
|
+
def calculate_live
|
10
|
+
setup_lifetime
|
11
|
+
visit = Set.new
|
12
|
+
@live_out = Hash.new { |hash, key| hash[key] = Set.new }
|
13
|
+
@live.clear
|
14
|
+
@globals.each do |temp|
|
15
|
+
@live[temp] = live_worklist(temp)
|
16
|
+
visit.clear
|
17
|
+
@definition_blocks[temp].each do |eval_block|
|
18
|
+
find_live_visited(eval_block, visit, @live[temp])
|
19
|
+
end
|
20
|
+
|
21
|
+
@live[temp] &= visit
|
22
|
+
@live[temp].each do |block|
|
23
|
+
block.real_predecessors.each do |pred|
|
24
|
+
if visit.include?(pred)
|
25
|
+
@live_out[pred] << temp
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# Computes LiveIn(T) forall Temps, Globals, and LiveKill(B) forall Blocks
|
35
|
+
# p.134, Morgan
|
36
|
+
def setup_lifetime
|
37
|
+
@globals = Set.new
|
38
|
+
exposed = Set.new
|
39
|
+
@live_in = Hash.new { |hash, key| hash[key] = Set.new }
|
40
|
+
@live_kill = Hash.new { |hash, key| hash[key] = Set.new }
|
41
|
+
@definition_blocks = Hash.new { |hash, key| hash[key] = Set.new }
|
42
|
+
|
43
|
+
vertices.each do |block|
|
44
|
+
exposed.clear
|
45
|
+
block.instructions.reverse_each do |ins|
|
46
|
+
targets = ins.explicit_targets
|
47
|
+
targets.each { |target| @definition_blocks[target] << block }
|
48
|
+
@live_kill[block] |= targets
|
49
|
+
exposed = (exposed - targets) | ins.operands
|
50
|
+
exposed << ins.block_operand if ins.block_operand
|
51
|
+
end
|
52
|
+
@globals |= exposed
|
53
|
+
exposed.each do |temp|
|
54
|
+
@live_in[temp] << block
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Computes the set of blocks in which the given temporary is alive at
|
60
|
+
# the beginning of the block. Uses setup_lifetime.
|
61
|
+
# p.134, Morgan
|
62
|
+
def live_worklist(temp)
|
63
|
+
worklist = Set.new(@live_in[temp])
|
64
|
+
result_live = Set.new(@live_in[temp])
|
65
|
+
until worklist.empty?
|
66
|
+
block = worklist.pop
|
67
|
+
block.real_predecessors.each do |pred|
|
68
|
+
if !@live_kill[pred].include?(temp) and !result_live.include?(pred)
|
69
|
+
result_live << pred
|
70
|
+
worklist << pred
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
result_live
|
75
|
+
end
|
76
|
+
|
77
|
+
# DFSes but ignores non-live blocks. Adds each block that is walked
|
78
|
+
# to the visit set. Used by calculate_live.
|
79
|
+
def find_live_visited(current, visit, live)
|
80
|
+
visit << current
|
81
|
+
current.real_successors.each do |block|
|
82
|
+
if live.include?(block) && !visit.include?(block)
|
83
|
+
find_live_visited(block, visit, live)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end # module LifetimeAnalysis
|
89
|
+
end # module ControlFlow
|
90
|
+
end # module Analysis
|
91
|
+
end # module Laser
|