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.
Files changed (319) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +14 -0
  4. data/LICENSE +661 -0
  5. data/README.md +158 -0
  6. data/Rakefile +104 -0
  7. data/VERSION +1 -0
  8. data/bin/laser +7 -0
  9. data/design_docs/goals.md +57 -0
  10. data/design_docs/object_regex.md +426 -0
  11. data/design_docs/type_annotations.md +80 -0
  12. data/ext/laser/BasicBlock.cpp +572 -0
  13. data/ext/laser/BasicBlock.h +118 -0
  14. data/ext/laser/extconf.rb +3 -0
  15. data/features/laser.feature +25 -0
  16. data/features/step_definitions/laser_steps.rb +39 -0
  17. data/features/support/env.rb +14 -0
  18. data/features/support/testdata/1_input +1 -0
  19. data/features/support/testdata/1_output +1 -0
  20. data/features/support/testdata/2_input +4 -0
  21. data/features/support/testdata/2_output +4 -0
  22. data/features/support/testdata/3_input +8 -0
  23. data/features/support/testdata/3_output +11 -0
  24. data/features/support/testdata/4_input +5 -0
  25. data/features/support/testdata/4_output +5 -0
  26. data/features/support/testdata/5_input +13 -0
  27. data/laser.gemspec +382 -0
  28. data/lib/laser.rb +98 -0
  29. data/lib/laser/analysis/annotations.rb +95 -0
  30. data/lib/laser/analysis/annotations/annotation_config.yaml +3 -0
  31. data/lib/laser/analysis/annotations/comment_attachment_annotation.rb +66 -0
  32. data/lib/laser/analysis/annotations/node_pointers_annotation.rb +36 -0
  33. data/lib/laser/analysis/annotations/runtime_annotation.rb +55 -0
  34. data/lib/laser/analysis/argument_expansion.rb +132 -0
  35. data/lib/laser/analysis/arity.rb +34 -0
  36. data/lib/laser/analysis/bindings.rb +144 -0
  37. data/lib/laser/analysis/bootstrap/bootstrap.rb +298 -0
  38. data/lib/laser/analysis/bootstrap/laser_class.rb +106 -0
  39. data/lib/laser/analysis/bootstrap/laser_method.rb +255 -0
  40. data/lib/laser/analysis/bootstrap/laser_module.rb +403 -0
  41. data/lib/laser/analysis/bootstrap/laser_module_copy.rb +74 -0
  42. data/lib/laser/analysis/bootstrap/laser_object.rb +69 -0
  43. data/lib/laser/analysis/bootstrap/laser_proc.rb +150 -0
  44. data/lib/laser/analysis/bootstrap/laser_singleton_class.rb +44 -0
  45. data/lib/laser/analysis/comments.rb +35 -0
  46. data/lib/laser/analysis/control_flow.rb +28 -0
  47. data/lib/laser/analysis/control_flow/alias_analysis.rb +31 -0
  48. data/lib/laser/analysis/control_flow/basic_block.rb +105 -0
  49. data/lib/laser/analysis/control_flow/cfg_builder.rb +2505 -0
  50. data/lib/laser/analysis/control_flow/cfg_instruction.rb +190 -0
  51. data/lib/laser/analysis/control_flow/constant_propagation.rb +742 -0
  52. data/lib/laser/analysis/control_flow/control_flow_graph.rb +370 -0
  53. data/lib/laser/analysis/control_flow/lifetime_analysis.rb +91 -0
  54. data/lib/laser/analysis/control_flow/method_call_search.rb +26 -0
  55. data/lib/laser/analysis/control_flow/raise_properties.rb +25 -0
  56. data/lib/laser/analysis/control_flow/simulation.rb +385 -0
  57. data/lib/laser/analysis/control_flow/static_single_assignment.rb +185 -0
  58. data/lib/laser/analysis/control_flow/unreachability_analysis.rb +57 -0
  59. data/lib/laser/analysis/control_flow/unused_variables.rb +91 -0
  60. data/lib/laser/analysis/control_flow/yield_properties.rb +103 -0
  61. data/lib/laser/analysis/errors.rb +131 -0
  62. data/lib/laser/analysis/laser_utils.rb +18 -0
  63. data/lib/laser/analysis/lexical_analysis.rb +172 -0
  64. data/lib/laser/analysis/method_call.rb +68 -0
  65. data/lib/laser/analysis/protocol_registry.rb +30 -0
  66. data/lib/laser/analysis/scope.rb +118 -0
  67. data/lib/laser/analysis/sexp.rb +159 -0
  68. data/lib/laser/analysis/sexp_analysis.rb +40 -0
  69. data/lib/laser/analysis/sexp_extensions/constant_extraction.rb +115 -0
  70. data/lib/laser/analysis/sexp_extensions/source_location.rb +164 -0
  71. data/lib/laser/analysis/sexp_extensions/type_inference.rb +47 -0
  72. data/lib/laser/analysis/signature.rb +76 -0
  73. data/lib/laser/analysis/special_methods/send.rb +67 -0
  74. data/lib/laser/analysis/unused_methods.rb +21 -0
  75. data/lib/laser/analysis/visitor.rb +141 -0
  76. data/lib/laser/annotation_parser/annotations.treetop +126 -0
  77. data/lib/laser/annotation_parser/annotations_parser.rb +748 -0
  78. data/lib/laser/annotation_parser/class_annotations.treetop +82 -0
  79. data/lib/laser/annotation_parser/class_annotations_parser.rb +654 -0
  80. data/lib/laser/annotation_parser/overload.treetop +24 -0
  81. data/lib/laser/annotation_parser/overload_parser.rb +167 -0
  82. data/lib/laser/annotation_parser/parsers.rb +6 -0
  83. data/lib/laser/annotation_parser/structural.treetop +37 -0
  84. data/lib/laser/annotation_parser/structural_parser.rb +406 -0
  85. data/lib/laser/annotation_parser/useful_parsers.treetop +47 -0
  86. data/lib/laser/annotation_parser/useful_parsers_parser.rb +674 -0
  87. data/lib/laser/rake/task.rb +46 -0
  88. data/lib/laser/runner.rb +189 -0
  89. data/lib/laser/scanner.rb +169 -0
  90. data/lib/laser/standard_library/_thread.rb +110 -0
  91. data/lib/laser/standard_library/abbrev.rb +103 -0
  92. data/lib/laser/standard_library/array.rb +418 -0
  93. data/lib/laser/standard_library/base64.rb +91 -0
  94. data/lib/laser/standard_library/basic_object.rb +55 -0
  95. data/lib/laser/standard_library/benchmark.rb +556 -0
  96. data/lib/laser/standard_library/bignum.rb +185 -0
  97. data/lib/laser/standard_library/cgi.rb +275 -0
  98. data/lib/laser/standard_library/cgi/cookie.rb +147 -0
  99. data/lib/laser/standard_library/cgi/core.rb +791 -0
  100. data/lib/laser/standard_library/cgi/html.rb +1021 -0
  101. data/lib/laser/standard_library/cgi/session.rb +537 -0
  102. data/lib/laser/standard_library/cgi/session/pstore.rb +111 -0
  103. data/lib/laser/standard_library/cgi/util.rb +188 -0
  104. data/lib/laser/standard_library/class_definitions.rb +333 -0
  105. data/lib/laser/standard_library/comparable.rb +125 -0
  106. data/lib/laser/standard_library/complex.rb +162 -0
  107. data/lib/laser/standard_library/enumerable.rb +178 -0
  108. data/lib/laser/standard_library/exceptions.rb +135 -0
  109. data/lib/laser/standard_library/fixnum.rb +188 -0
  110. data/lib/laser/standard_library/float.rb +180 -0
  111. data/lib/laser/standard_library/hash.rb +237 -0
  112. data/lib/laser/standard_library/integer.rb +123 -0
  113. data/lib/laser/standard_library/laser_magic.rb +7 -0
  114. data/lib/laser/standard_library/nil_false_true.rb +113 -0
  115. data/lib/laser/standard_library/numbers.rb +192 -0
  116. data/lib/laser/standard_library/proc.rb +31 -0
  117. data/lib/laser/standard_library/set.rb +1348 -0
  118. data/lib/laser/standard_library/string.rb +666 -0
  119. data/lib/laser/standard_library/stringio.rb +2 -0
  120. data/lib/laser/standard_library/symbol.rb +125 -0
  121. data/lib/laser/standard_library/tsort.rb +242 -0
  122. data/lib/laser/support/acts_as_struct.rb +66 -0
  123. data/lib/laser/support/frequency.rb +55 -0
  124. data/lib/laser/support/inheritable_attributes.rb +145 -0
  125. data/lib/laser/support/module_extensions.rb +94 -0
  126. data/lib/laser/support/placeholder_object.rb +13 -0
  127. data/lib/laser/third_party/rgl/adjacency.rb +221 -0
  128. data/lib/laser/third_party/rgl/base.rb +228 -0
  129. data/lib/laser/third_party/rgl/bidirectional.rb +39 -0
  130. data/lib/laser/third_party/rgl/condensation.rb +47 -0
  131. data/lib/laser/third_party/rgl/connected_components.rb +138 -0
  132. data/lib/laser/third_party/rgl/control_flow.rb +170 -0
  133. data/lib/laser/third_party/rgl/depth_first_spanning_tree.rb +37 -0
  134. data/lib/laser/third_party/rgl/dominators.rb +124 -0
  135. data/lib/laser/third_party/rgl/dot.rb +93 -0
  136. data/lib/laser/third_party/rgl/graphxml.rb +51 -0
  137. data/lib/laser/third_party/rgl/implicit.rb +174 -0
  138. data/lib/laser/third_party/rgl/mutable.rb +117 -0
  139. data/lib/laser/third_party/rgl/rdot.rb +445 -0
  140. data/lib/laser/third_party/rgl/topsort.rb +72 -0
  141. data/lib/laser/third_party/rgl/transitivity.rb +180 -0
  142. data/lib/laser/third_party/rgl/traversal.rb +348 -0
  143. data/lib/laser/types/types.rb +433 -0
  144. data/lib/laser/version.rb +14 -0
  145. data/lib/laser/warning.rb +149 -0
  146. data/lib/laser/warning_sets/default.yml +13 -0
  147. data/lib/laser/warnings/assignment_in_condition.rb +20 -0
  148. data/lib/laser/warnings/comment_spacing.rb +31 -0
  149. data/lib/laser/warnings/extra_blank_lines.rb +30 -0
  150. data/lib/laser/warnings/extra_whitespace.rb +16 -0
  151. data/lib/laser/warnings/hash_symbol_18_warning.rb +63 -0
  152. data/lib/laser/warnings/hash_symbol_19_warning.rb +29 -0
  153. data/lib/laser/warnings/line_length.rb +115 -0
  154. data/lib/laser/warnings/misaligned_unindentation.rb +17 -0
  155. data/lib/laser/warnings/operator_spacing.rb +68 -0
  156. data/lib/laser/warnings/parens_on_declaration.rb +30 -0
  157. data/lib/laser/warnings/rescue_exception.rb +42 -0
  158. data/lib/laser/warnings/semicolon.rb +25 -0
  159. data/lib/laser/warnings/sexp_errors.rb +24 -0
  160. data/lib/laser/warnings/uncalled_method_warning.rb +7 -0
  161. data/lib/laser/warnings/useless_double_quotes.rb +38 -0
  162. data/spec/analysis_specs/annotations_spec.rb +47 -0
  163. data/spec/analysis_specs/annotations_specs/comment_attachment_spec.rb +68 -0
  164. data/spec/analysis_specs/annotations_specs/node_pointers_annotation_spec.rb +90 -0
  165. data/spec/analysis_specs/annotations_specs/runtime_annotation_spec.rb +135 -0
  166. data/spec/analysis_specs/annotations_specs/spec_helper.rb +33 -0
  167. data/spec/analysis_specs/argument_expansion_spec.rb +113 -0
  168. data/spec/analysis_specs/bindings_spec.rb +36 -0
  169. data/spec/analysis_specs/comment_spec.rb +93 -0
  170. data/spec/analysis_specs/control_flow_specs/cfg_instruction_spec.rb +111 -0
  171. data/spec/analysis_specs/control_flow_specs/constant_propagation_spec.rb +560 -0
  172. data/spec/analysis_specs/control_flow_specs/control_flow_graph_spec.rb +5 -0
  173. data/spec/analysis_specs/control_flow_specs/raise_properties_spec.rb +310 -0
  174. data/spec/analysis_specs/control_flow_specs/raise_type_inference_spec.rb +301 -0
  175. data/spec/analysis_specs/control_flow_specs/return_type_inference_spec.rb +431 -0
  176. data/spec/analysis_specs/control_flow_specs/simulation_spec.rb +158 -0
  177. data/spec/analysis_specs/control_flow_specs/spec_helper.rb +110 -0
  178. data/spec/analysis_specs/control_flow_specs/tuple_misuse_inference_spec.rb +125 -0
  179. data/spec/analysis_specs/control_flow_specs/unreachability_analysis_spec.rb +76 -0
  180. data/spec/analysis_specs/control_flow_specs/unused_variable_spec.rb +99 -0
  181. data/spec/analysis_specs/control_flow_specs/yield_properties_spec.rb +372 -0
  182. data/spec/analysis_specs/error_spec.rb +30 -0
  183. data/spec/analysis_specs/laser_class_spec.rb +322 -0
  184. data/spec/analysis_specs/lexical_analysis_spec.rb +184 -0
  185. data/spec/analysis_specs/protocol_registry_spec.rb +63 -0
  186. data/spec/analysis_specs/scope_annotation_spec.rb +1013 -0
  187. data/spec/analysis_specs/scope_spec.rb +126 -0
  188. data/spec/analysis_specs/sexp_analysis_spec.rb +30 -0
  189. data/spec/analysis_specs/sexp_extension_specs/constant_extraction_spec.rb +309 -0
  190. data/spec/analysis_specs/sexp_extension_specs/source_location_spec.rb +231 -0
  191. data/spec/analysis_specs/sexp_extension_specs/spec_helper.rb +1 -0
  192. data/spec/analysis_specs/sexp_extension_specs/type_inference_spec.rb +252 -0
  193. data/spec/analysis_specs/sexp_spec.rb +167 -0
  194. data/spec/analysis_specs/spec_helper.rb +27 -0
  195. data/spec/analysis_specs/unused_methods_spec.rb +65 -0
  196. data/spec/analysis_specs/visitor_spec.rb +64 -0
  197. data/spec/annotation_parser_specs/annotations_parser_spec.rb +89 -0
  198. data/spec/annotation_parser_specs/class_annotation_parser_spec.rb +120 -0
  199. data/spec/annotation_parser_specs/overload_parser_spec.rb +39 -0
  200. data/spec/annotation_parser_specs/parsers_spec.rb +14 -0
  201. data/spec/annotation_parser_specs/spec_helper.rb +1 -0
  202. data/spec/annotation_parser_specs/structural_parser_spec.rb +67 -0
  203. data/spec/laser_spec.rb +14 -0
  204. data/spec/rake_specs/spec_helper.rb +1 -0
  205. data/spec/rake_specs/task_spec.rb +67 -0
  206. data/spec/runner_spec.rb +207 -0
  207. data/spec/scanner_spec.rb +75 -0
  208. data/spec/spec_helper.rb +121 -0
  209. data/spec/standard_library/exceptions_spec.rb +19 -0
  210. data/spec/standard_library/globals_spec.rb +14 -0
  211. data/spec/standard_library/set_spec.rb +31 -0
  212. data/spec/standard_library/spec_helper.rb +1 -0
  213. data/spec/standard_library/standard_library_spec.rb +302 -0
  214. data/spec/support_specs/acts_as_struct_spec.rb +94 -0
  215. data/spec/support_specs/frequency_spec.rb +23 -0
  216. data/spec/support_specs/module_extensions_spec.rb +117 -0
  217. data/spec/support_specs/spec_helper.rb +1 -0
  218. data/spec/type_specs/spec_helper.rb +1 -0
  219. data/spec/type_specs/types_spec.rb +133 -0
  220. data/spec/warning_spec.rb +95 -0
  221. data/spec/warning_specs/assignment_in_condition_spec.rb +68 -0
  222. data/spec/warning_specs/comment_spacing_spec.rb +65 -0
  223. data/spec/warning_specs/extra_blank_lines_spec.rb +70 -0
  224. data/spec/warning_specs/extra_whitespace_spec.rb +33 -0
  225. data/spec/warning_specs/hash_symbol_18_warning_spec.rb +89 -0
  226. data/spec/warning_specs/hash_symbol_19_warning_spec.rb +63 -0
  227. data/spec/warning_specs/line_length_spec.rb +173 -0
  228. data/spec/warning_specs/misaligned_unindentation_spec.rb +35 -0
  229. data/spec/warning_specs/operator_spacing_spec.rb +104 -0
  230. data/spec/warning_specs/parens_on_declaration_spec.rb +57 -0
  231. data/spec/warning_specs/rescue_exception_spec.rb +105 -0
  232. data/spec/warning_specs/semicolon_spec.rb +58 -0
  233. data/spec/warning_specs/spec_helper.rb +1 -0
  234. data/spec/warning_specs/useless_double_quotes_spec.rb +74 -0
  235. data/status_reports/2010/12/2010-12-14.md +163 -0
  236. data/status_reports/2010/12/2010-12-23.md +298 -0
  237. data/status_reports/2010/12/2010-12-24.md +6 -0
  238. data/test/third_party_tests/rgl_tests/TestComponents.rb +65 -0
  239. data/test/third_party_tests/rgl_tests/TestCycles.rb +61 -0
  240. data/test/third_party_tests/rgl_tests/TestDirectedGraph.rb +125 -0
  241. data/test/third_party_tests/rgl_tests/TestDot.rb +18 -0
  242. data/test/third_party_tests/rgl_tests/TestEdge.rb +34 -0
  243. data/test/third_party_tests/rgl_tests/TestGraph.rb +71 -0
  244. data/test/third_party_tests/rgl_tests/TestGraphXML.rb +57 -0
  245. data/test/third_party_tests/rgl_tests/TestImplicit.rb +52 -0
  246. data/test/third_party_tests/rgl_tests/TestRdot.rb +863 -0
  247. data/test/third_party_tests/rgl_tests/TestTransitivity.rb +129 -0
  248. data/test/third_party_tests/rgl_tests/TestTraversal.rb +220 -0
  249. data/test/third_party_tests/rgl_tests/TestUnDirectedGraph.rb +102 -0
  250. data/test/third_party_tests/rgl_tests/examples/north/Graph.log +128 -0
  251. data/test/third_party_tests/rgl_tests/examples/north/g.10.0.graphml +28 -0
  252. data/test/third_party_tests/rgl_tests/examples/north/g.10.1.graphml +28 -0
  253. data/test/third_party_tests/rgl_tests/examples/north/g.10.11.graphml +31 -0
  254. data/test/third_party_tests/rgl_tests/examples/north/g.10.12.graphml +27 -0
  255. data/test/third_party_tests/rgl_tests/examples/north/g.10.13.graphml +27 -0
  256. data/test/third_party_tests/rgl_tests/examples/north/g.10.14.graphml +27 -0
  257. data/test/third_party_tests/rgl_tests/examples/north/g.10.15.graphml +26 -0
  258. data/test/third_party_tests/rgl_tests/examples/north/g.10.16.graphml +26 -0
  259. data/test/third_party_tests/rgl_tests/examples/north/g.10.17.graphml +26 -0
  260. data/test/third_party_tests/rgl_tests/examples/north/g.10.19.graphml +37 -0
  261. data/test/third_party_tests/rgl_tests/examples/north/g.10.2.graphml +28 -0
  262. data/test/third_party_tests/rgl_tests/examples/north/g.10.20.graphml +38 -0
  263. data/test/third_party_tests/rgl_tests/examples/north/g.10.22.graphml +43 -0
  264. data/test/third_party_tests/rgl_tests/examples/north/g.10.24.graphml +30 -0
  265. data/test/third_party_tests/rgl_tests/examples/north/g.10.25.graphml +45 -0
  266. data/test/third_party_tests/rgl_tests/examples/north/g.10.27.graphml +38 -0
  267. data/test/third_party_tests/rgl_tests/examples/north/g.10.28.graphml +30 -0
  268. data/test/third_party_tests/rgl_tests/examples/north/g.10.29.graphml +38 -0
  269. data/test/third_party_tests/rgl_tests/examples/north/g.10.3.graphml +26 -0
  270. data/test/third_party_tests/rgl_tests/examples/north/g.10.30.graphml +34 -0
  271. data/test/third_party_tests/rgl_tests/examples/north/g.10.31.graphml +42 -0
  272. data/test/third_party_tests/rgl_tests/examples/north/g.10.34.graphml +42 -0
  273. data/test/third_party_tests/rgl_tests/examples/north/g.10.37.graphml +28 -0
  274. data/test/third_party_tests/rgl_tests/examples/north/g.10.38.graphml +38 -0
  275. data/test/third_party_tests/rgl_tests/examples/north/g.10.39.graphml +36 -0
  276. data/test/third_party_tests/rgl_tests/examples/north/g.10.4.graphml +26 -0
  277. data/test/third_party_tests/rgl_tests/examples/north/g.10.40.graphml +37 -0
  278. data/test/third_party_tests/rgl_tests/examples/north/g.10.41.graphml +37 -0
  279. data/test/third_party_tests/rgl_tests/examples/north/g.10.42.graphml +26 -0
  280. data/test/third_party_tests/rgl_tests/examples/north/g.10.45.graphml +28 -0
  281. data/test/third_party_tests/rgl_tests/examples/north/g.10.46.graphml +32 -0
  282. data/test/third_party_tests/rgl_tests/examples/north/g.10.5.graphml +31 -0
  283. data/test/third_party_tests/rgl_tests/examples/north/g.10.50.graphml +30 -0
  284. data/test/third_party_tests/rgl_tests/examples/north/g.10.56.graphml +29 -0
  285. data/test/third_party_tests/rgl_tests/examples/north/g.10.57.graphml +32 -0
  286. data/test/third_party_tests/rgl_tests/examples/north/g.10.58.graphml +32 -0
  287. data/test/third_party_tests/rgl_tests/examples/north/g.10.6.graphml +26 -0
  288. data/test/third_party_tests/rgl_tests/examples/north/g.10.60.graphml +32 -0
  289. data/test/third_party_tests/rgl_tests/examples/north/g.10.61.graphml +34 -0
  290. data/test/third_party_tests/rgl_tests/examples/north/g.10.62.graphml +34 -0
  291. data/test/third_party_tests/rgl_tests/examples/north/g.10.68.graphml +30 -0
  292. data/test/third_party_tests/rgl_tests/examples/north/g.10.69.graphml +32 -0
  293. data/test/third_party_tests/rgl_tests/examples/north/g.10.7.graphml +29 -0
  294. data/test/third_party_tests/rgl_tests/examples/north/g.10.70.graphml +26 -0
  295. data/test/third_party_tests/rgl_tests/examples/north/g.10.71.graphml +27 -0
  296. data/test/third_party_tests/rgl_tests/examples/north/g.10.72.graphml +28 -0
  297. data/test/third_party_tests/rgl_tests/examples/north/g.10.74.graphml +29 -0
  298. data/test/third_party_tests/rgl_tests/examples/north/g.10.75.graphml +29 -0
  299. data/test/third_party_tests/rgl_tests/examples/north/g.10.78.graphml +27 -0
  300. data/test/third_party_tests/rgl_tests/examples/north/g.10.79.graphml +34 -0
  301. data/test/third_party_tests/rgl_tests/examples/north/g.10.8.graphml +29 -0
  302. data/test/third_party_tests/rgl_tests/examples/north/g.10.80.graphml +34 -0
  303. data/test/third_party_tests/rgl_tests/examples/north/g.10.82.graphml +35 -0
  304. data/test/third_party_tests/rgl_tests/examples/north/g.10.83.graphml +32 -0
  305. data/test/third_party_tests/rgl_tests/examples/north/g.10.85.graphml +34 -0
  306. data/test/third_party_tests/rgl_tests/examples/north/g.10.86.graphml +34 -0
  307. data/test/third_party_tests/rgl_tests/examples/north/g.10.88.graphml +37 -0
  308. data/test/third_party_tests/rgl_tests/examples/north/g.10.89.graphml +29 -0
  309. data/test/third_party_tests/rgl_tests/examples/north/g.10.9.graphml +26 -0
  310. data/test/third_party_tests/rgl_tests/examples/north/g.10.90.graphml +32 -0
  311. data/test/third_party_tests/rgl_tests/examples/north/g.10.91.graphml +31 -0
  312. data/test/third_party_tests/rgl_tests/examples/north/g.10.92.graphml +26 -0
  313. data/test/third_party_tests/rgl_tests/examples/north/g.10.93.graphml +32 -0
  314. data/test/third_party_tests/rgl_tests/examples/north/g.10.94.graphml +34 -0
  315. data/test/third_party_tests/rgl_tests/examples/north/g.12.8.graphml +40 -0
  316. data/test/third_party_tests/rgl_tests/examples/north/g.14.9.graphml +36 -0
  317. data/test/third_party_tests/rgl_tests/test_helper.rb +7 -0
  318. data/test/third_party_tests/test_inheritable_attributes.rb +187 -0
  319. metadata +470 -0
