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,170 @@
|
|
|
1
|
+
require 'laser/third_party/rgl/mutable'
|
|
2
|
+
require 'set'
|
|
3
|
+
|
|
4
|
+
module RGL
|
|
5
|
+
# This is an implementation of a more efficient graph customized
|
|
6
|
+
# for control-flow purposes. Lots of operations on RGL's base library,
|
|
7
|
+
# while re-using a lot of code, are needlessly algorithmically insufficient.
|
|
8
|
+
# (#empty is O(|V|)!)
|
|
9
|
+
class ControlFlowGraph
|
|
10
|
+
EDGE_NORMAL = 1 << 0
|
|
11
|
+
EDGE_ABNORMAL = 1 << 1
|
|
12
|
+
EDGE_FAKE = 1 << 2
|
|
13
|
+
EDGE_EXECUTABLE = 1 << 3
|
|
14
|
+
EDGE_BLOCK_TAKEN = 1 << 4
|
|
15
|
+
|
|
16
|
+
include Enumerable
|
|
17
|
+
include MutableGraph
|
|
18
|
+
attr_reader :enter, :exit
|
|
19
|
+
attr_reader :vertices, :vertex_lookup
|
|
20
|
+
|
|
21
|
+
def initialize
|
|
22
|
+
@enter = Laser::Analysis::ControlFlow::TerminalBasicBlock.new('Enter')
|
|
23
|
+
@exit = Laser::Analysis::ControlFlow::TerminalBasicBlock.new('Exit')
|
|
24
|
+
@vertices = Set[@enter, @exit]
|
|
25
|
+
@vertex_lookup = {'Enter' => @enter, 'Exit' => @exit}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def [](key)
|
|
29
|
+
vertex_with_name(key.name)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def vertex_with_name(key)
|
|
33
|
+
@vertex_lookup[key]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Gets all the edges. O(E).
|
|
37
|
+
def edges
|
|
38
|
+
vertices.map { |vert| vert.successors.map { |succ| [vert, succ] }}.flatten 1
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Enumerates the vertices. O(V).
|
|
42
|
+
def each_vertex(&b)
|
|
43
|
+
vertices.each(&b)
|
|
44
|
+
end
|
|
45
|
+
alias each each_vertex
|
|
46
|
+
|
|
47
|
+
# Enumerates every vertex adjacent to u. O(V).
|
|
48
|
+
def each_adjacent(u, &b)
|
|
49
|
+
self[u].successors.each(&b)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Jacked from RGL. O(E).
|
|
53
|
+
def each_edge
|
|
54
|
+
each_vertex { |u|
|
|
55
|
+
each_adjacent(u) { |v| yield u,v }
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Adds the vertex to the set of vertices. O(1) amortized.
|
|
60
|
+
def add_vertex(u)
|
|
61
|
+
@vertex_lookup[u.name] = u
|
|
62
|
+
vertices << u
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Adds the edge to the graph. O(1) amortized.
|
|
66
|
+
def add_edge(u, v, flags = EDGE_NORMAL)
|
|
67
|
+
u.join(v)
|
|
68
|
+
u.set_flag(v, flags)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def is_block_taken?(src, dest)
|
|
72
|
+
src.has_flag?(dest, EDGE_BLOCK_TAKEN)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def is_abnormal?(src, dest)
|
|
76
|
+
src.has_flag?(dest, EDGE_ABNORMAL)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def is_fake?(src, dest)
|
|
80
|
+
src.has_flag?(dest, EDGE_FAKE)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def is_executable?(src, dest)
|
|
84
|
+
src.has_flag?(dest, EDGE_EXECUTABLE)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def add_flag(src, dest, flag)
|
|
88
|
+
src.add_flag(dest, flag)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def remove_flag(src, dest, flag)
|
|
92
|
+
src.remove_flag(dest, flag)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Removes the vertex from the graph. O(E) amortized.
|
|
96
|
+
def remove_vertex(u)
|
|
97
|
+
u.clear_edges
|
|
98
|
+
looked_up = self[u]
|
|
99
|
+
# looked_up.successors.each do |succ|
|
|
100
|
+
# self[succ].remove_predecessor looked_up
|
|
101
|
+
# self[looked_up].delete_all_flags succ
|
|
102
|
+
# end
|
|
103
|
+
# looked_up.predecessors.each do |pred|
|
|
104
|
+
# self[pred].remove_successor looked_up
|
|
105
|
+
# self[pred].delete_all_flags looked_up
|
|
106
|
+
# end
|
|
107
|
+
@vertex_lookup.delete looked_up.name
|
|
108
|
+
vertices.delete looked_up
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Removes the edge from the graph. O(1) amortized.
|
|
112
|
+
def remove_edge(u, v)
|
|
113
|
+
|
|
114
|
+
looked_up_u, looked_up_v = self[u], self[v]
|
|
115
|
+
looked_up_u.disconnect(looked_up_v)
|
|
116
|
+
# looked_up_u.remove_successor looked_up_v
|
|
117
|
+
# looked_up_v.remove_predecessor looked_up_u
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Counts the number of vertices. O(1).
|
|
121
|
+
def num_vertices
|
|
122
|
+
vertices.size
|
|
123
|
+
end
|
|
124
|
+
alias size num_vertices
|
|
125
|
+
|
|
126
|
+
# Does the graph have no vertices? O(1).
|
|
127
|
+
def empty?
|
|
128
|
+
vertices.empty?
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Does the graph contain this vertex? O(1).
|
|
132
|
+
def has_vertex?(u)
|
|
133
|
+
vertices.include?(u)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def has_edge?(u, v)
|
|
137
|
+
self[u].successors.include?(v)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Returns an array of vertices in this graph. O(V).
|
|
141
|
+
def to_a
|
|
142
|
+
vertices.to_a
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Is the graph directed? Yes, always.
|
|
146
|
+
def directed?
|
|
147
|
+
true
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Computes the total degree of the vertex. O(1).
|
|
151
|
+
def degree(u)
|
|
152
|
+
in_degree(u) + out_degree(u)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# What is the in-degree of the vertex u? O(1).
|
|
156
|
+
def in_degree(u)
|
|
157
|
+
self[u].predecessors.size
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# What is the out-degree of the vertex u? O(1).
|
|
161
|
+
def out_degree(u)
|
|
162
|
+
self[u].successors.size
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# How many edges are in the graph? O(V).
|
|
166
|
+
def num_edges
|
|
167
|
+
vertices.map { vertices.successors.size }.inject(:+)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
# connected_components.rb
|
|
3
|
+
#
|
|
4
|
+
# This file contains the algorithms for the connected components of an
|
|
5
|
+
# undirected graph (each_connected_component) and strongly connected components
|
|
6
|
+
# for directed graphs (strongly_connected_components).
|
|
7
|
+
#
|
|
8
|
+
require 'set'
|
|
9
|
+
require 'laser/third_party/rgl/traversal'
|
|
10
|
+
|
|
11
|
+
module RGL
|
|
12
|
+
module Graph
|
|
13
|
+
# Computes the depth first spanning tree of the CFG, and
|
|
14
|
+
# also attaches the depth-first ordering to the basic blocks
|
|
15
|
+
# in the CFG.
|
|
16
|
+
# O(|V| + |E|), just like DFS.
|
|
17
|
+
def depth_first_spanning_tree(start_node)
|
|
18
|
+
raise ArgumentError unless vertices.include?(start_node)
|
|
19
|
+
tree = DirectedAdjacencyGraph.new
|
|
20
|
+
visited = Set.new
|
|
21
|
+
build_dfst(tree, start_node, visited)
|
|
22
|
+
tree
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# builds the dfst from the start node.
|
|
26
|
+
# O(|V| + |E|), just like DFS.
|
|
27
|
+
def build_dfst(tree, node, visited)
|
|
28
|
+
visited << node
|
|
29
|
+
node.real_successors.each do |other|
|
|
30
|
+
if !visited.include?(other)
|
|
31
|
+
tree.add_edge(node, other)
|
|
32
|
+
build_dfst(tree, other, visited)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# dominators.rb
|
|
2
|
+
#
|
|
3
|
+
# This file contains algorithms for finding the dominators and dominance
|
|
4
|
+
# frontier of a control flow graph. These algorithms require that every node
|
|
5
|
+
# be reachable from the start node. Keep this in mind.
|
|
6
|
+
require 'set'
|
|
7
|
+
require 'laser/third_party/rgl/traversal'
|
|
8
|
+
|
|
9
|
+
module RGL
|
|
10
|
+
module Graph
|
|
11
|
+
# Returns the dominator tree of the graph. O(V^2), but performs better than
|
|
12
|
+
# or close to Lengauer-Tarjan on real-world ASTs.
|
|
13
|
+
#
|
|
14
|
+
# If the start node is not provided, it is assumed the receiver is a
|
|
15
|
+
# ControlFlowGraph and has an #enter method.
|
|
16
|
+
def dominator_tree(start_node = self.enter)
|
|
17
|
+
doms = {start_node => start_node}
|
|
18
|
+
changed = true
|
|
19
|
+
reverse_postorder = compute_post_order(self, start_node)
|
|
20
|
+
while changed
|
|
21
|
+
changed = false
|
|
22
|
+
reverse_postorder.each do |b|
|
|
23
|
+
if (original = b.each_real_predecessors.find { |node| doms[node] })
|
|
24
|
+
new_idom = original
|
|
25
|
+
b.each_real_predecessors do |p|
|
|
26
|
+
if doms[p] && p != original
|
|
27
|
+
new_idom = dominator_set_intersect(p, new_idom, doms)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
if doms[b] != new_idom
|
|
31
|
+
doms[b] = new_idom
|
|
32
|
+
changed = true
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# doms is IDOM. All outward edges connect an IDom to its dominee.
|
|
39
|
+
d_tree = self.class.new
|
|
40
|
+
(vertices - [enter, exit]).each do |b|
|
|
41
|
+
copy = Laser::Analysis::ControlFlow::BasicBlock.new(b.name)
|
|
42
|
+
copy.instructions = b.instructions
|
|
43
|
+
d_tree.add_vertex(copy)
|
|
44
|
+
end
|
|
45
|
+
doms.each { |src, dest| d_tree.add_edge(d_tree[src], d_tree[dest]) unless src == enter && dest == enter }
|
|
46
|
+
d_tree
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Returns the dominance frontier of the graph.
|
|
50
|
+
#
|
|
51
|
+
# If the start node is not provided, it is assumed the receiver is a
|
|
52
|
+
# ControlFlowGraph and has an #enter method.
|
|
53
|
+
#
|
|
54
|
+
# return: Node => Set<Node>
|
|
55
|
+
def dominance_frontier(start_node = self.enter, dom_tree)
|
|
56
|
+
vertices.inject(Hash.new { |h, k| h[k] = Set.new }) do |result, b|
|
|
57
|
+
preds = b.real_predecessors
|
|
58
|
+
if preds.size >= 2
|
|
59
|
+
preds.each do |p|
|
|
60
|
+
b_dominator = dom_tree[b].successors.first
|
|
61
|
+
break unless b_dominator
|
|
62
|
+
runner = dom_tree[p]
|
|
63
|
+
while runner && runner != b_dominator
|
|
64
|
+
result[runner] << b
|
|
65
|
+
runner = runner.successors.first
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
result
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Computes DF^+: the iterated dominance frontier of a set of blocks.
|
|
74
|
+
# Used in SSA conversion.
|
|
75
|
+
def iterated_dominance_frontier(set, dom_tree)
|
|
76
|
+
worklist = Set.new(set)
|
|
77
|
+
result = Set.new(set)
|
|
78
|
+
frontier = dominance_frontier(dom_tree)
|
|
79
|
+
|
|
80
|
+
until worklist.empty?
|
|
81
|
+
block = worklist.pop
|
|
82
|
+
frontier[dom_tree[block]].each do |candidate|
|
|
83
|
+
candidate_in_full_graph = self[candidate]
|
|
84
|
+
unless result.include?(candidate_in_full_graph)
|
|
85
|
+
result << candidate_in_full_graph
|
|
86
|
+
worklist << candidate_in_full_graph
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
result
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
private
|
|
94
|
+
|
|
95
|
+
# performs a set intersection of the dominator tree.
|
|
96
|
+
def dominator_set_intersect(b1, b2, doms)
|
|
97
|
+
finger1, finger2 = b1, b2
|
|
98
|
+
while finger1.post_order_number != finger2.post_order_number
|
|
99
|
+
finger1 = doms[finger1] while finger1.post_order_number < finger2.post_order_number
|
|
100
|
+
finger2 = doms[finger2] while finger2.post_order_number < finger1.post_order_number
|
|
101
|
+
end
|
|
102
|
+
finger1
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Good idea: depth-first ordering. found some slides about it:
|
|
106
|
+
# http://pages.cs.wisc.edu/~fischer/cs701.f08/lectures/Lecture18.4up.pdf
|
|
107
|
+
def compute_post_order(graph, start_node)
|
|
108
|
+
i = 1
|
|
109
|
+
result = []
|
|
110
|
+
visited = Set.new
|
|
111
|
+
post_order_df = proc do |node|
|
|
112
|
+
visited << node
|
|
113
|
+
node.real_successors.each do |successor|
|
|
114
|
+
post_order_df.call(successor) unless visited.include?(successor)
|
|
115
|
+
end
|
|
116
|
+
result << node
|
|
117
|
+
node.post_order_number = i
|
|
118
|
+
i += 1
|
|
119
|
+
end
|
|
120
|
+
post_order_df.call(start_node)
|
|
121
|
+
result
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# dot.rb
|
|
2
|
+
#
|
|
3
|
+
# $Id: dot.rb,v 1.8 2008/08/26 20:07:09 javanthropus Exp $
|
|
4
|
+
#
|
|
5
|
+
# Minimal Dot support, based on Dave Thomas's dot module (included in rdoc).
|
|
6
|
+
# rdot.rb is a modified version which also contains support for undirected
|
|
7
|
+
# graphs.
|
|
8
|
+
|
|
9
|
+
require 'laser/third_party/rgl/rdot'
|
|
10
|
+
|
|
11
|
+
module RGL
|
|
12
|
+
|
|
13
|
+
module Graph
|
|
14
|
+
|
|
15
|
+
# Return a RGL::DOT::Digraph for directed graphs or a DOT::Subgraph for an
|
|
16
|
+
# undirected Graph. _params_ can contain any graph property specified in
|
|
17
|
+
# rdot.rb.
|
|
18
|
+
|
|
19
|
+
def to_dot_graph (params = {})
|
|
20
|
+
params['name'] ||= self.class.name.gsub(/:/,'_')
|
|
21
|
+
fontsize = params['fontsize'] || '8'
|
|
22
|
+
fontname = params['fontname'] || 'Times-Roman'
|
|
23
|
+
graph = (directed? ? DOT::Digraph : DOT::Subgraph).new(params)
|
|
24
|
+
edge_class = directed? ? DOT::DirectedEdge : DOT::Edge
|
|
25
|
+
shape = params['shape'] || 'ellipse'
|
|
26
|
+
each_vertex do |v|
|
|
27
|
+
name = v.to_s
|
|
28
|
+
graph << DOT::Node.new('name' => name,
|
|
29
|
+
'fontsize' => fontsize,
|
|
30
|
+
'label' => name,
|
|
31
|
+
'shape' => shape,
|
|
32
|
+
'fontname' => fontname)
|
|
33
|
+
end
|
|
34
|
+
each_edge do |u,v|
|
|
35
|
+
if respond_to?(:is_abnormal?)
|
|
36
|
+
if is_abnormal?(u, v) && is_block_taken?(u, v)
|
|
37
|
+
color = 'blue'
|
|
38
|
+
elsif is_abnormal?(u, v)
|
|
39
|
+
color = 'red'
|
|
40
|
+
elsif is_fake?(u, v)
|
|
41
|
+
color = '#bbbbbb'
|
|
42
|
+
else
|
|
43
|
+
color = 'black'
|
|
44
|
+
end
|
|
45
|
+
style = (is_fake?(u, v) || !is_executable?(u, v)) ? 'dashed' : 'solid'
|
|
46
|
+
else
|
|
47
|
+
color = 'black'
|
|
48
|
+
style = 'solid'
|
|
49
|
+
end
|
|
50
|
+
graph << edge_class.new('from' => u.to_s,
|
|
51
|
+
'to' => v.to_s,
|
|
52
|
+
'fontsize' => fontsize,
|
|
53
|
+
'fontname' => fontname,
|
|
54
|
+
'color' => color,
|
|
55
|
+
'style' => style)
|
|
56
|
+
end
|
|
57
|
+
graph
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Output the DOT-graph to stream _s_.
|
|
61
|
+
|
|
62
|
+
def print_dotted_on (params = {}, s = $stdout)
|
|
63
|
+
s << to_dot_graph(params).to_s << "\n"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Call dotty[http://www.graphviz.org] for the graph which is written to the
|
|
67
|
+
# file 'graph.dot' in the # current directory.
|
|
68
|
+
|
|
69
|
+
def dotty (params = {})
|
|
70
|
+
dotfile = "graph.dot"
|
|
71
|
+
File.open(dotfile, "w") {|f|
|
|
72
|
+
print_dotted_on(params, f)
|
|
73
|
+
}
|
|
74
|
+
system("dotty", dotfile)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Use dot[http://www.graphviz.org] to create a graphical representation of
|
|
78
|
+
# the graph. Returns the filename of the graphics file.
|
|
79
|
+
|
|
80
|
+
def write_to_graphic_file (fmt='png', dotfile='graph', params = {})
|
|
81
|
+
src = dotfile + ".dot"
|
|
82
|
+
dot = dotfile + "." + fmt
|
|
83
|
+
|
|
84
|
+
File.open(src, 'w') do |f|
|
|
85
|
+
f << self.to_dot_graph(params).to_s << "\n"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
system( "dot -T#{fmt} -o #{dot} #{src}" )
|
|
89
|
+
dot
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end # module Graph
|
|
93
|
+
end # module RGL
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# graphxml.rb
|
|
2
|
+
#
|
|
3
|
+
# This file contains minimal support for creating RGL graphs from the GraphML
|
|
4
|
+
# format (see http://www.graphdrawing.org/graphml). The main purpose is to
|
|
5
|
+
# have a rich set of example graphs to have some more tests.
|
|
6
|
+
#
|
|
7
|
+
# See the examples directory, which contains a subdirectory _north_ with the
|
|
8
|
+
# Graph catalog GraphViz (see
|
|
9
|
+
# http://www.research.att.com/sw/tools/graphviz/refs.html).
|
|
10
|
+
#
|
|
11
|
+
# We use REXML::StreamListener from the REXML library
|
|
12
|
+
# (http://www.germane-software.com/software/rexml) to parse the grapml files.
|
|
13
|
+
|
|
14
|
+
require 'laser/third_party/rgl/mutable'
|
|
15
|
+
require 'rexml/document'
|
|
16
|
+
require 'rexml/streamlistener'
|
|
17
|
+
|
|
18
|
+
module RGL
|
|
19
|
+
module MutableGraph
|
|
20
|
+
# Used to parse a subset of GraphML into an RGL graph implementation.
|
|
21
|
+
class MutableGraphParser
|
|
22
|
+
include REXML::StreamListener
|
|
23
|
+
|
|
24
|
+
# First resets +graph+ to be empty and stores a reference for use with
|
|
25
|
+
# #tag_start.
|
|
26
|
+
def initialize (graph)
|
|
27
|
+
@graph = graph
|
|
28
|
+
@graph.remove_vertices(@graph.vertices)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Processes incoming edge and node elements from GraphML in order to
|
|
32
|
+
# populate the graph given to #new.
|
|
33
|
+
def tag_start (name, attrs)
|
|
34
|
+
case name
|
|
35
|
+
when 'edge'
|
|
36
|
+
@graph.add_edge(attrs['source'], attrs['target'])
|
|
37
|
+
when 'node'
|
|
38
|
+
@graph.add_vertex(attrs['id'])
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end # class MutableGraphParser
|
|
42
|
+
|
|
43
|
+
# Initializes an RGL graph from a subset of the GraphML format given in
|
|
44
|
+
# +source+ (see http://www.graphdrawing.org/graphml).
|
|
45
|
+
def from_graphxml(source)
|
|
46
|
+
listener = MutableGraphParser.new(self)
|
|
47
|
+
REXML::Document.parse_stream(source, listener)
|
|
48
|
+
self
|
|
49
|
+
end
|
|
50
|
+
end # module MutableGraph
|
|
51
|
+
end # module RGL
|