@@ -0,0 +1,26 @@
1
+ module Laser
2
+ module Analysis
3
+ module ControlFlow
4
+ # Finds the properties of how the code yields to a block argument.
5
+ # Should not be used on top-level code, naturally.
6
+ module MethodCallSearch
7
+ def find_method_calls(method_to_find, opts)
8
+ possible_calls = []
9
+ reachable_vertices do |block|
10
+ block.instructions.each do |insn|
11
+ cur_insn = insn
12
+ if (insn.type == :call || insn.type == :call_vararg)
13
+ # check if method could be from insn receiver
14
+ if insn.possible_methods(opts).include?(method_to_find)
15
+ possible_calls << insn
16
+ end
17
+ end
18
+ end
19
+ end
20
+ possible_calls
21
+ end
22
+ end
23
+ end # ControlFlow
24
+ end # Analysis
25
+ end #
26
+
@@ -0,0 +1,25 @@
1
+ module Laser
2
+ module Analysis
3
+ module ControlFlow
4
+ # Finds the properties of how the code yields to a block argument.
5
+ # Should not be used on top-level code, naturally.
6
+ module RaiseProperties
7
+ def find_raise_properties
8
+ find_raise_frequency
9
+ end
10
+
11
+ # Finds whether the method raises always, never, or sometimes.
12
+ def find_raise_frequency
13
+ fail_block = exception_postdominator
14
+ if fail_block.nil? || fail_block.real_predecessors.empty?
15
+ @raise_frequency = Frequency::NEVER
16
+ elsif (@exit.normal_predecessors & @exit.real_predecessors).empty?
17
+ @raise_frequency = Frequency::ALWAYS
18
+ else
19
+ @raise_frequency = Frequency::MAYBE
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,385 @@
1
+ module Laser
2
+ module Analysis
3
+ module ControlFlow
4
+ # Simulation of a CFG. Requires values for the formal arguments, if any.
5
+ # Stops as soon as an unpredictable statement is reached.
6
+ module Simulation
7
+ class SimulationError < StandardError; end
8
+ class NonDeterminismHappened < StandardError; end
9
+ class SimulationNonterminationError < StandardError; end
10
+ class ExitedNormally < StandardError
11
+ attr_reader :result
12
+ def initialize(result)
13
+ @result = result
14
+ end
15
+ end
16
+ class ExitedAbnormally < StandardError
17
+ attr_reader :error
18
+ def initialize(error)
19
+ @error = error
20
+ end
21
+ end
22
+ MAX_SIMULATION_BLOCKS = 100_000
23
+ DEFAULT_SIMULATION_OPTS =
24
+ {on_raise: :annotate, invocation_sites: Hash.new { |h, k| h[k] = Set.new },
25
+ invocation_counts: Hash.new do |h1, block|
26
+ h1[block] = Hash.new { |h2, callsite| h2[callsite] = 0 }
27
+ end,
28
+ remaining_blocks: MAX_SIMULATION_BLOCKS,
29
+ method: nil }
30
+ # simulates the CFG, with different possible assumptions about
31
+ # how we should treat the global environment/self object.
32
+ def simulate(formal_vals=[], opts={})
33
+ opts = DEFAULT_SIMULATION_OPTS.merge(opts)
34
+ opts[:formals] = formal_vals
35
+ clear_analyses
36
+ current_block = opts[:start_block] || @enter
37
+ previous_block = nil
38
+ begin
39
+ loop do
40
+ simulate_take_step(opts)
41
+ from, next_block = simulate_block(current_block,
42
+ opts.merge(previous_block: previous_block, current_block: current_block))
43
+ from.add_flag(next_block, ControlFlowGraph::EDGE_EXECUTABLE)
44
+ current_block, previous_block = next_block, current_block
45
+ end
46
+ rescue ExitedNormally => err
47
+ current_block.add_flag(current_block.normal_successors.first,
48
+ ControlFlowGraph::EDGE_EXECUTABLE)
49
+ err.result
50
+ rescue NonDeterminismHappened => err
51
+ Laser.debug_puts "Simulation ended at nondeterminism: #{err.message}"
52
+ Laser.debug_puts '>>> -- Starting Backup CP -- <<<'
53
+ perform_constant_propagation(initial_block: current_block, no_wipe: true)
54
+ Laser.debug_puts '>>> -- Finished Backup CP -- <<<'
55
+ raise err
56
+ rescue SimulationNonterminationError => err
57
+ Laser.debug_puts "Simulation failed to terminate: #{err.message}"
58
+ Laser.debug_p err.backtrace
59
+ @root.add_error(TopLevelSimulationRaised.new(err.message, @root, err))
60
+ rescue ExitedAbnormally => err
61
+ current_block.add_flag(current_block.exception_successors.first,
62
+ ControlFlowGraph::EDGE_EXECUTABLE)
63
+ if opts[:on_raise] == :annotate
64
+ msg = LaserObject === err.error ? err.error.laser_simulate('message', []) : err.error.message
65
+ Laser.debug_puts "Simulation exited abnormally: #{msg}"
66
+ @root.add_error(TopLevelSimulationRaised.new(msg, @root, err.error))
67
+ elsif opts[:on_raise] == :raise
68
+ raise err
69
+ end
70
+ rescue NotImplementedError => err
71
+ Laser.debug_puts "Simulation attempted: #{err.message}"
72
+ Laser.debug_p err.backtrace
73
+ end
74
+ end
75
+
76
+ def simulate_take_step(opts)
77
+ if (opts[:remaining_blocks] -= 1) <= 0
78
+ raise SimulationNonterminationError.new('Simulation failed to terminate')
79
+ end
80
+ end
81
+
82
+ def simulate_block(block, opts)
83
+ return if block.name == 'Exit'
84
+
85
+ Laser.debug_puts "Entering block #{block.name}"
86
+ # phi nodes always go first
87
+ block.phi_nodes.each do |node|
88
+ simulate_deterministic_phi_node(node, opts)
89
+ end
90
+ block.natural_instructions[0..-2].each do |insn|
91
+ simulate_instruction(insn, opts)
92
+ end
93
+ if block.instructions.empty?
94
+ [opts[:current_block], block.real_successors.first]
95
+ else
96
+ simulate_exit_instruction(block.instructions.last, opts)
97
+ end
98
+ end
99
+
100
+ def simulate_exit_instruction(insn, opts)
101
+ Laser.debug_puts "Simulating exit insn: #{insn.inspect}"
102
+ natural_exit = insn.block.normal_successors.first
103
+ case insn[0]
104
+ when :jump
105
+ [opts[:current_block], insn.block.real_successors.first]
106
+ when :branch
107
+ Laser.debug_puts "Branching on: #{insn[1].value.inspect}"
108
+ [opts[:current_block], insn[1].value ? insn.true_successor : insn.false_successor]
109
+ when :call, :call_vararg, :super, :super_vararg
110
+ # todo: block edge!
111
+ begin
112
+ simulate_instruction(insn, opts)
113
+ if (call_block = insn[-1][:block])
114
+ block_proc = call_block.value
115
+ if opts[:invocation_counts][block_proc][opts[:current_block]] > 0
116
+ executed_succ = opts[:current_block].successors.find { |b| b.name == block_proc.start_block.name }
117
+ opts[:current_block].add_flag(executed_succ,
118
+ ControlFlowGraph::EDGE_EXECUTABLE)
119
+ [self[block_proc.exit_block], natural_exit]
120
+ else
121
+ [opts[:current_block], natural_exit]
122
+ end
123
+ else
124
+ [opts[:current_block], natural_exit]
125
+ end
126
+ rescue ExitedAbnormally => err
127
+ Laser.debug_puts "Exception raised by call, taking abnormal edge. Error: #{err.error}"
128
+ Laser.debug_pp(err.backtrace)
129
+ [opts[:current_block], insn.block.exception_successors.first]
130
+ end
131
+ when :return
132
+ raise ExitedNormally.new(insn[1].value)
133
+ when :raise
134
+ raise ExitedAbnormally.new(insn[1].value)
135
+ else
136
+ raise ArgumentError.new("Unexpected instruction type #{insn[0].inspect}")
137
+ end
138
+ end
139
+
140
+ def simulate_deterministic_phi_node(node, opts)
141
+ # Laser.debug_puts "Simulating #{node.inspect} from #{opts[:previous_block].name}"
142
+ index_of_predecessor = node.block.predecessors.to_a.index(opts[:previous_block])
143
+ simulate_assignment(node[1], node[2 + index_of_predecessor], opts)
144
+ end
145
+
146
+ def simulate_assignment(lhs, rhs, opts)
147
+ if Bindings::Base === rhs
148
+ lhs.bind! rhs.value
149
+ else
150
+ lhs.bind! rhs
151
+ end
152
+ end
153
+
154
+ def simulate_instruction(insn, opts)
155
+ Laser.debug_puts "Simulating insn: #{insn.inspect}"
156
+ case insn[0]
157
+ when :assign then simulate_assignment(insn[1], insn[2], opts)
158
+ when :call, :call_vararg
159
+ # cases: special method we intercept, builtin we direct-send, and cfg we simulate
160
+ simulate_call_instruction(insn, opts)
161
+ when :super, :super_vararg
162
+ if opts[:method].nil?
163
+ raise ExitedAbnormally.new(NoMethodError.new('super called outside of method'))
164
+ else
165
+ simulate_call_instruction(insn, opts)
166
+ end
167
+ when :declare
168
+ # do nothing
169
+ else
170
+ raise ArgumentError.new("Unexpected instruction type #{insn[0].inspect}")
171
+ end
172
+ end
173
+
174
+ def simulate_call_instruction(insn, opts)
175
+ if insn.operands.any? { |op| op.value == VARYING || op.value == UNDEFINED }
176
+ raise NonDeterminismHappened.new(
177
+ "Nondeterministic operand (#{op.name}=#{op.value} in #{insn.inspect})")
178
+ end
179
+ receiver = insn[2].value
180
+ klass = Utilities.klass_for(receiver)
181
+ if insn.type == :call || insn.type == :call_vararg
182
+ method = klass.instance_method(insn[3]) # normal method dispatch
183
+ else
184
+ # super method dispatch
185
+ method = opts[:method].owner.parent.instance_method(opts[:method].name)
186
+ end
187
+ if !method
188
+ simulate_method_missing(insn, klass)
189
+ elsif should_simulate_call(method, opts)
190
+ simulate_call(receiver, method, insn, opts)
191
+ else
192
+ raise NonDeterminismHappened.new("Nondeterministic call: #{method.owner.name}##{method.name}")
193
+ end
194
+ end
195
+
196
+ def simulate_call(receiver, method, insn, opts)
197
+ args = simulate_args(insn)
198
+ block_to_use = insn[-1][:block] && insn[-1][:block].value
199
+ result = simulate_call_dispatch(receiver, method, args, block_to_use, opts)
200
+ insn[1].bind! result if insn[1]
201
+ end
202
+
203
+ def simulate_args(insn)
204
+ case insn.type
205
+ when :call
206
+ insn[4..-2].map(&:value)
207
+ when :call_vararg
208
+ insn[4].value
209
+ when :super
210
+ insn[2..-2].map(&:value)
211
+ when :super_vararg
212
+ insn[2].value
213
+ end
214
+ end
215
+
216
+ def should_simulate_call(method, opts)
217
+ method.predictable && (opts[:mutation] || !method.mutation)
218
+ end
219
+
220
+ def simulate_call_dispatch(receiver, method, args, block, opts)
221
+ Laser.debug_puts("simulate_call(#{receiver.inspect}, #{method.name}, #{args.inspect}, #{block.inspect}, #{opts.inspect})")
222
+ opts = opts.merge(method: method)
223
+ if block
224
+ new_invocation_sites = opts[:invocation_sites].merge(block => opts[:invocation_sites][block] | Set[opts[:current_block]])
225
+ opts = opts.merge(invocation_sites: new_invocation_sites, on_raise: :raise)
226
+ end
227
+ method.been_used!
228
+ if method.special
229
+ simulate_special_method(receiver, method, args, block, opts)
230
+ elsif method.builtin
231
+ begin
232
+ if !block
233
+ receiver.send(method.name, *args)
234
+ else
235
+ result = receiver.send(method.name, *args) do |*given_args, &given_blk|
236
+ # self is this because no builtins change self... right?
237
+ block.simulate(given_args, given_blk, opts)
238
+ end
239
+ result
240
+ end
241
+ rescue ExitedAbnormally => abnormal
242
+ Bootstrap::EXCEPTION_STACK.value.push(abnormal.error)
243
+ raise abnormal
244
+ # Extremely unsafe exception handler: assumes my code does not raise
245
+ # exceptions!
246
+ rescue Exception => err
247
+ Laser.debug_puts("Internal exception raised: #{err.message}")
248
+ Laser.debug_pp(err.backtrace)
249
+ Bootstrap::EXCEPTION_STACK.value.push(err)
250
+ raise ExitedAbnormally.new(err)
251
+ end
252
+ else
253
+ Laser.debug_puts "About to simulate #{method.owner.name}##{method.name}"
254
+ result = method.simulate_with_args(receiver, args, block, opts)
255
+ Laser.debug_puts "Finished simulating #{method.owner.name}##{method.name} => #{result.inspect}"
256
+ result
257
+ end
258
+ end
259
+
260
+ def simulate_method_missing(insn, klass)
261
+ error_klass = insn.node.type == :vcall ? 'NameError' : 'NoMethodError'
262
+ missing_method_error = ClassRegistry[error_klass].laser_simulate(
263
+ 'new', ["Method missing: #{klass.name}##{insn[3]}", insn[3].to_s])
264
+ Bootstrap::EXCEPTION_STACK.value.push(missing_method_error)
265
+ raise ExitedAbnormally.new(missing_method_error)
266
+ end
267
+
268
+ def simulate_special_method(receiver, method, args, block, opts)
269
+ case method
270
+ when ClassRegistry['Class'].instance_method(:allocate)
271
+ LaserObject.new(receiver, nil)
272
+ when ClassRegistry['Class'].singleton_class.instance_method(:new)
273
+ LaserClass.new(ClassRegistry['Class'], nil) do |klass|
274
+ klass.superclass = args.first
275
+ end
276
+ when ClassRegistry['Module'].singleton_class.instance_method(:new)
277
+ LaserModule.new
278
+ when ClassRegistry['Kernel'].instance_method(:require)
279
+ simulate_require(args)
280
+ when ClassRegistry['Kernel'].instance_method(:send)
281
+ method_name, *actual_args = args
282
+ klass = Utilities.klass_for(receiver)
283
+ method = klass.instance_method(method_name)
284
+ if should_simulate_call(method, opts)
285
+ simulate_call_dispatch(receiver, method, actual_args, block, opts)
286
+ else
287
+ raise NonDeterminismHappened.new("Nondeterministic call: #{method.inspect}")
288
+ end
289
+ when ClassRegistry['Module'].instance_method(:define_method)
290
+ simulate_define_method(receiver, args, block)
291
+ when ClassRegistry['Module'].instance_method(:module_eval)
292
+ simulate_module_eval(receiver, args, block)
293
+ when ClassRegistry['Laser#Magic'].singleton_class.instance_method(:get_global)
294
+ Scope::GlobalScope.lookup(args.first).value
295
+ when ClassRegistry['Laser#Magic'].singleton_class.instance_method(:set_global)
296
+ Scope::GlobalScope.lookup(args[0]).bind!(args[1])
297
+ when ClassRegistry['Laser#Magic'].singleton_class.instance_method(:current_self)
298
+ opts[:self]
299
+ when ClassRegistry['Laser#Magic'].singleton_class.instance_method(:current_block)
300
+ opts[:block]
301
+ when ClassRegistry['Laser#Magic'].singleton_class.instance_method(:current_arity)
302
+ opts[:formals].size
303
+ when ClassRegistry['Laser#Magic'].singleton_class.instance_method(:current_argument)
304
+ opts[:formals][args.first]
305
+ when ClassRegistry['Laser#Magic'].singleton_class.instance_method(:current_argument_range)
306
+ opts[:formals][args[0], args[1]]
307
+ when ClassRegistry['Laser#Magic'].singleton_class.instance_method(:current_exception),
308
+ ClassRegistry['Laser#Magic'].singleton_class.instance_method(:get_just_raised_exception)
309
+ Bootstrap::EXCEPTION_STACK.value.last
310
+ when ClassRegistry['Laser#Magic'].singleton_class.instance_method(:push_exception)
311
+ Bootstrap::EXCEPTION_STACK.value.push args[0]
312
+ when ClassRegistry['Laser#Magic'].singleton_class.instance_method(:pop_exception)
313
+ Bootstrap::EXCEPTION_STACK.value.pop
314
+ when ClassRegistry['Laser#Magic'].singleton_class.instance_method(:responds?)
315
+ receiver, method_name = args
316
+ Utilities.klass_for(receiver).instance_method(method_name)
317
+ when Scope::GlobalScope.self_ptr.singleton_class.instance_method(:private)
318
+ ClassRegistry['Object'].private(*args)
319
+ when Scope::GlobalScope.self_ptr.singleton_class.instance_method(:public)
320
+ ClassRegistry['Object'].public(*args)
321
+ end
322
+ end
323
+
324
+ def reset_simulation!
325
+ all_variables.each do |temp|
326
+ temp.bind! UNDEFINED
327
+ temp.inferred_type = nil
328
+ end
329
+ vertices.each do |block|
330
+ block.successors.each do |succ|
331
+ block.remove_flag(succ, ControlFlowGraph::EDGE_EXECUTABLE)
332
+ end
333
+ end
334
+ end
335
+
336
+ def simulate_define_method(receiver, args, block)
337
+ if args.size == 1 && block
338
+ receiver.define_method(args.first, block)
339
+ elsif args.size == 2
340
+ receiver.define_method(args[0], args[1])
341
+ else
342
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 1..2)")
343
+ end
344
+ end
345
+
346
+ # TODO(adgar): validate arguments
347
+ # TODO(adgar): make errors visible
348
+ def simulate_require(args)
349
+ file = args.first
350
+ load_path = Scope::GlobalScope.lookup('$:').value
351
+ loaded_values = Scope::GlobalScope.lookup('$"').value
352
+ to_load = file + '.rb'
353
+ load_path.each do |path|
354
+ joined = File.join(path, to_load)
355
+ if File.exist?(joined)
356
+ if !loaded_values.include?(joined)
357
+ tree = Annotations.annotate_inputs([[joined, File.read(joined)]], optimize: false)
358
+ #node.errors.concat tree[0][1].all_errors
359
+ return true
360
+ end
361
+ return false
362
+ end
363
+ end
364
+ raise LoadError.new("No such file: #{file}")
365
+ end
366
+
367
+ def simulate_module_eval(receiver, args, block)
368
+ # essentially: parse, compile with a custom scope + lexical target (cref), simulate.
369
+ if args.size > 0
370
+ text = args[0]
371
+ file = args[1] || "(eval)"
372
+ line = args[2] || 1 # ignored currently
373
+ tree = Sexp.new(RipperPlus.sexp(text), file, text)
374
+ Annotations.ordered_annotations.each do |annotator|
375
+ annotator.annotate_with_text(tree, text)
376
+ end
377
+ custom_scope = ClosedScope.new(Scope::GlobalScope, receiver.binding)
378
+ cfg = GraphBuilder.new(tree, [], custom_scope).build
379
+ cfg.analyze
380
+ end
381
+ end
382
+ end # Simulation
383
+ end # ControlFlow
384
+ end # Analysis
385
+ end # Laser
@@ -0,0 +1,185 @@
1
+ module Laser
2
+ module Analysis
3
+ module ControlFlow
4
+ # Methods for computing the static single assignment form of a
5
+ # Control Flow Graph.
6
+ module StaticSingleAssignment
7
+ # SSA Form
8
+ def static_single_assignment_form
9
+ calculate_live
10
+ dom_tree = dominator_tree
11
+ place_phi_nodes(dom_tree)
12
+ ssa_name_formals
13
+ rename_for_ssa(enter, dom_tree)
14
+ @in_ssa = true
15
+ self
16
+ end
17
+
18
+ private
19
+
20
+ # Places phi nodes, minimally, using DF+
21
+ def place_phi_nodes(dom_tree)
22
+ @globals.each do |temp|
23
+ set = @definition_blocks[temp] | Set[enter]
24
+ iterated_dominance_frontier(set, dom_tree).each do |block|
25
+ if @live[temp].include?(block)
26
+ n = block.real_predecessors.size
27
+ block.instructions.unshift(Instruction.new([:phi, temp, *([temp] * n)], block: block))
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ # Sets up SSA to handle the formal arguments
34
+ def ssa_name_formals
35
+ self_binding = @root.scope.lookup('self')
36
+ @name_stack[self_binding].push(self_binding)
37
+ end
38
+
39
+ # Renames all variables in the block, and all blocks it dominates,
40
+ # to SSA-form variables by adding a suffix of the form #\d. Since
41
+ # '#' is not allowed in an identifier's name, it will be clear
42
+ # visually what part of the name is the SSA suffix, and it is trivially
43
+ # stripped algorithmically to determine which original temp it refers to.
44
+ #
45
+ # p.175, Morgan
46
+ def rename_for_ssa(block, dom_tree)
47
+ # Note the definition caused by all phi nodes in the block, as
48
+ # phi nodes are evaluated immediately upon entering a block.
49
+ block.phi_nodes.each do |phi_node|
50
+ temp = phi_node[1]
51
+ @name_stack[temp].push(new_ssa_name(temp))
52
+ ssa_name_for(temp).definition = phi_node
53
+ @all_cached_variables << ssa_name_for(temp)
54
+ end
55
+ # Replace current operands and note new definitions
56
+ block.natural_instructions.each do |ins|
57
+ new_operands = []
58
+ ins.operands.each do |temp|
59
+ ssa_uninitialize_fix(temp, block, ins) if ssa_name_for(temp).nil?
60
+ ssa_name_for(temp).uses << ins
61
+ new_operands << ssa_name_for(temp)
62
+ end
63
+ if ins.block_operand
64
+ new_block_operand = ssa_name_for(ins.block_operand)
65
+ new_block_operand.uses << ins
66
+ ins.replace_block_operand(new_block_operand)
67
+ end
68
+ ins.replace_operands(new_operands) unless ins.operands.empty?
69
+ ins.explicit_targets.each do |temp|
70
+ if temp != Bootstrap::VISIBILITY_STACK
71
+ @name_stack[temp].push(new_ssa_name(temp))
72
+ ssa_name_for(temp).definition = ins
73
+ @all_cached_variables << ssa_name_for(temp)
74
+ end
75
+ end
76
+ end
77
+ # Update all phi nodes this block leads to with the name of
78
+ # the variable this block uses
79
+ # TODO(adgar): make ordering more reliable, it currently relies
80
+ # on the fact that Set uses Hash, and Hashes in 1.9 are ordered
81
+ block.real_successors.each do |succ|
82
+ j = succ.real_predecessors.to_a.index(block)
83
+ tweaked_phi_nodes = ssa_uninitialized_phinode_fix(block, succ, j)
84
+ succ.phi_nodes.each do |phi_node|
85
+ replacement = ssa_name_for(phi_node[j + 2])
86
+ phi_node[j + 2] = replacement
87
+ replacement.uses << phi_node
88
+ end
89
+ tweaked_phi_nodes.each do |phi_node|
90
+ @name_stack[phi_node[1]].pop
91
+ end
92
+ end
93
+ # Recurse to dominated blocks
94
+ dom_tree[block].each_real_predecessors do |pred|
95
+ rename_for_ssa(self[pred], dom_tree)
96
+ end
97
+ # Update all targets with the current definition
98
+ block.natural_instructions.reverse_each do |ins|
99
+ ins.explicit_targets.each do |target|
100
+ if target != Bootstrap::VISIBILITY_STACK
101
+ ins.replace_target(target, @name_stack[target].pop)
102
+ end
103
+ end
104
+ end
105
+
106
+ block.phi_nodes.each do |ins|
107
+ ins[1] = @name_stack[ins[1]].pop
108
+ end
109
+ end
110
+
111
+ def ssa_uninitialized_phinode_fix(block, succ, j)
112
+ phi_nodes_with_undefined_ops = succ.phi_nodes.select do |phi_node|
113
+ ssa_name_for(phi_node[j+2]).nil?
114
+ end
115
+ if phi_nodes_with_undefined_ops.any?
116
+ fixup_block = ssa_phinode_fixup_block(block, succ, j)
117
+ phi_nodes_with_undefined_ops.each do |phi_node|
118
+ assign = ssa_uninitialize_fixing_instruction(
119
+ phi_node[1], phi_node, fixup_block, true)
120
+ fixup_block.instructions << assign
121
+ end
122
+ fixup_block.instructions << Instruction.new([:jump, succ.name], node: nil, block: fixup_block)
123
+ end
124
+ phi_nodes_with_undefined_ops
125
+ end
126
+
127
+ def ssa_phinode_fixup_block(predecessor, block, j)
128
+ fixup_block = BasicBlock.new("SSA-FIX-#{block.name}-#{j}")
129
+ add_vertex(fixup_block)
130
+
131
+ predecessor.insert_block_on_edge(block, fixup_block)
132
+
133
+ exit_insn = predecessor.instructions.last
134
+ if exit_insn && exit_insn.type == :jump
135
+ exit_insn[1] = fixup_block.name
136
+ elsif exit_insn && exit_insn.type == :branch
137
+ exit_insn[exit_insn.index(block.name)] = fixup_block.name
138
+ end
139
+
140
+ fixup_block
141
+ end
142
+
143
+ # If a block uses a variable in a non-phi instruction, but there
144
+ # is no name for that variable on the current path, then it is
145
+ # being read before it has been written. Uninitialized variables
146
+ # have value nil, so before the read, insert an assignment to
147
+ # nil. SSA will take over from there.
148
+ def ssa_uninitialize_fix(temp, block, ins)
149
+ assignment = ssa_uninitialize_fixing_instruction(temp, ins, block)
150
+ block.instructions.insert(block.instructions.index(ins), assignment)
151
+ end
152
+
153
+ def ssa_uninitialize_fixing_instruction(temp, reading_ins, block, renamed=false)
154
+ @name_stack[temp].push(new_ssa_name(temp))
155
+ @all_cached_variables << ssa_name_for(temp)
156
+ target = renamed ? ssa_name_for(temp) : temp
157
+ assignment = Instruction.new([:assign, target, nil],
158
+ node: reading_ins.node, block: block)
159
+ ssa_name_for(temp).definition = assignment
160
+ end
161
+
162
+ def ssa_name_for(temp)
163
+ @name_stack[temp].last
164
+ end
165
+
166
+ def new_ssa_name(temp)
167
+ @name_count[temp] += 1
168
+ name = "#{temp.name}##{@name_count[temp]}"
169
+ result = Bindings::TemporaryBinding.new(name, nil)
170
+ if temp == @final_return
171
+ @final_return = result
172
+ elsif temp == @final_exception
173
+ @final_exception = result
174
+ elsif temp == @block_register
175
+ @block_register = result
176
+ elsif (scope_owner = temp.self_owner)
177
+ result.self_owner = scope_owner
178
+ scope_owner.self_ptr = result
179
+ end
180
+ result
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end