aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe')
-rw-r--r--lib/hipe/Makefile21
-rw-r--r--lib/hipe/amd64/Makefile23
-rw-r--r--lib/hipe/amd64/hipe_amd64_assemble.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_defuse.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_encode.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_frame.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_liveness.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_main.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_pp.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_ra.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_ra_finalise.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_ra_ls.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_ra_naive.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_ra_postconditions.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl39
-rw-r--r--lib/hipe/amd64/hipe_amd64_ra_x87_ls.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_registers.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_spill_restore.erl23
-rw-r--r--lib/hipe/amd64/hipe_amd64_x87.erl23
-rw-r--r--lib/hipe/amd64/hipe_rtl_to_amd64.erl23
-rw-r--r--lib/hipe/arm/Makefile23
-rw-r--r--lib/hipe/arm/hipe_arm.erl23
-rw-r--r--lib/hipe/arm/hipe_arm.hrl23
-rw-r--r--lib/hipe/arm/hipe_arm_assemble.erl25
-rw-r--r--lib/hipe/arm/hipe_arm_cfg.erl23
-rw-r--r--lib/hipe/arm/hipe_arm_defuse.erl23
-rw-r--r--lib/hipe/arm/hipe_arm_encode.erl23
-rw-r--r--lib/hipe/arm/hipe_arm_finalise.erl23
-rw-r--r--lib/hipe/arm/hipe_arm_frame.erl23
-rw-r--r--lib/hipe/arm/hipe_arm_liveness_gpr.erl23
-rw-r--r--lib/hipe/arm/hipe_arm_main.erl23
-rw-r--r--lib/hipe/arm/hipe_arm_pp.erl21
-rw-r--r--lib/hipe/arm/hipe_arm_ra.erl23
-rw-r--r--lib/hipe/arm/hipe_arm_ra_finalise.erl23
-rw-r--r--lib/hipe/arm/hipe_arm_ra_ls.erl23
-rw-r--r--lib/hipe/arm/hipe_arm_ra_naive.erl23
-rw-r--r--lib/hipe/arm/hipe_arm_ra_postconditions.erl23
-rw-r--r--lib/hipe/arm/hipe_arm_registers.erl31
-rw-r--r--lib/hipe/arm/hipe_rtl_to_arm.erl32
-rw-r--r--lib/hipe/cerl/Makefile23
-rw-r--r--lib/hipe/cerl/cerl_cconv.erl34
-rw-r--r--lib/hipe/cerl/cerl_closurean.erl21
-rw-r--r--lib/hipe/cerl/cerl_hipe_primops.hrl23
-rw-r--r--lib/hipe/cerl/cerl_hipeify.erl33
-rw-r--r--lib/hipe/cerl/cerl_lib.erl23
-rw-r--r--lib/hipe/cerl/cerl_messagean.erl21
-rw-r--r--lib/hipe/cerl/cerl_pmatch.erl61
-rw-r--r--lib/hipe/cerl/cerl_prettypr.erl41
-rw-r--r--lib/hipe/cerl/cerl_to_icode.erl33
-rw-r--r--lib/hipe/cerl/cerl_typean.erl23
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl289
-rw-r--r--lib/hipe/cerl/erl_types.erl2494
-rw-r--r--lib/hipe/doc/Makefile21
-rw-r--r--lib/hipe/doc/src/Makefile21
-rw-r--r--lib/hipe/doc/src/book.xml21
-rw-r--r--lib/hipe/doc/src/hipe_app.xml38
-rw-r--r--lib/hipe/doc/src/notes.xml296
-rw-r--r--lib/hipe/doc/src/part_notes.xml23
-rw-r--r--lib/hipe/doc/src/ref_man.xml23
-rw-r--r--lib/hipe/flow/Makefile23
-rw-r--r--lib/hipe/flow/cfg.hrl33
-rw-r--r--lib/hipe/flow/cfg.inc23
-rw-r--r--lib/hipe/flow/ebb.inc23
-rw-r--r--lib/hipe/flow/hipe_bb.erl23
-rw-r--r--lib/hipe/flow/hipe_bb.hrl23
-rw-r--r--lib/hipe/flow/hipe_dominators.erl23
-rw-r--r--lib/hipe/flow/hipe_gen_cfg.erl23
-rw-r--r--lib/hipe/flow/liveness.inc23
-rw-r--r--lib/hipe/icode/Makefile25
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl87
-rw-r--r--lib/hipe/icode/hipe_icode.erl71
-rw-r--r--lib/hipe/icode/hipe_icode.hrl28
-rw-r--r--lib/hipe/icode/hipe_icode_bincomp.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_call_elim.erl78
-rw-r--r--lib/hipe/icode/hipe_icode_callgraph.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_cfg.erl26
-rw-r--r--lib/hipe/icode/hipe_icode_coordinator.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_ebb.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_exceptions.erl41
-rw-r--r--lib/hipe/icode/hipe_icode_fp.erl423
-rw-r--r--lib/hipe/icode/hipe_icode_heap_test.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_inline_bifs.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_instruction_counter.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_liveness.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_mulret.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_pp.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_primops.erl69
-rw-r--r--lib/hipe/icode/hipe_icode_primops.hrl23
-rw-r--r--lib/hipe/icode/hipe_icode_range.erl177
-rw-r--r--lib/hipe/icode/hipe_icode_split_arith.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_ssa.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_ssa_const_prop.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_ssa_copy_prop.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl27
-rw-r--r--lib/hipe/icode/hipe_icode_type.erl55
-rw-r--r--lib/hipe/icode/hipe_icode_type.hrl23
-rw-r--r--lib/hipe/llvm/Makefile40
-rw-r--r--lib/hipe/llvm/elf_format.erl654
-rw-r--r--lib/hipe/llvm/elf_format.hrl40
-rw-r--r--lib/hipe/llvm/hipe_llvm.erl98
-rw-r--r--lib/hipe/llvm/hipe_llvm_main.erl191
-rw-r--r--lib/hipe/llvm/hipe_llvm_merge.erl2
-rw-r--r--lib/hipe/llvm/hipe_rtl_to_llvm.erl45
-rw-r--r--lib/hipe/main/Makefile23
-rw-r--r--lib/hipe/main/hipe.app.src28
-rw-r--r--lib/hipe/main/hipe.appup.src23
-rw-r--r--lib/hipe/main/hipe.erl222
-rw-r--r--lib/hipe/main/hipe.hrl.src66
-rw-r--r--lib/hipe/main/hipe_main.erl51
-rw-r--r--lib/hipe/misc/Makefile23
-rw-r--r--lib/hipe/misc/hipe_consttab.erl36
-rw-r--r--lib/hipe/misc/hipe_consttab.hrl25
-rw-r--r--lib/hipe/misc/hipe_data_pp.erl23
-rw-r--r--lib/hipe/misc/hipe_gensym.erl23
-rw-r--r--lib/hipe/misc/hipe_pack_constants.erl23
-rw-r--r--lib/hipe/misc/hipe_sdi.erl23
-rw-r--r--lib/hipe/misc/hipe_sdi.hrl23
-rw-r--r--lib/hipe/opt/Makefile23
-rw-r--r--lib/hipe/opt/hipe_schedule.erl23
-rw-r--r--lib/hipe/opt/hipe_schedule_prio.erl23
-rw-r--r--lib/hipe/opt/hipe_spillmin.erl23
-rw-r--r--lib/hipe/opt/hipe_spillmin_color.erl23
-rw-r--r--lib/hipe/opt/hipe_spillmin_scan.erl23
-rw-r--r--lib/hipe/opt/hipe_target_machine.erl23
-rw-r--r--lib/hipe/opt/hipe_ultra_mod2.erl23
-rw-r--r--lib/hipe/opt/hipe_ultra_prio.erl23
-rw-r--r--lib/hipe/ppc/Makefile23
-rw-r--r--lib/hipe/ppc/hipe_ppc.erl33
-rw-r--r--lib/hipe/ppc/hipe_ppc.hrl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_assemble.erl30
-rw-r--r--lib/hipe/ppc/hipe_ppc_cfg.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_defuse.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_encode.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_finalise.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_frame.erl21
-rw-r--r--lib/hipe/ppc/hipe_ppc_liveness_all.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_liveness_fpr.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_liveness_gpr.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_main.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_pp.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_ra.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_ra_finalise.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_ra_ls.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_ra_naive.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_ra_postconditions.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl23
-rw-r--r--lib/hipe/ppc/hipe_ppc_registers.erl23
-rw-r--r--lib/hipe/ppc/hipe_rtl_to_ppc.erl21
-rw-r--r--lib/hipe/regalloc/Makefile23
-rw-r--r--lib/hipe/regalloc/hipe_adj_list.erl23
-rw-r--r--lib/hipe/regalloc/hipe_amd64_specific.erl23
-rw-r--r--lib/hipe/regalloc/hipe_amd64_specific_sse2.erl23
-rw-r--r--lib/hipe/regalloc/hipe_amd64_specific_x87.erl23
-rw-r--r--lib/hipe/regalloc/hipe_arm_specific.erl23
-rw-r--r--lib/hipe/regalloc/hipe_coalescing_regalloc.erl23
-rw-r--r--lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl23
-rw-r--r--lib/hipe/regalloc/hipe_ig.erl23
-rw-r--r--lib/hipe/regalloc/hipe_ig_moves.erl23
-rw-r--r--lib/hipe/regalloc/hipe_ls_regalloc.erl23
-rw-r--r--lib/hipe/regalloc/hipe_moves.erl23
-rw-r--r--lib/hipe/regalloc/hipe_node_sets.erl23
-rw-r--r--lib/hipe/regalloc/hipe_optimistic_regalloc.erl23
-rw-r--r--lib/hipe/regalloc/hipe_ppc_specific.erl23
-rw-r--r--lib/hipe/regalloc/hipe_ppc_specific_fp.erl23
-rw-r--r--lib/hipe/regalloc/hipe_reg_worklists.erl23
-rw-r--r--lib/hipe/regalloc/hipe_regalloc_loop.erl23
-rw-r--r--lib/hipe/regalloc/hipe_sparc_specific.erl23
-rw-r--r--lib/hipe/regalloc/hipe_sparc_specific_fp.erl23
-rw-r--r--lib/hipe/regalloc/hipe_spillcost.erl23
-rw-r--r--lib/hipe/regalloc/hipe_spillcost.hrl23
-rw-r--r--lib/hipe/regalloc/hipe_temp_map.erl23
-rw-r--r--lib/hipe/regalloc/hipe_x86_specific.erl23
-rw-r--r--lib/hipe/regalloc/hipe_x86_specific_x87.erl23
-rw-r--r--lib/hipe/rtl/Makefile23
-rw-r--r--lib/hipe/rtl/hipe_icode2rtl.erl23
-rw-r--r--lib/hipe/rtl/hipe_rtl.erl30
-rw-r--r--lib/hipe/rtl/hipe_rtl.hrl23
-rw-r--r--lib/hipe/rtl/hipe_rtl_arch.erl21
-rw-r--r--lib/hipe/rtl/hipe_rtl_arith.inc91
-rw-r--r--lib/hipe/rtl/hipe_rtl_arith_32.erl26
-rw-r--r--lib/hipe/rtl/hipe_rtl_arith_64.erl23
-rw-r--r--lib/hipe/rtl/hipe_rtl_binary.erl167
-rw-r--r--lib/hipe/rtl/hipe_rtl_binary_construct.erl670
-rw-r--r--lib/hipe/rtl/hipe_rtl_binary_match.erl207
-rw-r--r--lib/hipe/rtl/hipe_rtl_cfg.erl23
-rw-r--r--lib/hipe/rtl/hipe_rtl_cleanup_const.erl23
-rw-r--r--lib/hipe/rtl/hipe_rtl_exceptions.erl23
-rw-r--r--lib/hipe/rtl/hipe_rtl_lcm.erl104
-rw-r--r--lib/hipe/rtl/hipe_rtl_liveness.erl23
-rw-r--r--lib/hipe/rtl/hipe_rtl_mk_switch.erl23
-rw-r--r--lib/hipe/rtl/hipe_rtl_primops.erl23
-rw-r--r--lib/hipe/rtl/hipe_rtl_ssa.erl23
-rw-r--r--lib/hipe/rtl/hipe_rtl_ssa_avail_expr.erl23
-rw-r--r--lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl23
-rw-r--r--lib/hipe/rtl/hipe_rtl_ssapre.erl497
-rw-r--r--lib/hipe/rtl/hipe_rtl_symbolic.erl23
-rw-r--r--lib/hipe/rtl/hipe_rtl_varmap.erl23
-rw-r--r--lib/hipe/rtl/hipe_tagscheme.erl75
-rw-r--r--lib/hipe/sparc/Makefile23
-rw-r--r--lib/hipe/sparc/hipe_rtl_to_sparc.erl63
-rw-r--r--lib/hipe/sparc/hipe_sparc.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc.hrl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_assemble.erl25
-rw-r--r--lib/hipe/sparc/hipe_sparc_cfg.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_defuse.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_encode.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_finalise.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_frame.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_liveness_all.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_liveness_fpr.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_liveness_gpr.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_main.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_pp.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_ra.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_ra_finalise.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_ra_ls.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_ra_naive.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_ra_postconditions.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_ra_postconditions_fp.erl23
-rw-r--r--lib/hipe/sparc/hipe_sparc_registers.erl31
-rw-r--r--lib/hipe/ssa/hipe_ssa.inc23
-rw-r--r--lib/hipe/ssa/hipe_ssa_const_prop.inc23
-rw-r--r--lib/hipe/ssa/hipe_ssa_copy_prop.inc23
-rw-r--r--lib/hipe/ssa/hipe_ssa_liveness.inc23
-rw-r--r--lib/hipe/test/Makefile11
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_arith.erl72
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_beam_instrs.erl102
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_bifs.erl257
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_bignums.erl143
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_boolean.erl47
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_bugs_beam.erl138
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl463
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_comparisons.erl157
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_exceptions.erl465
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_floats.erl250
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_fun.erl124
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_guards.erl164
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_inline_function.erl73
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_inline_module.erl31
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_issues_beam.erl326
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_issues_hipe.erl153
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_lists.erl61
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_module_info.erl32
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_pattern_match.erl46
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_random.erl238
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_receive.erl56
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_records.erl28
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_strength_reduce.erl65
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_switches.erl52
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_tail_rec.erl39
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_tuples.erl177
-rw-r--r--lib/hipe/test/bs_SUITE_data/bs_add.erl10
-rw-r--r--lib/hipe/test/bs_SUITE_data/bs_construct.erl177
-rw-r--r--lib/hipe/test/bs_SUITE_data/bs_match.erl120
-rw-r--r--lib/hipe/test/bs_SUITE_data/bs_match_compiler.erl1235
-rw-r--r--lib/hipe/test/bs_SUITE_data/bs_split.erl10
-rw-r--r--lib/hipe/test/bs_SUITE_data/bs_utf.erl344
-rw-r--r--lib/hipe/test/hipe_SUITE.erl22
-rw-r--r--lib/hipe/test/hipe_testsuite_driver.erl42
-rw-r--r--lib/hipe/test/maps_SUITE_data/maps_map_size.erl6
-rw-r--r--lib/hipe/test/maps_SUITE_data/maps_map_sort_literals.erl31
-rw-r--r--lib/hipe/test/maps_SUITE_data/maps_put_map_assoc.erl2
-rw-r--r--lib/hipe/test/maps_SUITE_data/maps_put_map_exact.erl4
-rw-r--r--lib/hipe/test/maps_SUITE_data/maps_update_assoc.erl2
-rw-r--r--lib/hipe/test/maps_SUITE_data/maps_update_exact.erl10
-rw-r--r--lib/hipe/test/maps_SUITE_data/maps_update_map_expressions.erl6
-rw-r--r--lib/hipe/test/opt_verify_SUITE.erl62
-rw-r--r--lib/hipe/test/opt_verify_SUITE_data/call_elim_test.erl12
-rw-r--r--lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_no_opt_poss.erl32
-rw-r--r--lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl32
-rw-r--r--lib/hipe/test/sanity_SUITE_data/sanity_comp_timeout.erl28
-rw-r--r--lib/hipe/test/sanity_SUITE_data/sanity_no_zombies.erl21
-rw-r--r--lib/hipe/tools/Makefile23
-rw-r--r--lib/hipe/tools/hipe_jit.erl23
-rw-r--r--lib/hipe/tools/hipe_profile.erl23
-rw-r--r--lib/hipe/tools/hipe_timer.erl41
-rw-r--r--lib/hipe/util/Makefile23
-rw-r--r--lib/hipe/util/hipe_digraph.erl21
-rw-r--r--lib/hipe/util/hipe_dot.erl23
-rw-r--r--lib/hipe/util/hipe_timing.erl23
-rw-r--r--lib/hipe/util/hipe_vectors.erl23
-rw-r--r--lib/hipe/util/hipe_vectors.hrl23
-rw-r--r--lib/hipe/vsn.mk2
-rw-r--r--lib/hipe/x86/Makefile23
-rw-r--r--lib/hipe/x86/hipe_rtl_to_x86.erl23
-rw-r--r--lib/hipe/x86/hipe_x86.erl23
-rw-r--r--lib/hipe/x86/hipe_x86.hrl23
-rw-r--r--lib/hipe/x86/hipe_x86_assemble.erl25
-rw-r--r--lib/hipe/x86/hipe_x86_cfg.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_defuse.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_encode.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_frame.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_liveness.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_main.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_postpass.erl26
-rw-r--r--lib/hipe/x86/hipe_x86_pp.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_ra.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_ra_finalise.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_ra_ls.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_ra_naive.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_ra_postconditions.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_ra_x87_ls.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_registers.erl23
-rw-r--r--lib/hipe/x86/hipe_x86_spill_restore.erl21
-rw-r--r--lib/hipe/x86/hipe_x86_x87.erl23
305 files changed, 13065 insertions, 5716 deletions
diff --git a/lib/hipe/Makefile b/lib/hipe/Makefile
index 46cbc33ae2..0676484fca 100644
--- a/lib/hipe/Makefile
+++ b/lib/hipe/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
diff --git a/lib/hipe/amd64/Makefile b/lib/hipe/amd64/Makefile
index 50cd024d72..8dc2af2679 100644
--- a/lib/hipe/amd64/Makefile
+++ b/lib/hipe/amd64/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2012. All Rights Reserved.
+# Copyright Ericsson AB 2004-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -72,7 +73,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += -DHIPE_AMD64 +warn_exported_vars
+ERL_COMPILE_FLAGS += -DHIPE_AMD64 -Werror +warn_export_vars
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/amd64/hipe_amd64_assemble.erl b/lib/hipe/amd64/hipe_amd64_assemble.erl
index db3cfcc6bd..a7b11f7c72 100644
--- a/lib/hipe/amd64/hipe_amd64_assemble.erl
+++ b/lib/hipe/amd64/hipe_amd64_assemble.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_defuse.erl b/lib/hipe/amd64/hipe_amd64_defuse.erl
index c48e80f3f1..907f078f3f 100644
--- a/lib/hipe/amd64/hipe_amd64_defuse.erl
+++ b/lib/hipe/amd64/hipe_amd64_defuse.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_encode.erl b/lib/hipe/amd64/hipe_amd64_encode.erl
index cbdab25b25..df15732cea 100644
--- a/lib/hipe/amd64/hipe_amd64_encode.erl
+++ b/lib/hipe/amd64/hipe_amd64_encode.erl
@@ -1,18 +1,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/amd64/hipe_amd64_frame.erl b/lib/hipe/amd64/hipe_amd64_frame.erl
index 2bc319f40f..f3bcdf302a 100644
--- a/lib/hipe/amd64/hipe_amd64_frame.erl
+++ b/lib/hipe/amd64/hipe_amd64_frame.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_liveness.erl b/lib/hipe/amd64/hipe_amd64_liveness.erl
index be878773cb..5cfdbb0f3e 100644
--- a/lib/hipe/amd64/hipe_amd64_liveness.erl
+++ b/lib/hipe/amd64/hipe_amd64_liveness.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_main.erl b/lib/hipe/amd64/hipe_amd64_main.erl
index 4de7364170..c22c6cd73b 100644
--- a/lib/hipe/amd64/hipe_amd64_main.erl
+++ b/lib/hipe/amd64/hipe_amd64_main.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_pp.erl b/lib/hipe/amd64/hipe_amd64_pp.erl
index 93ed7b9073..7c3ee8458a 100644
--- a/lib/hipe/amd64/hipe_amd64_pp.erl
+++ b/lib/hipe/amd64/hipe_amd64_pp.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_ra.erl b/lib/hipe/amd64/hipe_amd64_ra.erl
index b9ac0338f0..1d8453d54d 100644
--- a/lib/hipe/amd64/hipe_amd64_ra.erl
+++ b/lib/hipe/amd64/hipe_amd64_ra.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_ra_finalise.erl b/lib/hipe/amd64/hipe_amd64_ra_finalise.erl
index a6a787c340..d835c3ec14 100644
--- a/lib/hipe/amd64/hipe_amd64_ra_finalise.erl
+++ b/lib/hipe/amd64/hipe_amd64_ra_finalise.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_ra_ls.erl b/lib/hipe/amd64/hipe_amd64_ra_ls.erl
index 7ff2a7c082..9361b91f04 100644
--- a/lib/hipe/amd64/hipe_amd64_ra_ls.erl
+++ b/lib/hipe/amd64/hipe_amd64_ra_ls.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_ra_naive.erl b/lib/hipe/amd64/hipe_amd64_ra_naive.erl
index 194ea8b597..38218a65dc 100644
--- a/lib/hipe/amd64/hipe_amd64_ra_naive.erl
+++ b/lib/hipe/amd64/hipe_amd64_ra_naive.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_ra_postconditions.erl b/lib/hipe/amd64/hipe_amd64_ra_postconditions.erl
index ef3c284c45..2d03239ea6 100644
--- a/lib/hipe/amd64/hipe_amd64_ra_postconditions.erl
+++ b/lib/hipe/amd64/hipe_amd64_ra_postconditions.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl b/lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl
index 9ed3d01a56..b1f7bd7572 100644
--- a/lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl
+++ b/lib/hipe/amd64/hipe_amd64_ra_sse2_postconditions.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -86,22 +87,29 @@ do_fp_unop(I, TempMap) ->
%%% Fix an fmove op.
do_fmove(I, TempMap) ->
#fmove{src=Src,dst=Dst} = I,
- case is_mem_opnd(Dst, TempMap) and is_mem_opnd(Src, TempMap) of
+ case
+ (is_mem_opnd(Src, TempMap) andalso is_mem_opnd(Dst, TempMap))
+ orelse (is_mem_opnd(Src, TempMap) andalso (not is_float_temp(Dst)))
+ orelse ((not is_float_temp(Src)) andalso is_mem_opnd(Dst, TempMap))
+ of
true ->
- Tmp = clone(Src),
+ Tmp = spill_temp(double),
{[#fmove{src=Src, dst=Tmp},I#fmove{src=Tmp,dst=Dst}],
true};
false ->
{[I], false}
end.
+is_float_temp(#x86_temp{type=Type}) -> Type =:= double;
+is_float_temp(#x86_mem{}) -> false.
+
%%% Check if an operand denotes a memory cell (mem or pseudo).
is_mem_opnd(Opnd, TempMap) ->
R =
case Opnd of
#x86_mem{} -> true;
- #x86_temp{} ->
+ #x86_temp{type=double} ->
Reg = hipe_x86:temp_reg(Opnd),
case hipe_x86:temp_is_allocatable(Opnd) of
true ->
@@ -175,6 +183,9 @@ clone(Dst) ->
#x86_mem{} -> hipe_x86:mem_type(Dst);
#x86_temp{} -> hipe_x86:temp_type(Dst)
end,
+ spill_temp(Type).
+
+spill_temp(Type) ->
hipe_x86:mk_new_temp(Type).
%%% Make a certain reg into a clone of Dst
diff --git a/lib/hipe/amd64/hipe_amd64_ra_x87_ls.erl b/lib/hipe/amd64/hipe_amd64_ra_x87_ls.erl
index 267f3335aa..6da3f44cd3 100644
--- a/lib/hipe/amd64/hipe_amd64_ra_x87_ls.erl
+++ b/lib/hipe/amd64/hipe_amd64_ra_x87_ls.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_registers.erl b/lib/hipe/amd64/hipe_amd64_registers.erl
index 4c49eeb00a..780c2cc547 100644
--- a/lib/hipe/amd64/hipe_amd64_registers.erl
+++ b/lib/hipe/amd64/hipe_amd64_registers.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_spill_restore.erl b/lib/hipe/amd64/hipe_amd64_spill_restore.erl
index 56e3ffd24d..61e2dfa26d 100644
--- a/lib/hipe/amd64/hipe_amd64_spill_restore.erl
+++ b/lib/hipe/amd64/hipe_amd64_spill_restore.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_amd64_x87.erl b/lib/hipe/amd64/hipe_amd64_x87.erl
index e7bf1c1866..1f42e4749d 100644
--- a/lib/hipe/amd64/hipe_amd64_x87.erl
+++ b/lib/hipe/amd64/hipe_amd64_x87.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/amd64/hipe_rtl_to_amd64.erl b/lib/hipe/amd64/hipe_rtl_to_amd64.erl
index 17aef0eeac..d55b5b2c22 100644
--- a/lib/hipe/amd64/hipe_rtl_to_amd64.erl
+++ b/lib/hipe/amd64/hipe_rtl_to_amd64.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/Makefile b/lib/hipe/arm/Makefile
index 651b82f1ed..00b6732afa 100644
--- a/lib/hipe/arm/Makefile
+++ b/lib/hipe/arm/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2012. All Rights Reserved.
+# Copyright Ericsson AB 2005-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -73,7 +74,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars
+ERL_COMPILE_FLAGS += -Werror +warn_export_vars
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/arm/hipe_arm.erl b/lib/hipe/arm/hipe_arm.erl
index 391f84ca47..f34525fa3b 100644
--- a/lib/hipe/arm/hipe_arm.erl
+++ b/lib/hipe/arm/hipe_arm.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm.hrl b/lib/hipe/arm/hipe_arm.hrl
index 9ee2cb3d06..558174e3fc 100644
--- a/lib/hipe/arm/hipe_arm.hrl
+++ b/lib/hipe/arm/hipe_arm.hrl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm_assemble.erl b/lib/hipe/arm/hipe_arm_assemble.erl
index e9de96a927..4a245cd853 100644
--- a/lib/hipe/arm/hipe_arm_assemble.erl
+++ b/lib/hipe/arm/hipe_arm_assemble.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -47,7 +48,7 @@ assemble(CompiledCode, Closures, Exports, Options) ->
DataRelocs = hipe_pack_constants:mk_data_relocs(RefsFromConsts, LabelMap),
SSE = hipe_pack_constants:slim_sorted_exportmap(ExportMap,Closures,Exports),
SlimRefs = hipe_pack_constants:slim_refs(AccRefs),
- Bin = term_to_binary([{?VERSION_STRING(),?HIPE_SYSTEM_CRC},
+ Bin = term_to_binary([{?VERSION_STRING(),?HIPE_ERTS_CHECKSUM},
ConstAlign, ConstSize,
SC,
DataRelocs, % nee LM, LabelMap
diff --git a/lib/hipe/arm/hipe_arm_cfg.erl b/lib/hipe/arm/hipe_arm_cfg.erl
index 984a3ccf9e..f2fa0a5164 100644
--- a/lib/hipe/arm/hipe_arm_cfg.erl
+++ b/lib/hipe/arm/hipe_arm_cfg.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm_defuse.erl b/lib/hipe/arm/hipe_arm_defuse.erl
index 8d6efebc21..f57b0e601c 100644
--- a/lib/hipe/arm/hipe_arm_defuse.erl
+++ b/lib/hipe/arm/hipe_arm_defuse.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm_encode.erl b/lib/hipe/arm/hipe_arm_encode.erl
index 19e507fdbd..9368cbf628 100644
--- a/lib/hipe/arm/hipe_arm_encode.erl
+++ b/lib/hipe/arm/hipe_arm_encode.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/arm/hipe_arm_finalise.erl b/lib/hipe/arm/hipe_arm_finalise.erl
index 38e3efd223..a4b2f9c73c 100644
--- a/lib/hipe/arm/hipe_arm_finalise.erl
+++ b/lib/hipe/arm/hipe_arm_finalise.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm_frame.erl b/lib/hipe/arm/hipe_arm_frame.erl
index 316aa2ef82..e1e441a967 100644
--- a/lib/hipe/arm/hipe_arm_frame.erl
+++ b/lib/hipe/arm/hipe_arm_frame.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm_liveness_gpr.erl b/lib/hipe/arm/hipe_arm_liveness_gpr.erl
index cab81c47a1..82cc5a7a67 100644
--- a/lib/hipe/arm/hipe_arm_liveness_gpr.erl
+++ b/lib/hipe/arm/hipe_arm_liveness_gpr.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm_main.erl b/lib/hipe/arm/hipe_arm_main.erl
index 5243b3579e..dce1193b24 100644
--- a/lib/hipe/arm/hipe_arm_main.erl
+++ b/lib/hipe/arm/hipe_arm_main.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm_pp.erl b/lib/hipe/arm/hipe_arm_pp.erl
index c4dde31188..18aca1fc6b 100644
--- a/lib/hipe/arm/hipe_arm_pp.erl
+++ b/lib/hipe/arm/hipe_arm_pp.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm_ra.erl b/lib/hipe/arm/hipe_arm_ra.erl
index bdd9e228e0..2f65e864fd 100644
--- a/lib/hipe/arm/hipe_arm_ra.erl
+++ b/lib/hipe/arm/hipe_arm_ra.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm_ra_finalise.erl b/lib/hipe/arm/hipe_arm_ra_finalise.erl
index 9edc362e90..4faeadcd7f 100644
--- a/lib/hipe/arm/hipe_arm_ra_finalise.erl
+++ b/lib/hipe/arm/hipe_arm_ra_finalise.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm_ra_ls.erl b/lib/hipe/arm/hipe_arm_ra_ls.erl
index 53bfd5b2a3..d9a360d00c 100644
--- a/lib/hipe/arm/hipe_arm_ra_ls.erl
+++ b/lib/hipe/arm/hipe_arm_ra_ls.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/arm/hipe_arm_ra_naive.erl b/lib/hipe/arm/hipe_arm_ra_naive.erl
index 786895f2ca..6201269f44 100644
--- a/lib/hipe/arm/hipe_arm_ra_naive.erl
+++ b/lib/hipe/arm/hipe_arm_ra_naive.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm_ra_postconditions.erl b/lib/hipe/arm/hipe_arm_ra_postconditions.erl
index 96b0d5733f..40978e65f6 100644
--- a/lib/hipe/arm/hipe_arm_ra_postconditions.erl
+++ b/lib/hipe/arm/hipe_arm_ra_postconditions.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/arm/hipe_arm_registers.erl b/lib/hipe/arm/hipe_arm_registers.erl
index ff6a163e9c..dcf039676b 100644
--- a/lib/hipe/arm/hipe_arm_registers.erl
+++ b/lib/hipe/arm/hipe_arm_registers.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -66,6 +67,8 @@
-define(R15, 15).
-define(LAST_PRECOLOURED, 15). % must handle both GPR and FPR ranges
+-define(LR, ?R14).
+
-define(ARG0, ?R1).
-define(ARG1, ?R2).
-define(ARG2, ?R3).
@@ -113,7 +116,7 @@ stack_pointer() -> ?STACK_POINTER.
proc_pointer() -> ?PROC_POINTER.
-lr() -> ?R14.
+lr() -> ?LR.
pc() -> ?R15.
@@ -197,7 +200,9 @@ call_clobbered() -> % does the RA strip the type or not?
].
tailcall_clobbered() -> % tailcall crapola needs one temp
- [{?TEMP1,tagged},{?TEMP1,untagged}].
+ [{?TEMP1,tagged},{?TEMP1,untagged}
+ ,{?LR,tagged},{?LR,untagged}
+ ].
live_at_return() ->
[%%{?LR,untagged},
diff --git a/lib/hipe/arm/hipe_rtl_to_arm.erl b/lib/hipe/arm/hipe_rtl_to_arm.erl
index a4dc5db978..93342aba33 100644
--- a/lib/hipe/arm/hipe_rtl_to_arm.erl
+++ b/lib/hipe/arm/hipe_rtl_to_arm.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -147,10 +148,11 @@ mk_shift_ir(S, Dst, Src1, ShiftOp, Src2) ->
mk_li(Tmp, Src1,
mk_shift_rr(S, Dst, Tmp, ShiftOp, Src2)).
-mk_shift_ri(S, Dst, Src1, ShiftOp, Src2) when is_integer(Src2) ->
- if Src2 >= 0, Src2 < 32 -> ok;
- true -> io:format("~w: excessive immediate shift ~w\n", [?MODULE,Src2])
- end,
+mk_shift_ri(S, Dst, Src1, ShiftOp, 0)
+ when ShiftOp =:= lsl; ShiftOp =:= lsr; ShiftOp =:= asr ->
+ [hipe_arm:mk_move(S, Dst, Src1)];
+mk_shift_ri(S, Dst, Src1, ShiftOp, Src2)
+ when is_integer(Src2), Src2 > 0, Src2 < 32 ->
Am1 = {Src1,ShiftOp,Src2},
[hipe_arm:mk_move(S, Dst, Am1)].
diff --git a/lib/hipe/cerl/Makefile b/lib/hipe/cerl/Makefile
index d13dfb33c2..9f50d6bf91 100644
--- a/lib/hipe/cerl/Makefile
+++ b/lib/hipe/cerl/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2012. All Rights Reserved.
+# Copyright Ericsson AB 2003-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -65,7 +66,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += -Werror +inline +warn_exported_vars +warn_unused_import +warn_missing_spec #+warn_untyped_record
+ERL_COMPILE_FLAGS += +inline -Werror +warn_export_vars +warn_unused_import +warn_missing_spec #+warn_untyped_record
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/cerl/cerl_cconv.erl b/lib/hipe/cerl/cerl_cconv.erl
index cf4d317b0d..ac9d01ab0e 100644
--- a/lib/hipe/cerl/cerl_cconv.erl
+++ b/lib/hipe/cerl/cerl_cconv.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -709,7 +710,7 @@ ren__new() ->
ren__add(Key, Value, Ren) ->
dict:store(Key, Value, Ren).
-ren__map(Key, Ren) ->
+ren__map(Key, Ren) ->
case dict:find(Key, Ren) of
{ok, Value} ->
Value;
@@ -721,11 +722,14 @@ ren__map(Key, Ren) ->
%% ---------------------------------------------------------------------
%% State
--record(state, {module :: module(), function :: {atom(), arity()},
- names, refs, defs = []}).
+-record(state, {module :: module(),
+ function :: {atom(), arity()} | 'undefined',
+ names = sets:new() :: sets:set(), %% XXX: refine
+ refs = dict:new() :: dict:dict(), %% XXX: refine
+ defs = []}).
s__new(Module) ->
- #state{module = Module, names = sets:new(), refs = dict:new()}.
+ #state{module = Module}.
s__add_function_name(Name, S) ->
S#state{names = sets:add_element(Name, S#state.names)}.
diff --git a/lib/hipe/cerl/cerl_closurean.erl b/lib/hipe/cerl/cerl_closurean.erl
index 1b325703ae..d37c91e5c6 100644
--- a/lib/hipe/cerl/cerl_closurean.erl
+++ b/lib/hipe/cerl/cerl_closurean.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/cerl/cerl_hipe_primops.hrl b/lib/hipe/cerl/cerl_hipe_primops.hrl
index a777cd0108..3efb9a3bdd 100644
--- a/lib/hipe/cerl/cerl_hipe_primops.hrl
+++ b/lib/hipe/cerl/cerl_hipe_primops.hrl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/cerl/cerl_hipeify.erl b/lib/hipe/cerl/cerl_hipeify.erl
index 3351be77f2..6611abd204 100644
--- a/lib/hipe/cerl/cerl_hipeify.erl
+++ b/lib/hipe/cerl/cerl_hipeify.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2015. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -622,12 +623,12 @@ ren__map(Key, Ren) ->
%% ---------------------------------------------------------------------
%% State
-%% pmatch = 'true' | 'false' | 'no_duplicates' | 'duplicate_all'
+-type pmatch() :: 'true' | 'false' | 'no_duplicates' | 'duplicate_all'.
--record(state, {module::atom(),
- function::{atom(), 0..256},
- pmatch=true,
- revisit = false}).
+-record(state, {module :: module(),
+ function :: {atom(), arity()} | 'undefined',
+ pmatch = true :: pmatch(),
+ revisit = false :: boolean()}).
s__new(Module) ->
#state{module = Module}.
diff --git a/lib/hipe/cerl/cerl_lib.erl b/lib/hipe/cerl/cerl_lib.erl
index 83bb20e047..0bc77909d9 100644
--- a/lib/hipe/cerl/cerl_lib.erl
+++ b/lib/hipe/cerl/cerl_lib.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/cerl/cerl_messagean.erl b/lib/hipe/cerl/cerl_messagean.erl
index 7911b875a9..7df0a245fb 100644
--- a/lib/hipe/cerl/cerl_messagean.erl
+++ b/lib/hipe/cerl/cerl_messagean.erl
@@ -1,18 +1,19 @@
%% =====================================================================
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/cerl/cerl_pmatch.erl b/lib/hipe/cerl/cerl_pmatch.erl
index 3bc93e80dd..ca27fff1dd 100644
--- a/lib/hipe/cerl/cerl_pmatch.erl
+++ b/lib/hipe/cerl/cerl_pmatch.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -31,7 +32,7 @@
-module(cerl_pmatch).
--define(NO_UNUSED, true).
+%%-define(NO_UNUSED, true).
-export([clauses/2]).
-ifndef(NO_UNUSED).
@@ -59,6 +60,8 @@
%% @see transform/2
-ifndef(NO_UNUSED).
+-spec core_transform(cerl:c_module(), [_]) -> cerl:c_module().
+
core_transform(M, Opts) ->
cerl:to_records(transform(cerl:from_records(M), Opts)).
-endif. % NO_UNUSED
@@ -76,6 +79,8 @@ core_transform(M, Opts) ->
%% @see core_transform/2
-ifndef(NO_UNUSED).
+-spec transform(cerl:cerl(), [_]) -> cerl:cerl().
+
transform(M, _Opts) ->
expr(M, env__empty()).
-endif. % NO_UNUSED
@@ -109,7 +114,7 @@ transform(M, _Opts) ->
%% @see expr/2
%% @see transform/2
--spec clauses([cerl:cerl()], rec_env:environment()) ->
+-spec clauses([cerl:cerl(),...], rec_env:environment()) ->
{cerl:cerl(), [cerl:cerl()]}.
clauses(Cs, Env) ->
@@ -226,12 +231,9 @@ match_typegroup(T, V, Vs, Gs, Else, Env) ->
Else, Env),
typetest_clause(T, V, Body, Env).
-match_congroup({?binary_id, Segs}, Vs, Cs, _Else, Env) ->
- Ref = get_unique(),
- Guard = cerl:c_primop(cerl:c_atom(set_label), [cerl:c_int(Ref)]),
- NewElse = cerl:c_primop(cerl:c_atom(goto_label), [cerl:c_int(Ref)]),
- Body = match(Vs, Cs, NewElse, Env),
- cerl:c_clause([make_pat(?binary_id, Segs)], Guard, Body);
+match_congroup({?binary_id, Segs}, Vs, Cs, Else, Env) ->
+ Body = match(Vs, Cs, Else, Env),
+ cerl:c_clause([make_pat(?binary_id, Segs)], Body);
match_congroup({D, A}, Vs, Cs, Else, Env) ->
Vs1 = new_vars(A, Env),
@@ -406,8 +408,19 @@ make_let(Vs, A, B) ->
%% @see rec_env
-ifndef(NO_UNUSED).
+-spec expr(cerl:cerl(), rec_env:environment()) -> cerl:cerl().
+
expr(E, Env) ->
case cerl:type(E) of
+ binary ->
+ Es = expr_list(cerl:binary_segments(E), Env),
+ cerl:update_c_binary(E, Es);
+ bitstr ->
+ V = expr(cerl:bitstr_val(E), Env),
+ Sz = expr(cerl:bitstr_size(E), Env),
+ Unit = expr(cerl:bitstr_unit(E), Env),
+ Type = expr(cerl:bitstr_type(E), Env),
+ cerl:update_c_bitstr(E, V, Sz, Unit, Type, cerl:bitstr_flags(E));
literal ->
E;
var ->
@@ -577,16 +590,6 @@ is_simple(E) ->
end.
-get_unique() ->
- case get(unique_label) of
- undefined ->
- put(unique_label, 1),
- 0;
- N ->
- put(unique_label, N+1),
- N
- end.
-
%% ---------------------------------------------------------------------
%% Abstract datatype: environment()
diff --git a/lib/hipe/cerl/cerl_prettypr.erl b/lib/hipe/cerl/cerl_prettypr.erl
index f4a67439d6..f0acab99e3 100644
--- a/lib/hipe/cerl/cerl_prettypr.erl
+++ b/lib/hipe/cerl/cerl_prettypr.erl
@@ -1,18 +1,19 @@
%% =====================================================================
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -63,8 +64,8 @@
seq_arg/1, seq_body/1, string_lit/1, try_arg/1,
try_body/1, try_vars/1, try_evars/1, try_handler/1,
tuple_es/1, type/1, values_es/1, var_name/1,
- c_map/1, map_arg/1, map_es/1, is_c_map_empty/1,
- c_map_pair/2, map_pair_key/1, map_pair_val/1, map_pair_op/1
+ map_arg/1, map_es/1, is_c_map_empty/1,
+ map_pair_key/1, map_pair_val/1, map_pair_op/1
]).
-define(PAPER, 76).
@@ -498,12 +499,8 @@ lay_literal(Node, Ctxt) ->
lay_cons(Node, Ctxt);
V when is_tuple(V) ->
lay_tuple(Node, Ctxt);
- M when is_map(M), map_size(M) =:= 0 ->
- text("~{}~");
M when is_map(M) ->
- lay_map(c_map([c_map_pair(abstract(K),abstract(V))
- || {K,V} <- maps:to_list(M)]),
- Ctxt)
+ lay_map(Node, Ctxt)
end.
lay_var(Node, Ctxt) ->
@@ -626,12 +623,10 @@ lay_map_pair(Node, Ctxt) ->
K = map_pair_key(Node),
V = map_pair_val(Node),
OpTxt = case concrete(map_pair_op(Node)) of
- assoc -> "::<";
- exact -> "~<"
+ assoc -> "=>";
+ exact -> ":="
end,
- beside(floating(text(OpTxt)),
- beside(lay(K,Ctxt),beside(floating(text(",")), beside(lay(V,Ctxt),
- floating(text(">")))))).
+ beside(lay(K,Ctxt),beside(floating(text(OpTxt)),lay(V,Ctxt))).
lay_let(Node, Ctxt) ->
V = lay_value_list(let_vars(Node), Ctxt),
diff --git a/lib/hipe/cerl/cerl_to_icode.erl b/lib/hipe/cerl/cerl_to_icode.erl
index 2645056be1..ab131c2d01 100644
--- a/lib/hipe/cerl/cerl_to_icode.erl
+++ b/lib/hipe/cerl/cerl_to_icode.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2015. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -110,7 +111,7 @@
effect = false :: boolean(),
fail = [], % [] or fail-to label
class = expr :: 'expr' | 'guard',
- line = 0 :: erl_scan:line(), % current line number
+ line = 0 :: erl_anno:line(), % current line number
'receive' :: 'undefined' | #'receive'{}
}).
@@ -793,9 +794,9 @@ bitstr_gen_op([V], #ctxt{fail=FL, class=guard}, SizeInfo, ConstInfo,
Type, Flags, Base, Offset) ->
SL = new_label(),
case SizeInfo of
- {all,_NewUnit, NewAlign, S1} ->
+ {all, NewUnit, NewAlign, S1} ->
Type = binary,
- Name = {bs_put_binary_all, Flags},
+ Name = {bs_put_binary_all, NewUnit, Flags},
Primop = {hipe_bs_primop, Name},
{add_code([icode_guardop([Offset], Primop,
[V, Base, Offset], SL, FL),
@@ -818,9 +819,9 @@ bitstr_gen_op([V], #ctxt{fail=FL, class=guard}, SizeInfo, ConstInfo,
bitstr_gen_op([V], _Ctxt, SizeInfo, ConstInfo, Type, Flags, Base,
Offset) ->
case SizeInfo of
- {all, _NewUnit, NewAlign, S} ->
+ {all, NewUnit, NewAlign, S} ->
Type = binary,
- Name = {bs_put_binary_all, Flags},
+ Name = {bs_put_binary_all, NewUnit, Flags},
Primop = {hipe_bs_primop, Name},
{add_code([icode_call_primop([Offset], Primop,
[V, Base, Offset])], S),
diff --git a/lib/hipe/cerl/cerl_typean.erl b/lib/hipe/cerl/cerl_typean.erl
index f694c07c82..ddc48c7915 100644
--- a/lib/hipe/cerl/cerl_typean.erl
+++ b/lib/hipe/cerl/cerl_typean.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 74e93bf098..230fce2e68 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -45,7 +46,6 @@
t_bitstr/0,
t_boolean/0,
t_byte/0,
- t_char/0,
t_cons/0,
t_cons/2,
t_cons_hd/1,
@@ -86,13 +86,12 @@
t_is_port/2,
t_is_maybe_improper_list/2,
t_is_reference/2,
- t_is_string/1,
t_is_subtype/2,
t_is_tuple/2,
t_list/0,
t_list/1,
t_list_elements/2,
- t_list_termination/1,
+ t_list_termination/2,
t_mfa/0,
t_module/0,
t_nil/0,
@@ -116,7 +115,16 @@
t_tuple_size/2,
t_tuple_subtypes/2,
t_is_map/2,
- t_map/0
+ t_map/0,
+ t_map/3,
+ t_map_def_key/2,
+ t_map_def_val/2,
+ t_map_get/3,
+ t_map_is_key/3,
+ t_map_entries/2,
+ t_map_put/3,
+ t_map_update/3,
+ t_map_pairwise_merge/4
]).
-ifdef(DO_ERL_BIF_TYPES_TEST).
@@ -138,7 +146,7 @@ type(M, F, A) ->
type(M, F, A, Xs) ->
type(M, F, A, Xs, 'universe').
--type opaques() :: 'universe' | [erl_types:erl_type()].
+-type opaques() :: erl_types:opaques().
-type arg_types() :: [erl_types:erl_type()].
@@ -513,14 +521,15 @@ type(erlang, 'bsl', 2, Xs, Opaques) ->
type(erlang, 'bnot', 1, Xs, Opaques) ->
strict(erlang, 'bnot', 1, Xs,
fun ([X1]) ->
- case arith('bnot', X1, Opaques) of
+ case arith_bnot(X1, Opaques) of
error -> t_integer();
{ok, T} -> T
end
end, Opaques);
%% Guard bif, needs to be here.
type(erlang, abs, 1, Xs, Opaques) ->
- strict(erlang, abs, 1, Xs, fun ([X]) -> X end, Opaques);
+ strict(erlang, abs, 1, Xs,
+ fun ([X1]) -> arith_abs(X1, Opaques) end, Opaques);
%% This returns (-X)-1, so it often gives a negative result.
%% strict(erlang, 'bnot', 1, Xs, fun (_) -> t_integer() end, Opaques);
type(erlang, append, 2, Xs, _Opaques) -> type(erlang, '++', 2, Xs); % alias
@@ -550,9 +559,6 @@ type(erlang, bit_size, 1, Xs, Opaques) ->
type(erlang, byte_size, 1, Xs, Opaques) ->
strict(erlang, byte_size, 1, Xs,
fun (_) -> t_non_neg_integer() end, Opaques);
-type(erlang, disconnect_node, 1, Xs, Opaques) ->
- strict(erlang, disconnect_node, 1, Xs,
- fun (_) -> t_sup([t_boolean(), t_atom('ignored')]) end, Opaques);
%% Guard bif, needs to be here.
%% Also much more expressive than anything you could write in a spec...
type(erlang, element, 2, Xs, Opaques) ->
@@ -581,16 +587,9 @@ type(erlang, element, 2, Xs, Opaques) ->
%% Guard bif, needs to be here.
type(erlang, float, 1, Xs, Opaques) ->
strict(erlang, float, 1, Xs, fun (_) -> t_float() end, Opaques);
-type(erlang, fun_info, 1, Xs, Opaques) ->
- strict(erlang, fun_info, 1, Xs,
- fun (_) -> t_list(t_tuple([t_atom(), t_any()])) end, Opaques);
-type(erlang, get_cookie, 0, _, _Opaques) -> t_atom(); % | t_atom('nocookie')
%% Guard bif, needs to be here.
type(erlang, hd, 1, Xs, Opaques) ->
strict(erlang, hd, 1, Xs, fun ([X]) -> t_cons_hd(X) end, Opaques);
-type(erlang, integer_to_list, 2, Xs, Opaques) ->
- strict(erlang, integer_to_list, 2, Xs,
- fun (_) -> t_string() end, Opaques);
type(erlang, info, 1, Xs, _) -> type(erlang, system_info, 1, Xs); % alias
%% All type tests are guard BIF's and may be implemented in ways that
%% cannot be expressed in a type spec, why they are kept in erl_bif_types.
@@ -765,7 +764,19 @@ type(erlang, length, 1, Xs, Opaques) ->
strict(erlang, length, 1, Xs, fun (_) -> t_non_neg_fixnum() end, Opaques);
%% Guard bif, needs to be here.
type(erlang, map_size, 1, Xs, Opaques) ->
- strict(erlang, map_size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques);
+ type(maps, size, 1, Xs, Opaques);
+type(erlang, make_fun, 3, Xs, Opaques) ->
+ strict(erlang, make_fun, 3, Xs,
+ fun ([_, _, Arity]) ->
+ case t_number_vals(Arity, Opaques) of
+ [N] ->
+ case is_integer(N) andalso 0 =< N andalso N =< 255 of
+ true -> t_fun(N, t_any());
+ false -> t_none()
+ end;
+ _Other -> t_fun()
+ end
+ end, Opaques);
type(erlang, make_tuple, 2, Xs, Opaques) ->
strict(erlang, make_tuple, 2, Xs,
fun ([Int, _]) ->
@@ -782,8 +793,6 @@ type(erlang, make_tuple, 3, Xs, Opaques) ->
_Other -> t_tuple()
end
end, Opaques);
-type(erlang, memory, 0, _, _Opaques) ->
- t_list(t_tuple([t_atom(), t_non_neg_fixnum()]));
type(erlang, nif_error, 1, Xs, Opaques) ->
%% this BIF and the next one are stubs for NIFs and never return
strict(erlang, nif_error, 1, Xs, fun (_) -> t_any() end, Opaques);
@@ -799,8 +808,6 @@ type(erlang, round, 1, Xs, Opaques) ->
strict(erlang, round, 1, Xs, fun (_) -> t_integer() end, Opaques);
%% Guard bif, needs to be here.
type(erlang, self, 0, _, _Opaques) -> t_pid();
-type(erlang, set_cookie, 2, Xs, Opaques) ->
- strict(erlang, set_cookie, 2, Xs, fun (_) -> t_atom('true') end, Opaques);
type(erlang, setelement, 3, Xs, Opaques) ->
strict(erlang, setelement, 3, Xs,
fun ([X1, X2, X3]) ->
@@ -835,19 +842,7 @@ type(erlang, setelement, 3, Xs, Opaques) ->
%% Guard bif, needs to be here.
type(erlang, size, 1, Xs, Opaques) ->
strict(erlang, size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques);
-type(erlang, spawn, 1, Xs, Opaques) ->
- strict(erlang, spawn, 1, Xs, fun (_) -> t_pid() end, Opaques);
-type(erlang, spawn, 2, Xs, Opaques) ->
- strict(erlang, spawn, 2, Xs, fun (_) -> t_pid() end, Opaques);
-type(erlang, spawn, 4, Xs, Opaques) ->
- strict(erlang, spawn, 4, Xs, fun (_) -> t_pid() end, Opaques);
-type(erlang, spawn_link, 1, Xs, _) -> type(erlang, spawn, 1, Xs); % same
-type(erlang, spawn_link, 2, Xs, _) -> type(erlang, spawn, 2, Xs); % same
-type(erlang, spawn_link, 4, Xs, _) -> type(erlang, spawn, 4, Xs); % same
type(erlang, subtract, 2, Xs, _Opaques) -> type(erlang, '--', 2, Xs); % alias
-type(erlang, suspend_process, 1, Xs, Opaques) ->
- strict(erlang, suspend_process, 1, Xs,
- fun (_) -> t_atom('true') end, Opaques);
type(erlang, system_info, 1, Xs, Opaques) ->
strict(erlang, system_info, 1, Xs,
fun ([Type]) ->
@@ -912,8 +907,7 @@ type(erlang, system_info, 1, Xs, Opaques) ->
t_list(t_pid());
['os_type'] ->
t_tuple([t_sup([t_atom('unix'),
- t_atom('win32'),
- t_atom('ose')]),
+ t_atom('win32')]),
t_atom()]);
['os_version'] ->
t_sup(t_tuple([t_non_neg_fixnum(),
@@ -1001,10 +995,6 @@ type(erlang, tuple_to_list, 1, Xs, Opaques) ->
end
end
end, Opaques);
-type(erlang, yield, 0, _, _Opaques) -> t_atom('true');
-%%-- ets ----------------------------------------------------------------------
-type(ets, rename, 2, Xs, Opaques) ->
- strict(ets, rename, 2, Xs, fun ([_, Name]) -> Name end, Opaques);
%%-- hipe_bifs ----------------------------------------------------------------
type(hipe_bifs, add_ref, 2, Xs, Opaques) ->
strict(hipe_bifs, add_ref, 2, Xs, fun (_) -> t_nil() end, Opaques);
@@ -1070,9 +1060,6 @@ type(hipe_bifs, find_na_or_make_stub, 2, Xs, Opaques) ->
type(hipe_bifs, fun_to_address, 1, Xs, Opaques) ->
strict(hipe_bifs, fun_to_address, 1, Xs,
fun (_) -> t_integer() end, Opaques);
-%% type(hipe_bifs, get_emu_address, 1, Xs, Opaques) ->
-%% strict(hipe_bifs, get_emu_address, 1, Xs,
-%% fun (_) -> t_integer() end, Opaques); % address
type(hipe_bifs, get_fe, 2, Xs, Opaques) ->
strict(hipe_bifs, get_fe, 2, Xs, fun (_) -> t_integer() end, Opaques);
type(hipe_bifs, get_rts_param, 1, Xs, Opaques) ->
@@ -1081,9 +1068,6 @@ type(hipe_bifs, get_rts_param, 1, Xs, Opaques) ->
type(hipe_bifs, invalidate_funinfo_native_addresses, 1, Xs, Opaques) ->
strict(hipe_bifs, invalidate_funinfo_native_addresses, 1, Xs,
fun (_) -> t_nil() end, Opaques);
-%% type(hipe_bifs, make_native_stub, 2, Xs, Opaques) ->
-%% strict(hipe_bifs, make_native_stub, 2, Xs,
-%% fun (_) -> t_integer() end, Opaques); % address
type(hipe_bifs, mark_referred_from, 1, Xs, Opaques) ->
strict(hipe_bifs, mark_referred_from, 1, Xs,
fun (_) -> t_nil() end, Opaques);
@@ -1119,8 +1103,8 @@ type(hipe_bifs, set_native_address, 3, Xs, Opaques) ->
type(hipe_bifs, set_native_address_in_fe, 2, Xs, Opaques) ->
strict(hipe_bifs, set_native_address_in_fe, 2, Xs,
fun (_) -> t_atom('true') end, Opaques);
-type(hipe_bifs, system_crc, 1, Xs, Opaques) ->
- strict(hipe_bifs, system_crc, 1, Xs, fun (_) -> t_crc32() end, Opaques);
+type(hipe_bifs, system_crc, 0, _, _Opaques) ->
+ t_crc32();
type(hipe_bifs, term_to_word, 1, Xs, Opaques) ->
strict(hipe_bifs, term_to_word, 1, Xs,
fun (_) -> t_integer() end, Opaques);
@@ -1341,8 +1325,8 @@ type(lists, foldr, 3, Xs, _Opaques) -> type(lists, foldl, 3, Xs); % same
type(lists, keydelete, 3, Xs, Opaques) ->
strict(lists, keydelete, 3, Xs,
fun ([_, _, L]) ->
- Term = t_list_termination(L),
- t_sup(Term, erl_types:lift_list_to_pos_empty(L))
+ Term = t_list_termination(L, Opaques),
+ t_sup(Term, erl_types:lift_list_to_pos_empty(L, Opaques))
end, Opaques);
type(lists, keyfind, 3, Xs, Opaques) ->
strict(lists, keyfind, 3, Xs,
@@ -1670,24 +1654,88 @@ type(lists, zipwith3, 4, Xs, Opaques) ->
fun ([F,_As,_Bs,_Cs]) -> t_sup(t_list(t_fun_range(F, Opaques)),
t_nil()) end, Opaques);
-%%-- string -------------------------------------------------------------------
-type(string, chars, 2, Xs, Opaques) -> % NOTE: added to avoid loss of info
- strict(string, chars, 2, Xs, fun (_) -> t_string() end, Opaques);
-type(string, chars, 3, Xs, Opaques) -> % NOTE: added to avoid loss of info
- strict(string, chars, 3, Xs,
- fun ([Char, N, Tail]) ->
- case t_is_nil(Tail) of
- true ->
- type(string, chars, 2, [Char, N]);
+%%-- maps ---------------------------------------------------------------------
+type(maps, from_list, 1, Xs, Opaques) ->
+ strict(maps, from_list, 1, Xs,
+ fun ([List]) ->
+ case t_is_nil(List, Opaques) of
+ true -> t_from_term(#{});
false ->
- case t_is_string(Tail) of
- true ->
- t_string();
- false ->
- t_sup(t_sup(t_string(), Tail), t_cons(Char, Tail))
+ T = t_list_elements(List, Opaques),
+ case t_tuple_subtypes(T, Opaques) of
+ unknown -> t_map();
+ Stypes when length(Stypes) >= 1 ->
+ t_sup([begin
+ [K, V] = t_tuple_args(Args, Opaques),
+ t_map([], K, V)
+ end || Args <- Stypes])
end
end
end, Opaques);
+type(maps, get, 2, Xs, Opaques) ->
+ strict(maps, get, 2, Xs,
+ fun ([Key, Map]) ->
+ t_map_get(Key, Map, Opaques)
+ end, Opaques);
+type(maps, is_key, 2, Xs, Opaques) ->
+ strict(maps, is_key, 2, Xs,
+ fun ([Key, Map]) ->
+ t_map_is_key(Key, Map, Opaques)
+ end, Opaques);
+type(maps, merge, 2, Xs, Opaques) ->
+ strict(maps, merge, 2, Xs,
+ fun ([MapA, MapB]) ->
+ ADefK = t_map_def_key(MapA, Opaques),
+ BDefK = t_map_def_key(MapB, Opaques),
+ ADefV = t_map_def_val(MapA, Opaques),
+ BDefV = t_map_def_val(MapB, Opaques),
+ t_map(t_map_pairwise_merge(
+ fun(K, _, _, mandatory, V) -> {K, mandatory, V};
+ (K, MNess, VA, optional, VB) -> {K, MNess, t_sup(VA,VB)}
+ end, MapA, MapB, Opaques),
+ t_sup(ADefK, BDefK), t_sup(ADefV, BDefV))
+ end, Opaques);
+type(maps, put, 3, Xs, Opaques) ->
+ strict(maps, put, 3, Xs,
+ fun ([Key, Value, Map]) ->
+ t_map_put({Key, Value}, Map, Opaques)
+ end, Opaques);
+type(maps, size, 1, Xs, Opaques) ->
+ strict(maps, size, 1, Xs,
+ fun ([Map]) ->
+ Mand = [E || E={_,mandatory,_} <- t_map_entries(Map, Opaques)],
+ LowerBound = length(Mand),
+ case t_is_none(t_map_def_key(Map, Opaques)) of
+ false -> t_from_range(LowerBound, pos_inf);
+ true ->
+ Opt = [E || E={_,optional,_} <- t_map_entries(Map, Opaques)],
+ UpperBound = LowerBound + length(Opt),
+ t_from_range(LowerBound, UpperBound)
+ end
+ end, Opaques);
+type(maps, to_list, 1, Xs, Opaques) ->
+ strict(maps, to_list, 1, Xs,
+ fun ([Map]) ->
+ DefK = t_map_def_key(Map, Opaques),
+ DefV = t_map_def_val(Map, Opaques),
+ Pairs = t_map_entries(Map, Opaques),
+ EType = lists:foldl(
+ fun({K,_,V},EType0) ->
+ case t_is_none(V) of
+ true -> t_subtract(EType0, t_tuple([K,t_any()]));
+ false -> t_sup(EType0, t_tuple([K,V]))
+ end
+ end, t_tuple([DefK, DefV]), Pairs),
+ case t_is_none(EType) of
+ true -> t_nil();
+ false -> t_list(EType)
+ end
+ end, Opaques);
+type(maps, update, 3, Xs, Opaques) ->
+ strict(maps, update, 3, Xs,
+ fun ([Key, Value, Map]) ->
+ t_map_update({Key, Value}, Map, Opaques)
+ end, Opaques);
%%-----------------------------------------------------------------------------
type(M, F, A, Xs, _O) when is_atom(M), is_atom(F),
@@ -1932,7 +1980,7 @@ negwidth(X, N) ->
false -> negwidth(X, N+1)
end.
-arith('bnot', X1, Opaques) ->
+arith_bnot(X1, Opaques) ->
case t_is_integer(X1, Opaques) of
false -> error;
true ->
@@ -1942,6 +1990,28 @@ arith('bnot', X1, Opaques) ->
infinity_add(infinity_inv(Min1), -1))}
end.
+arith_abs(X1, Opaques) ->
+ case t_is_integer(X1, Opaques) of
+ false ->
+ case t_is_float(X1, Opaques) of
+ true -> t_float();
+ false -> t_number()
+ end;
+ true ->
+ Min1 = number_min(X1, Opaques),
+ Max1 = number_max(X1, Opaques),
+ {NewMin, NewMax} =
+ case infinity_geq(Min1, 0) of
+ true -> {Min1, Max1};
+ false ->
+ case infinity_geq(Max1, 0) of
+ true -> {0, infinity_inv(Min1)};
+ false -> {infinity_inv(Max1), infinity_inv(Min1)}
+ end
+ end,
+ t_from_range(NewMin, NewMax)
+ end.
+
arith_mult(Min1, Max1, Min2, Max2) ->
Tmp_list = [infinity_mult(Min1, Min2), infinity_mult(Min1, Max2),
infinity_mult(Max1, Min2), infinity_mult(Max1, Max2)],
@@ -2170,7 +2240,7 @@ type_ranks(Type, I, Min, Max, [TypeClass|Rest], Opaques) ->
type_order() ->
[t_number(), t_atom(), t_reference(), t_fun(), t_port(), t_pid(), t_tuple(),
- t_list(), t_binary()].
+ t_map(), t_list(), t_bitstr()].
key_comparisons_fail(X0, KeyPos, TupleList, Opaques) ->
X = case t_is_number(t_inf(X0, t_number(), Opaques), Opaques) of
@@ -2270,9 +2340,7 @@ arg_types(erlang, bit_size, 1) ->
[t_bitstr()];
%% Guard bif, needs to be here.
arg_types(erlang, byte_size, 1) ->
- [t_binary()];
-arg_types(erlang, disconnect_node, 1) ->
- [t_node()];
+ [t_bitstr()];
arg_types(erlang, halt, 0) ->
[];
arg_types(erlang, halt, 1) ->
@@ -2292,17 +2360,11 @@ arg_types(erlang, element, 2) ->
%% Guard bif, needs to be here.
arg_types(erlang, float, 1) ->
[t_number()];
-arg_types(erlang, fun_info, 1) ->
- [t_fun()];
-arg_types(erlang, get_cookie, 0) ->
- [];
%% Guard bif, needs to be here.
arg_types(erlang, hd, 1) ->
[t_cons()];
arg_types(erlang, info, 1) ->
arg_types(erlang, system_info, 1); % alias
-arg_types(erlang, integer_to_list, 2) ->
- [t_integer(), t_from_range(2, 36)];
arg_types(erlang, is_atom, 1) ->
[t_any()];
arg_types(erlang, is_binary, 1) ->
@@ -2343,12 +2405,12 @@ arg_types(erlang, length, 1) ->
%% Guard bif, needs to be here.
arg_types(erlang, map_size, 1) ->
[t_map()];
+arg_types(erlang, make_fun, 3) ->
+ [t_atom(), t_atom(), t_arity()];
arg_types(erlang, make_tuple, 2) ->
[t_non_neg_fixnum(), t_any()]; % the value 0 is OK as first argument
arg_types(erlang, make_tuple, 3) ->
[t_non_neg_fixnum(), t_any(), t_list(t_tuple([t_pos_integer(), t_any()]))];
-arg_types(erlang, memory, 0) ->
- [];
arg_types(erlang, nif_error, 1) ->
[t_any()];
arg_types(erlang, nif_error, 2) ->
@@ -2365,29 +2427,13 @@ arg_types(erlang, round, 1) ->
%% Guard bif, needs to be here.
arg_types(erlang, self, 0) ->
[];
-arg_types(erlang, set_cookie, 2) ->
- [t_node(), t_atom()];
arg_types(erlang, setelement, 3) ->
[t_pos_integer(), t_tuple(), t_any()];
%% Guard bif, needs to be here.
arg_types(erlang, size, 1) ->
[t_sup(t_tuple(), t_binary())];
-arg_types(erlang, spawn, 1) -> %% TODO: Tuple?
- [t_fun()];
-arg_types(erlang, spawn, 2) -> %% TODO: Tuple?
- [t_node(), t_fun()];
-arg_types(erlang, spawn, 4) -> %% TODO: Tuple?
- [t_node(), t_atom(), t_atom(), t_list()];
-arg_types(erlang, spawn_link, 1) ->
- arg_types(erlang, spawn, 1); % same
-arg_types(erlang, spawn_link, 2) ->
- arg_types(erlang, spawn, 2); % same
-arg_types(erlang, spawn_link, 4) ->
- arg_types(erlang, spawn, 4); % same
arg_types(erlang, subtract, 2) ->
arg_types(erlang, '--', 2);
-arg_types(erlang, suspend_process, 1) ->
- [t_pid()];
arg_types(erlang, system_info, 1) ->
[t_sup([t_atom(), % documented
t_tuple([t_atom(), t_any()]), % documented
@@ -2406,11 +2452,6 @@ arg_types(erlang, tuple_size, 1) ->
[t_tuple()];
arg_types(erlang, tuple_to_list, 1) ->
[t_tuple()];
-arg_types(erlang, yield, 0) ->
- [];
-%%------- ets -----------------------------------------------------------------
-arg_types(ets, rename, 2) ->
- [t_atom(), t_atom()];
%%------- hipe_bifs -----------------------------------------------------------
arg_types(hipe_bifs, add_ref, 2) ->
[t_mfa(), t_tuple([t_mfa(),
@@ -2462,16 +2503,12 @@ arg_types(hipe_bifs, find_na_or_make_stub, 2) ->
[t_mfa(), t_boolean()];
arg_types(hipe_bifs, fun_to_address, 1) ->
[t_mfa()];
-%% arg_types(hipe_bifs, get_emu_address, 1) ->
-%% [t_mfa()];
arg_types(hipe_bifs, get_fe, 2) ->
[t_atom(), t_tuple([t_integer(), t_integer(), t_integer()])];
arg_types(hipe_bifs, get_rts_param, 1) ->
[t_fixnum()];
arg_types(hipe_bifs, invalidate_funinfo_native_addresses, 1) ->
[t_list(t_mfa())];
-%% arg_types(hipe_bifs, make_native_stub, 2) ->
-%% [t_integer(), t_arity()];
arg_types(hipe_bifs, mark_referred_from, 1) ->
[t_mfa()];
arg_types(hipe_bifs, merge_term, 1) ->
@@ -2500,8 +2537,8 @@ arg_types(hipe_bifs, set_native_address, 3) ->
[t_mfa(), t_integer(), t_boolean()];
arg_types(hipe_bifs, set_native_address_in_fe, 2) ->
[t_integer(), t_integer()];
-arg_types(hipe_bifs, system_crc, 1) ->
- [t_crc32()];
+arg_types(hipe_bifs, system_crc, 0) ->
+ [];
arg_types(hipe_bifs, term_to_word, 1) ->
[t_any()];
arg_types(hipe_bifs, update_code_size, 3) ->
@@ -2611,13 +2648,23 @@ arg_types(lists, zipwith, 3) ->
[t_fun([t_any(), t_any()], t_any()), t_list(), t_list()];
arg_types(lists, zipwith3, 4) ->
[t_fun([t_any(), t_any(), t_any()], t_any()), t_list(), t_list(), t_list()];
-
-%%------- string --------------------------------------------------------------
-arg_types(string, chars, 2) ->
- [t_char(), t_non_neg_integer()];
-arg_types(string, chars, 3) ->
- [t_char(), t_non_neg_integer(), t_any()];
-%%-----------------------------------------------------------------------------
+%%------- maps ----------------------------------------------------------------
+arg_types(maps, from_list, 1) ->
+ [t_list(t_tuple(2))];
+arg_types(maps, get, 2) ->
+ [t_any(), t_map()];
+arg_types(maps, is_key, 2) ->
+ [t_any(), t_map()];
+arg_types(maps, merge, 2) ->
+ [t_map(), t_map()];
+arg_types(maps, put, 3) ->
+ [t_any(), t_any(), t_map()];
+arg_types(maps, size, 1) ->
+ [t_map()];
+arg_types(maps, to_list, 1) ->
+ [t_map()];
+arg_types(maps, update, 3) ->
+ [t_any(), t_any(), t_map()];
arg_types(M, F, A) when is_atom(M), is_atom(F),
is_integer(A), 0 =< A, A =< 255 ->
unknown. % safe approximation for all functions.
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 4215448c61..15f7b793a1 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -40,7 +41,6 @@
any_none_or_unit/1,
lookup_record/3,
max/2,
- module_builtin_opaques/1,
min/2,
number_max/1, number_max/2,
number_min/1, number_min/2,
@@ -68,7 +68,6 @@
t_cons/2,
t_cons_hd/1, t_cons_hd/2,
t_cons_tl/1, t_cons_tl/2,
- t_constant/0,
t_contains_opaque/1, t_contains_opaque/2,
t_decorate_with_opaque/3,
t_elements/1,
@@ -79,10 +78,11 @@
t_non_neg_fixnum/0,
t_pos_fixnum/0,
t_float/0,
+ t_var_names/1,
t_form_to_string/1,
- t_from_form/1,
- t_from_form/2,
- t_from_form/3,
+ t_from_form/6,
+ t_from_form_without_remote/3,
+ t_check_record_fields/6,
t_from_range/2,
t_from_range_unsafe/2,
t_from_term/1,
@@ -118,7 +118,6 @@
%% t_is_byte/1,
%% t_is_char/1,
t_is_cons/1, t_is_cons/2,
- t_is_constant/1,
t_is_equal/2,
t_is_fixnum/1,
t_is_float/1, t_is_float/2,
@@ -139,7 +138,8 @@
t_is_port/1, t_is_port/2,
t_is_maybe_improper_list/1, t_is_maybe_improper_list/2,
t_is_reference/1, t_is_reference/2,
- t_is_remote/1,
+ t_is_singleton/1,
+ t_is_singleton/2,
t_is_string/1,
t_is_subtype/2,
t_is_tuple/1, t_is_tuple/2,
@@ -149,9 +149,18 @@
t_list/0,
t_list/1,
t_list_elements/1, t_list_elements/2,
- t_list_termination/1,
+ t_list_termination/1, t_list_termination/2,
t_map/0,
t_map/1,
+ t_map/3,
+ t_map_entries/2, t_map_entries/1,
+ t_map_def_key/2, t_map_def_key/1,
+ t_map_def_val/2, t_map_def_val/1,
+ t_map_get/2, t_map_get/3,
+ t_map_is_key/2, t_map_is_key/3,
+ t_map_update/2, t_map_update/3,
+ t_map_pairwise_merge/4,
+ t_map_put/2, t_map_put/3,
t_matchstate/0,
t_matchstate/2,
t_matchstate_present/1,
@@ -172,23 +181,20 @@
t_number_vals/1, t_number_vals/2,
t_opaque_from_records/1,
t_opaque_structure/1,
- %% t_parameterized_module/0,
t_pid/0,
t_port/0,
t_maybe_improper_list/0,
%% t_maybe_improper_list/2,
t_product/1,
t_reference/0,
- t_remote/3,
+ t_singleton_to_term/2,
t_string/0,
t_struct_from_opaque/2,
- t_solve_remote/3,
t_subst/2,
t_subtract/2,
t_subtract_list/2,
t_sup/1,
t_sup/2,
- t_tid/0,
t_timeout/0,
t_to_string/1,
t_to_string/2,
@@ -209,11 +215,12 @@
type_is_defined/4,
record_field_diffs_to_string/2,
subst_all_vars_to_any/1,
- subst_all_remote/2,
- lift_list_to_pos_empty/1,
+ lift_list_to_pos_empty/1, lift_list_to_pos_empty/2,
is_opaque_type/2,
is_erl_type/1,
- atom_to_string/1
+ atom_to_string/1,
+ var_table__new/0,
+ cache__new/0
]).
%%-define(DO_ERL_TYPES_TEST, true).
@@ -229,7 +236,7 @@
-export([t_is_identifier/1]).
-endif.
--export_type([erl_type/0, type_table/0, var_table/0]).
+-export_type([erl_type/0, opaques/0, type_table/0, var_table/0, cache/0]).
%%-define(DEBUG, true).
@@ -250,6 +257,8 @@
%%
-define(REC_TYPE_LIMIT, 2).
+-define(EXPAND_DEPTH, 16).
+-define(EXPAND_LIMIT, 10000).
-define(TUPLE_TAG_LIMIT, 5).
-define(TUPLE_ARITY_LIMIT, 8).
@@ -279,7 +288,6 @@
-define(number_tag, number).
-define(opaque_tag, opaque).
-define(product_tag, product).
--define(remote_tag, remote).
-define(tuple_set_tag, tuple_set).
-define(tuple_tag, tuple).
-define(union_tag, union).
@@ -287,7 +295,7 @@
-type tag() :: ?atom_tag | ?binary_tag | ?function_tag | ?identifier_tag
| ?list_tag | ?map_tag | ?matchstate_tag | ?nil_tag | ?number_tag
- | ?opaque_tag | ?product_tag | ?remote_tag
+ | ?opaque_tag | ?product_tag
| ?tuple_tag | ?tuple_set_tag | ?union_tag | ?var_tag.
-define(float_qual, float).
@@ -319,7 +327,7 @@
%% Auxiliary types and convenient macros
%%
--type parse_form() :: {atom(), _, _} | {atom(), _, _, _} | {'op', _, _, _, _}. %% XXX: Temporarily
+-type parse_form() :: erl_parse:abstract_type().
-type rng_elem() :: 'pos_inf' | 'neg_inf' | integer().
-record(int_set, {set :: [integer()]}).
@@ -329,7 +337,6 @@
%% was updated to 2.7 due to this change.
-record(opaque, {mod :: module(), name :: atom(),
args = [] :: [erl_type()], struct :: erl_type()}).
--record(remote, {mod:: module(), name :: atom(), args = [] :: [erl_type()]}).
-define(atom(Set), #c{tag=?atom_tag, elements=Set}).
-define(bitstr(Unit, Base), #c{tag=?binary_tag, elements=[Unit,Base]}).
@@ -346,10 +353,10 @@
-define(nonempty_list(Types, Term),?list(Types, Term, ?nonempty_qual)).
-define(number(Set, Qualifier), #c{tag=?number_tag, elements=Set,
qualifier=Qualifier}).
--define(map(Pairs), #c{tag=?map_tag, elements=Pairs}).
+-define(map(Pairs,DefKey,DefVal),
+ #c{tag=?map_tag, elements={Pairs,DefKey,DefVal}}).
-define(opaque(Optypes), #c{tag=?opaque_tag, elements=Optypes}).
-define(product(Types), #c{tag=?product_tag, elements=Types}).
--define(remote(RemTypes), #c{tag=?remote_tag, elements=RemTypes}).
-define(tuple(Types, Arity, Qual), #c{tag=?tuple_tag, elements=Types,
qualifier={Arity, Qual}}).
-define(tuple_set(Tuples), #c{tag=?tuple_set_tag, elements=Tuples}).
@@ -367,31 +374,32 @@
-type opaques() :: [erl_type()] | 'universe'.
-type record_key() :: {'record', atom()}.
--type type_key() :: {'type' | 'opaque', atom(), arity()}.
--type record_value() :: orddict:orddict(). % XXX. To be refined
--type type_value() :: {module(), erl_type(), atom()}.
--type type_table() :: dict:dict(record_key(), record_value())
- | dict:dict(type_key(), type_value()).
+-type type_key() :: {'type' | 'opaque', mfa()}.
+-type record_value() :: [{atom(), erl_parse:abstract_expr(), erl_type()}].
+-type type_value() :: {{module(), {file:name(), erl_anno:line()},
+ erl_parse:abstract_type(), ArgNames :: [atom()]},
+ erl_type()}.
+-type type_table() :: dict:dict(record_key() | type_key(),
+ record_value() | type_value()).
--type var_table() :: dict:dict(atom(), erl_type()).
+-opaque var_table() :: #{atom() => erl_type()}.
%%-----------------------------------------------------------------------------
%% Unions
%%
--define(union(List), #c{tag=?union_tag, elements=[_,_,_,_,_,_,_,_,_,_,_]=List}).
-
--define(atom_union(T), ?union([T,?none,?none,?none,?none,?none,?none,?none,?none,?none,?none])).
--define(bitstr_union(T), ?union([?none,T,?none,?none,?none,?none,?none,?none,?none,?none,?none])).
--define(function_union(T), ?union([?none,?none,T,?none,?none,?none,?none,?none,?none,?none,?none])).
--define(identifier_union(T), ?union([?none,?none,?none,T,?none,?none,?none,?none,?none,?none,?none])).
--define(list_union(T), ?union([?none,?none,?none,?none,T,?none,?none,?none,?none,?none,?none])).
--define(number_union(T), ?union([?none,?none,?none,?none,?none,T,?none,?none,?none,?none,?none])).
--define(tuple_union(T), ?union([?none,?none,?none,?none,?none,?none,T,?none,?none,?none,?none])).
--define(matchstate_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,T,?none,?none,?none])).
--define(opaque_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,T,?none,?none])).
--define(remote_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,T,?none])).
--define(map_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,?none,T])).
+-define(union(List), #c{tag=?union_tag, elements=[_,_,_,_,_,_,_,_,_,_]=List}).
+
+-define(atom_union(T), ?union([T,?none,?none,?none,?none,?none,?none,?none,?none,?none])).
+-define(bitstr_union(T), ?union([?none,T,?none,?none,?none,?none,?none,?none,?none,?none])).
+-define(function_union(T), ?union([?none,?none,T,?none,?none,?none,?none,?none,?none,?none])).
+-define(identifier_union(T), ?union([?none,?none,?none,T,?none,?none,?none,?none,?none,?none])).
+-define(list_union(T), ?union([?none,?none,?none,?none,T,?none,?none,?none,?none,?none])).
+-define(number_union(T), ?union([?none,?none,?none,?none,?none,T,?none,?none,?none,?none])).
+-define(tuple_union(T), ?union([?none,?none,?none,?none,?none,?none,T,?none,?none,?none])).
+-define(matchstate_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,T,?none,?none])).
+-define(opaque_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,T,?none])).
+-define(map_union(T), ?union([?none,?none,?none,?none,?none,?none,?none,?none,?none,T])).
-define(integer_union(T), ?number_union(T)).
-define(float_union(T), ?number_union(T)).
-define(nil_union(T), ?list_union(T)).
@@ -466,16 +474,6 @@ has_opaque_subtype(T) ->
t_opaque_structure(?opaque(Elements)) ->
t_sup([Struct || #opaque{struct = Struct} <- ordsets:to_list(Elements)]).
--spec t_opaque_modules(erl_type()) -> [module()].
-
-t_opaque_modules(?opaque(Elements)) ->
- case ordsets:size(Elements) of
- 1 ->
- [#opaque{mod = Mod}] = set_to_list(Elements),
- [Mod];
- _ -> throw({error, "Unexpected multiple opaque types"})
- end.
-
-spec t_contains_opaque(erl_type()) -> boolean().
t_contains_opaque(Type) ->
@@ -496,14 +494,13 @@ t_contains_opaque(?function(Domain, Range), Opaques) ->
t_contains_opaque(Domain, Opaques)
orelse t_contains_opaque(Range, Opaques);
t_contains_opaque(?identifier(_Types), _Opaques) -> false;
-t_contains_opaque(?integer(_Types), _Opaques) -> false;
t_contains_opaque(?int_range(_From, _To), _Opaques) -> false;
t_contains_opaque(?int_set(_Set), _Opaques) -> false;
+t_contains_opaque(?integer(_Types), _Opaques) -> false;
t_contains_opaque(?list(Type, Tail, _), Opaques) ->
t_contains_opaque(Type, Opaques) orelse t_contains_opaque(Tail, Opaques);
-t_contains_opaque(?map(_) = Map, Opaques) ->
- list_contains_opaque(map_values(Map), Opaques) orelse
- list_contains_opaque(map_keys(Map), Opaques);
+t_contains_opaque(?map(_, _, _) = Map, Opaques) ->
+ list_contains_opaque(map_all_types(Map), Opaques);
t_contains_opaque(?matchstate(_P, _Slots), _Opaques) -> false;
t_contains_opaque(?nil, _Opaques) -> false;
t_contains_opaque(?number(_Set, _Tag), _Opaques) -> false;
@@ -593,13 +590,11 @@ t_find_opaque_mismatch_list([H|T]) ->
%% calling t_contains_opaque/2 is that the traversal stops when
%% there is a mismatch which means that unknown opaque types "below"
%% the mismatch are not found.
-%% XXX. Returns one element even if both oparands contain opaque types.
-%% XXX. Slow since t_inf() is called but the results are ignored.
t_find_unknown_opaque(_T1, _T2, 'universe') -> [];
t_find_unknown_opaque(T1, T2, Opaques) ->
try t_inf(T1, T2, {match, Opaques}) of
_ -> []
- catch throw:N when is_integer(N) -> [N]
+ catch throw:{pos, Ns} -> Ns
end.
-spec t_decorate_with_opaque(erl_type(), erl_type(), [erl_type()]) -> erl_type().
@@ -690,8 +685,8 @@ list_decorate(List, L, Opaques) ->
union_decorate(U1, U2, Opaques) ->
Union = union_decorate(U1, U2, Opaques, 0, []),
- [A,B,F,I,L,N,T,M,_,_R,Map] = U1,
- [_,_,_,_,_,_,_,_,Opaque,_,_] = U2,
+ [A,B,F,I,L,N,T,M,_,Map] = U1,
+ [_,_,_,_,_,_,_,_,Opaque,_] = U2,
List = [A,B,F,I,L,N,T,M,Map],
DecList = [Dec ||
E <- List,
@@ -759,14 +754,15 @@ t_opaque_from_records(RecDict) ->
end
end, RecDict),
OpaqueTypeDict =
- dict:map(fun({opaque, Name, _Arity}, {Module, _Type, ArgNames}) ->
+ dict:map(fun({opaque, Name, _Arity},
+ {{Module, _FileLine, _Form, ArgNames}, _Type}) ->
%% Args = args_to_types(ArgNames),
%% List = lists:zip(ArgNames, Args),
- %% TmpVarDict = dict:from_list(List),
- %% Rep = t_from_form(Type, RecDict, TmpVarDict),
- Rep = t_none(), % not used for anything right now
+ %% TmpVarTab = maps:to_list(List),
+ %% Rep = t_from_form(Type, RecDict, TmpVarTab),
+ Rep = t_any(), % not used for anything right now
Args = [t_any() || _ <- ArgNames],
- skip_opaque_alias(Rep, Module, Name, Args)
+ t_opaque(Module, Name, Args, Rep)
end, OpaqueRecDict),
[OpaqueType || {_Key, OpaqueType} <- dict:to_list(OpaqueTypeDict)].
@@ -801,158 +797,10 @@ t_struct_from_opaque(Type, _Opaques) -> Type.
list_struct_from_opaque(Types, Opaques) ->
[t_struct_from_opaque(Type, Opaques) || Type <- Types].
--spec module_builtin_opaques(module()) -> [erl_type()].
-
-module_builtin_opaques(Module) ->
- [O || O <- all_opaque_builtins(), lists:member(Module, t_opaque_modules(O))].
-
%%-----------------------------------------------------------------------------
-%% Remote types: these types are used for preprocessing;
-%% they should never reach the analysis stage.
-
--spec t_remote(atom(), atom(), [erl_type()]) -> erl_type().
-
-t_remote(Mod, Name, Args) ->
- ?remote(set_singleton(#remote{mod = Mod, name = Name, args = Args})).
-
--spec t_is_remote(erl_type()) -> boolean().
-
-t_is_remote(Type) ->
- do_opaque(Type, 'universe', fun is_remote/1).
-
-is_remote(?remote(_)) -> true;
-is_remote(_) -> false.
-type mod_records() :: dict:dict(module(), type_table()).
--spec t_solve_remote(erl_type(), sets:set(mfa()), mod_records()) -> erl_type().
-
-t_solve_remote(Type, ExpTypes, Records) ->
- {RT, _RR} = t_solve_remote(Type, ExpTypes, Records, []),
- RT.
-
-t_solve_remote(?function(Domain, Range), ET, R, C) ->
- {RT1, RR1} = t_solve_remote(Domain, ET, R, C),
- {RT2, RR2} = t_solve_remote(Range, ET, R, C),
- {?function(RT1, RT2), RR1 ++ RR2};
-t_solve_remote(?list(Types, Term, Size), ET, R, C) ->
- {RT1, RR1} = t_solve_remote(Types, ET, R, C),
- {RT2, RR2} = t_solve_remote(Term, ET, R, C),
- {?list(RT1, RT2, Size), RR1 ++ RR2};
-t_solve_remote(?product(Types), ET, R, C) ->
- {RL, RR} = list_solve_remote(Types, ET, R, C),
- {?product(RL), RR};
-t_solve_remote(?opaque(Set), ET, R, C) ->
- List = ordsets:to_list(Set),
- {NewList, RR} = opaques_solve_remote(List, ET, R, C),
- {?opaque(ordsets:from_list(NewList)), RR};
-t_solve_remote(?tuple(?any, _, _) = T, _ET, _R, _C) -> {T, []};
-t_solve_remote(?tuple(Types, _Arity, _Tag), ET, R, C) ->
- {RL, RR} = list_solve_remote(Types, ET, R, C),
- {t_tuple(RL), RR};
-t_solve_remote(?tuple_set(Set), ET, R, C) ->
- {NewTuples, RR} = tuples_solve_remote(Set, ET, R, C),
- {t_sup(NewTuples), RR};
-t_solve_remote(?remote(Set), ET, R, C) ->
- RemoteList = ordsets:to_list(Set),
- {RL, RR} = list_solve_remote_type(RemoteList, ET, R, C),
- {t_sup(RL), RR};
-t_solve_remote(?union(List), ET, R, C) ->
- {RL, RR} = list_solve_remote(List, ET, R, C),
- {t_sup(RL), RR};
-t_solve_remote(T, _ET, _R, _C) -> {T, []}.
-
-t_solve_remote_type(#remote{mod = RemMod, name = Name, args = Args0} = RemType,
- ET, R, C) ->
- Args = lists:map(fun(A) ->
- {Arg, _} = t_solve_remote(A, ET, R, C),
- Arg
- end, Args0),
- ArgsLen = length(Args),
- case dict:find(RemMod, R) of
- error ->
- self() ! {self(), ext_types, {RemMod, Name, ArgsLen}},
- {t_any(), []};
- {ok, RemDict} ->
- MFA = {RemMod, Name, ArgsLen},
- case sets:is_element(MFA, ET) of
- true ->
- case lookup_type(Name, ArgsLen, RemDict) of
- {type, {_Mod, Type, ArgNames}} ->
- {NewType, NewCycle, NewRR} =
- case can_unfold_more(RemType, C) of
- true ->
- List = lists:zip(ArgNames, Args),
- TmpVarDict = dict:from_list(List),
- {t_from_form(Type, RemDict, TmpVarDict), [RemType|C], []};
- false ->
- {t_any(), C, [RemType]}
- end,
- {RT, RR} = t_solve_remote(NewType, ET, R, NewCycle),
- RetRR = NewRR ++ RR,
- RT1 =
- case lists:member(RemType, RetRR) of
- true -> t_limit(RT, ?REC_TYPE_LIMIT);
- false -> RT
- end,
- {RT1, RetRR};
- {opaque, {Mod, Type, ArgNames}} ->
- List = lists:zip(ArgNames, Args),
- TmpVarDict = dict:from_list(List),
- {Rep, NewCycle, NewRR} =
- case can_unfold_more(RemType, C) of
- true ->
- {t_from_form(Type, RemDict, TmpVarDict), [RemType|C], []};
- false ->
- {t_any(), C, [RemType]}
- end,
- {NewRep, RR} = t_solve_remote(Rep, ET, R, NewCycle),
- RetRR = NewRR ++ RR,
- RT1 =
- case lists:member(RemType, RetRR) of
- true -> t_limit(NewRep, ?REC_TYPE_LIMIT);
- false -> NewRep
- end,
- {skip_opaque_alias(RT1, Mod, Name, Args), RetRR};
- error ->
- Msg = io_lib:format("Unable to find remote type ~w:~w()\n",
- [RemMod, Name]),
- throw({error, Msg})
- end;
- false ->
- self() ! {self(), ext_types, {RemMod, Name, ArgsLen}},
- {t_any(), []}
- end
- end.
-
-list_solve_remote([], _ET, _R, _C) ->
- {[], []};
-list_solve_remote([Type|Types], ET, R, C) ->
- {RT, RR1} = t_solve_remote(Type, ET, R, C),
- {RL, RR2} = list_solve_remote(Types, ET, R, C),
- {[RT|RL], RR1 ++ RR2}.
-
-list_solve_remote_type([], _ET, _R, _C) ->
- {[], []};
-list_solve_remote_type([Type|Types], ET, R, C) ->
- {RT, RR1} = t_solve_remote_type(Type, ET, R, C),
- {RL, RR2} = list_solve_remote_type(Types, ET, R, C),
- {[RT|RL], RR1 ++ RR2}.
-
-opaques_solve_remote([], _ET, _R, _C) ->
- {[], []};
-opaques_solve_remote([#opaque{struct = Struct} = Remote|Tail], ET, R, C) ->
- {RT, RR1} = t_solve_remote(Struct, ET, R, C),
- {LOp, RR2} = opaques_solve_remote(Tail, ET, R, C),
- {[Remote#opaque{struct = RT}|LOp], RR1 ++ RR2}.
-
-tuples_solve_remote([], _ET, _R, _C) ->
- {[], []};
-tuples_solve_remote([{_Sz, Tuples}|Tail], ET, R, C) ->
- {RL, RR1} = list_solve_remote(Tuples, ET, R, C),
- {LSzTpls, RR2} = tuples_solve_remote(Tail, ET, R, C),
- {RL ++ LSzTpls, RR1 ++ RR2}.
-
%%-----------------------------------------------------------------------------
%% Unit type. Signals non termination.
%%
@@ -1653,6 +1501,11 @@ t_list_elements(Type, Opaques) ->
list_elements(?list(Contents, _, _)) -> Contents;
list_elements(?nil) -> ?none.
+-spec t_list_termination(erl_type(), opaques()) -> erl_type().
+
+t_list_termination(Type, Opaques) ->
+ do_opaque(Type, Opaques, fun t_list_termination/1).
+
-spec t_list_termination(erl_type()) -> erl_type().
t_list_termination(?nil) -> ?nil;
@@ -1728,6 +1581,11 @@ is_maybe_improper_list(_) -> false.
%% %% false = t_is_subtype(t_nil(), Termination),
%% ?list(Content, Termination, ?any).
+-spec lift_list_to_pos_empty(erl_type(), opaques()) -> erl_type().
+
+lift_list_to_pos_empty(Type, Opaques) ->
+ do_opaque(Type, Opaques, fun lift_list_to_pos_empty/1).
+
-spec lift_list_to_pos_empty(erl_type()) -> erl_type().
lift_list_to_pos_empty(?nil) -> ?nil;
@@ -1737,16 +1595,112 @@ lift_list_to_pos_empty(?list(Content, Termination, _)) ->
%%-----------------------------------------------------------------------------
%% Maps
%%
+%% Representation:
+%% ?map(Pairs, DefaultKey, DefaultValue)
+%%
+%% Pairs is a sorted dictionary of types with a mandatoriness tag on each pair
+%% (t_map_dict()). DefaultKey and DefaultValue are plain types.
+%%
+%% A map M belongs to this type iff
+%% For each pair {KT, mandatory, VT} in Pairs, there exists a pair {K, V} in M
+%% such that K \in KT and V \in VT.
+%% For each pair {KT, optional, VT} in Pairs, either there exists no key K in
+%% M s.t. K in KT, or there exists a pair {K, V} in M such that K \in KT and
+%% V \in VT.
+%% For each remaining pair {K, V} in M (where remaining means that there is no
+%% key KT in Pairs s.t. K \in KT), K \in DefaultKey and V \in DefaultValue.
+%%
+%% Invariants:
+%% * The keys in Pairs are singleton types.
+%% * The values of Pairs must not be unit, and may only be none if the
+%% mandatoriness tag is 'optional'.
+%% * Optional must contain no pair {K,V} s.t. K is a subtype of DefaultKey and
+%% V is equal to DefaultKey.
+%% * DefaultKey must be the empty type iff DefaultValue is the empty type.
+%% * DefaultKey must not be a singleton type.
+%% * For every key K in Pairs, DefaultKey - K must not be representable; i.e.
+%% t_subtract(DefaultKey, K) must return DefaultKey.
+%% * For every pair {K, 'optional', ?none} in Pairs, K must be a subtype of
+%% DefaultKey.
+%% * Pairs must be sorted and not contain any duplicate keys.
+%%
+%% These invariants ensure that equal map types are represented by equal terms.
+
+-define(mand, mandatory).
+-define(opt, optional).
+
+-type t_map_mandatoriness() :: ?mand | ?opt.
+-type t_map_pair() :: {erl_type(), t_map_mandatoriness(), erl_type()}.
+-type t_map_dict() :: [t_map_pair()].
-spec t_map() -> erl_type().
t_map() ->
- ?map([]).
+ t_map([], t_any(), t_any()).
-spec t_map([{erl_type(), erl_type()}]) -> erl_type().
-t_map(_) ->
- ?map([]).
+t_map(L) ->
+ lists:foldl(fun t_map_put/2, t_map(), L).
+
+-spec t_map(t_map_dict(), erl_type(), erl_type()) -> erl_type().
+
+t_map(Pairs0, DefK0, DefV0) ->
+ DefK1 = lists:foldl(fun({K,_,_},Acc)->t_subtract(Acc,K)end, DefK0, Pairs0),
+ {DefK2, DefV1} =
+ case t_is_none_or_unit(DefK1) orelse t_is_none_or_unit(DefV0) of
+ true -> {?none, ?none};
+ false -> {DefK1, DefV0}
+ end,
+ {Pairs1, DefK, DefV}
+ = case is_singleton_type(DefK2) of
+ true -> {mapdict_insert({DefK2, ?opt, DefV1}, Pairs0), ?none, ?none};
+ false -> {Pairs0, DefK2, DefV1}
+ end,
+ Pairs = normalise_map_optionals(Pairs1, DefK, DefV),
+ %% Validate invariants of the map representation.
+ %% Since we needed to iterate over the arguments in order to normalise anyway,
+ %% we might as well save us some future pain and do this even without
+ %% define(DEBUG, true).
+ try
+ validate_map_elements(Pairs)
+ catch error:badarg -> error(badarg, [Pairs0,DefK0,DefV0])
+ end,
+ case map_pairs_are_none(Pairs) of
+ true -> ?none;
+ false -> ?map(Pairs, DefK, DefV)
+ end.
+
+normalise_map_optionals([], _, _) -> [];
+normalise_map_optionals([E={K,?opt,?none}|T], DefK, DefV) ->
+ Diff = t_subtract(DefK, K),
+ case t_is_subtype(K, DefK) andalso DefK =:= Diff of
+ true -> [E|normalise_map_optionals(T, DefK, DefV)];
+ false -> normalise_map_optionals(T, Diff, DefV)
+ end;
+normalise_map_optionals([E={K,?opt,V}|T], DefK, DefV) ->
+ case t_is_equal(V, DefV) andalso t_is_subtype(K, DefK) of
+ true -> normalise_map_optionals(T, DefK, DefV);
+ false -> [E|normalise_map_optionals(T, DefK, DefV)]
+ end;
+normalise_map_optionals([E|T], DefK, DefV) ->
+ [E|normalise_map_optionals(T, DefK, DefV)].
+
+validate_map_elements([{K1,_,_}|Rest=[{K2,_,_}|_]]) ->
+ case is_singleton_type(K1) andalso K1 < K2 of
+ false -> error(badarg);
+ true -> validate_map_elements(Rest)
+ end;
+validate_map_elements([{K,_,_}]) ->
+ case is_singleton_type(K) of
+ false -> error(badarg);
+ true -> true
+ end;
+validate_map_elements([]) -> true.
+
+map_pairs_are_none([]) -> false;
+map_pairs_are_none([{_,?mand,?none}|_]) -> true;
+map_pairs_are_none([_|Ps]) -> map_pairs_are_none(Ps).
-spec t_is_map(erl_type()) -> boolean().
@@ -1758,9 +1712,259 @@ t_is_map(Type) ->
t_is_map(Type, Opaques) ->
do_opaque(Type, Opaques, fun is_map1/1).
-is_map1(?map(_)) -> true;
+is_map1(?map(_, _, _)) -> true;
is_map1(_) -> false.
+-spec t_map_entries(erl_type()) -> t_map_dict().
+
+t_map_entries(M) ->
+ t_map_entries(M, 'universe').
+
+-spec t_map_entries(erl_type(), opaques()) -> t_map_dict().
+
+t_map_entries(M, Opaques) ->
+ do_opaque(M, Opaques, fun map_entries/1).
+
+map_entries(?map(Pairs,_,_)) ->
+ Pairs.
+
+-spec t_map_def_key(erl_type()) -> erl_type().
+
+t_map_def_key(M) ->
+ t_map_def_key(M, 'universe').
+
+-spec t_map_def_key(erl_type(), opaques()) -> erl_type().
+
+t_map_def_key(M, Opaques) ->
+ do_opaque(M, Opaques, fun map_def_key/1).
+
+map_def_key(?map(_,DefK,_)) ->
+ DefK.
+
+-spec t_map_def_val(erl_type()) -> erl_type().
+
+t_map_def_val(M) ->
+ t_map_def_val(M, 'universe').
+
+-spec t_map_def_val(erl_type(), opaques()) -> erl_type().
+
+t_map_def_val(M, Opaques) ->
+ do_opaque(M, Opaques, fun map_def_val/1).
+
+map_def_val(?map(_,_,DefV)) ->
+ DefV.
+
+-spec mapdict_store(t_map_pair(), t_map_dict()) -> t_map_dict().
+
+mapdict_store(E={K,_,_}, [{K,_,_}|T]) -> [E|T];
+mapdict_store(E1={K1,_,_}, [E2={K2,_,_}|T]) when K1 > K2 ->
+ [E2|mapdict_store(E1, T)];
+mapdict_store(E={_,_,_}, T) -> [E|T].
+
+-spec mapdict_insert(t_map_pair(), t_map_dict()) -> t_map_dict().
+
+mapdict_insert(E={K,_,_}, D=[{K,_,_}|_]) -> error(badarg, [E, D]);
+mapdict_insert(E1={K1,_,_}, [E2={K2,_,_}|T]) when K1 > K2 ->
+ [E2|mapdict_insert(E1, T)];
+mapdict_insert(E={_,_,_}, T) -> [E|T].
+
+-type map_pairwise_merge_fun() :: fun((erl_type(),
+ t_map_mandatoriness(), erl_type(),
+ t_map_mandatoriness(), erl_type())
+ -> t_map_pair() | false).
+
+-spec t_map_pairwise_merge(map_pairwise_merge_fun(), erl_type(), erl_type(),
+ opaques()) -> t_map_dict().
+t_map_pairwise_merge(F, MapA, MapB, Opaques) ->
+ do_opaque(MapA, Opaques,
+ fun(UMapA) ->
+ do_opaque(MapB, Opaques,
+ fun(UMapB) ->
+ map_pairwise_merge(F, UMapA, UMapB)
+ end)
+ end).
+
+%% Merges the pairs of two maps together. Missing pairs become (?opt, DefV) or
+%% (?opt, ?none), depending on whether K \in DefK.
+-spec map_pairwise_merge(map_pairwise_merge_fun(), erl_type(), erl_type())
+ -> t_map_dict().
+map_pairwise_merge(F, ?map(APairs, ADefK, ADefV),
+ ?map(BPairs, BDefK, BDefV)) ->
+ map_pairwise_merge(F, APairs, ADefK, ADefV, BPairs, BDefK, BDefV).
+
+map_pairwise_merge(_, [], _, _, [], _, _) -> [];
+map_pairwise_merge(F, As0, ADefK, ADefV, Bs0, BDefK, BDefV) ->
+ {K1, AMNess1, AV1, As1, BMNess1, BV1, Bs1} =
+ case {As0, Bs0} of
+ {[{K,AMNess,AV}|As], [{K, BMNess,BV}|Bs]} ->
+ {K, AMNess, AV, As, BMNess, BV, Bs};
+ {[{K,AMNess,AV}|As], [{BK,_, _ }|_]=Bs} when K < BK ->
+ {K, AMNess, AV, As, ?opt, mapmerge_otherv(K, BDefK, BDefV), Bs};
+ {As, [{K, BMNess,BV}|Bs]} ->
+ {K, ?opt, mapmerge_otherv(K, ADefK, ADefV), As, BMNess, BV, Bs};
+ {[{K,AMNess,AV}|As], []=Bs} ->
+ {K, AMNess, AV, As, ?opt, mapmerge_otherv(K, BDefK, BDefV), Bs}
+ end,
+ MK = K1, %% Rename to make clear that we are matching below
+ case F(K1, AMNess1, AV1, BMNess1, BV1) of
+ false -> map_pairwise_merge(F,As1,ADefK,ADefV,Bs1,BDefK,BDefV);
+ {MK,_,_}=M -> [M|map_pairwise_merge(F,As1,ADefK,ADefV,Bs1,BDefK,BDefV)]
+ end.
+
+%% Folds over the pairs in two maps simultaneously in reverse key order. Missing
+%% pairs become (?opt, DefV) or (?opt, ?none), depending on whether K \in DefK.
+-spec map_pairwise_merge_foldr(fun((erl_type(),
+ t_map_mandatoriness(), erl_type(),
+ t_map_mandatoriness(), erl_type(),
+ Acc) -> Acc),
+ Acc, erl_type(), erl_type()) -> Acc.
+
+map_pairwise_merge_foldr(F, AccIn, ?map(APairs, ADefK, ADefV),
+ ?map(BPairs, BDefK, BDefV)) ->
+ map_pairwise_merge_foldr(F, AccIn, APairs, ADefK, ADefV, BPairs, BDefK, BDefV).
+
+map_pairwise_merge_foldr(_, Acc, [], _, _, [], _, _) -> Acc;
+map_pairwise_merge_foldr(F, AccIn, As0, ADefK, ADefV, Bs0, BDefK, BDefV) ->
+ {K1, AMNess1, AV1, As1, BMNess1, BV1, Bs1} =
+ case {As0, Bs0} of
+ {[{K,AMNess,AV}|As], [{K,BMNess,BV}|Bs]} ->
+ {K, AMNess, AV, As, BMNess, BV, Bs};
+ {[{K,AMNess,AV}|As], [{BK,_, _ }|_]=Bs} when K < BK ->
+ {K, AMNess, AV, As, ?opt, mapmerge_otherv(K, BDefK, BDefV), Bs};
+ {As, [{K,BMNess,BV}|Bs]} ->
+ {K, ?opt, mapmerge_otherv(K, ADefK, ADefV), As, BMNess, BV, Bs};
+ {[{K,AMNess,AV}|As], []=Bs} ->
+ {K, AMNess, AV, As, ?opt, mapmerge_otherv(K, BDefK, BDefV), Bs}
+ end,
+ F(K1, AMNess1, AV1, BMNess1, BV1,
+ map_pairwise_merge_foldr(F,AccIn,As1,ADefK,ADefV,Bs1,BDefK,BDefV)).
+
+%% By observing that a missing pair in a map is equivalent to an optional pair,
+%% with ?none or DefV value, depending on whether K \in DefK, we can simplify
+%% merging by denormalising the map pairs temporarily, removing all 'false'
+%% cases, at the cost of the creation of more tuples:
+mapmerge_otherv(K, ODefK, ODefV) ->
+ case t_inf(K, ODefK) of
+ ?none -> ?none;
+ _KOrOpaque -> ODefV
+ end.
+
+-spec t_map_put({erl_type(), erl_type()}, erl_type()) -> erl_type().
+
+t_map_put(KV, Map) ->
+ t_map_put(KV, Map, 'universe').
+
+-spec t_map_put({erl_type(), erl_type()}, erl_type(), opaques()) -> erl_type().
+
+t_map_put(KV, Map, Opaques) ->
+ do_opaque(Map, Opaques, fun(UM) -> map_put(KV, UM, Opaques) end).
+
+%% Key and Value are *not* unopaqued, but the map is
+map_put(_, ?none, _) -> ?none;
+map_put({Key, Value}, ?map(Pairs,DefK,DefV), Opaques) ->
+ case t_is_none_or_unit(Key) orelse t_is_none_or_unit(Value) of
+ true -> ?none;
+ false ->
+ case is_singleton_type(Key) of
+ true ->
+ t_map(mapdict_store({Key, ?mand, Value}, Pairs), DefK, DefV);
+ false ->
+ t_map([{K, MNess, case t_is_none(t_inf(K, Key, Opaques)) of
+ true -> V;
+ false -> t_sup(V, Value)
+ end} || {K, MNess, V} <- Pairs],
+ t_sup(DefK, Key),
+ t_sup(DefV, Value))
+ end
+ end.
+
+-spec t_map_update({erl_type(), erl_type()}, erl_type()) -> erl_type().
+
+t_map_update(KV, Map) ->
+ t_map_update(KV, Map, 'universe').
+
+-spec t_map_update({erl_type(), erl_type()}, erl_type(), opaques()) -> erl_type().
+
+t_map_update(_, ?none, _) -> ?none;
+t_map_update(KV={Key, _}, M, Opaques) ->
+ case t_is_subtype(t_atom('true'), t_map_is_key(Key, M, Opaques)) of
+ false -> ?none;
+ true -> t_map_put(KV, M, Opaques)
+ end.
+
+-spec t_map_get(erl_type(), erl_type()) -> erl_type().
+
+t_map_get(Key, Map) ->
+ t_map_get(Key, Map, 'universe').
+
+-spec t_map_get(erl_type(), erl_type(), opaques()) -> erl_type().
+
+t_map_get(Key, Map, Opaques) ->
+ do_opaque(Map, Opaques,
+ fun(UM) ->
+ do_opaque(Key, Opaques, fun(UK) -> map_get(UK, UM) end)
+ end).
+
+map_get(_, ?none) -> ?none;
+map_get(Key, ?map(Pairs, DefK, DefV)) ->
+ DefRes =
+ case t_do_overlap(DefK, Key) of
+ false -> t_none();
+ true -> DefV
+ end,
+ case is_singleton_type(Key) of
+ false ->
+ lists:foldl(fun({K, _, V}, Res) ->
+ case t_do_overlap(K, Key) of
+ false -> Res;
+ true -> t_sup(Res, V)
+ end
+ end, DefRes, Pairs);
+ true ->
+ case lists:keyfind(Key, 1, Pairs) of
+ false -> DefRes;
+ {_, _, ValType} -> ValType
+ end
+ end.
+
+-spec t_map_is_key(erl_type(), erl_type()) -> erl_type().
+
+t_map_is_key(Key, Map) ->
+ t_map_is_key(Key, Map, 'universe').
+
+-spec t_map_is_key(erl_type(), erl_type(), opaques()) -> erl_type().
+
+t_map_is_key(Key, Map, Opaques) ->
+ do_opaque(Map, Opaques,
+ fun(UM) ->
+ do_opaque(Key, Opaques, fun(UK) -> map_is_key(UK, UM) end)
+ end).
+
+map_is_key(_, ?none) -> ?none;
+map_is_key(Key, ?map(Pairs, DefK, _DefV)) ->
+ case is_singleton_type(Key) of
+ true ->
+ case lists:keyfind(Key, 1, Pairs) of
+ {Key, ?mand, _} -> t_atom(true);
+ {Key, ?opt, ?none} -> t_atom(false);
+ {Key, ?opt, _} -> t_boolean();
+ false ->
+ case t_do_overlap(DefK, Key) of
+ false -> t_atom(false);
+ true -> t_boolean()
+ end
+ end;
+ false ->
+ case t_do_overlap(DefK, Key)
+ orelse lists:any(fun({_,_,?none}) -> false;
+ ({K,_,_}) -> t_do_overlap(K, Key)
+ end, Pairs)
+ of
+ true -> t_boolean();
+ false -> t_atom(false)
+ end
+ end.
+
%%-----------------------------------------------------------------------------
%% Tuples
%%
@@ -1891,17 +2095,6 @@ is_tuple1(_) -> false.
t_bitstrlist() ->
t_iolist(1, t_bitstr()).
-%% XXX. To be removed.
--spec t_constant() -> erl_type().
-
-t_constant() ->
- t_sup([t_number(), t_identifier(), t_atom(), t_fun(), t_binary()]).
-
--spec t_is_constant(erl_type()) -> boolean().
-
-t_is_constant(X) ->
- t_is_subtype(X, t_constant()).
-
-spec t_arity() -> erl_type().
t_arity() ->
@@ -1951,7 +2144,7 @@ t_mfa() ->
-spec t_module() -> erl_type().
t_module() ->
- t_sup(t_atom(), t_parameterized_module()).
+ t_atom().
-spec t_node() -> erl_type().
@@ -1977,92 +2170,11 @@ t_iolist(N, T) when N > 0 ->
t_iolist(0, T) ->
t_maybe_improper_list(t_any(), t_sup(T, t_nil())).
--spec t_parameterized_module() -> erl_type().
-
-t_parameterized_module() ->
- t_tuple().
-
-spec t_timeout() -> erl_type().
t_timeout() ->
t_sup(t_non_neg_integer(), t_atom('infinity')).
-%%-----------------------------------------------------------------------------
-%% Some built-in opaque types
-%%
-
--spec t_array() -> erl_type().
-
-t_array() ->
- t_opaque(array, array, [t_any()],
- t_tuple([t_atom('array'),
- t_sup([t_atom('undefined'), t_non_neg_integer()]),
- t_sup([t_atom('undefined'), t_non_neg_integer()]),
- t_any(),
- t_any()])).
-
--spec t_dict() -> erl_type().
-
-t_dict() ->
- t_opaque(dict, dict, [t_any(), t_any()],
- t_tuple([t_atom('dict'),
- t_sup([t_atom('undefined'), t_non_neg_integer()]),
- t_sup([t_atom('undefined'), t_non_neg_integer()]),
- t_sup([t_atom('undefined'), t_non_neg_integer()]),
- t_sup([t_atom('undefined'), t_non_neg_integer()]),
- t_sup([t_atom('undefined'), t_non_neg_integer()]),
- t_sup([t_atom('undefined'), t_non_neg_integer()]),
- t_sup([t_atom('undefined'), t_tuple()]),
- t_sup([t_atom('undefined'), t_tuple()])])).
-
--spec t_digraph() -> erl_type().
-
-t_digraph() ->
- t_opaque(digraph, digraph, [],
- t_tuple([t_atom('digraph'),
- t_sup(t_atom(), t_tid()),
- t_sup(t_atom(), t_tid()),
- t_sup(t_atom(), t_tid()),
- t_boolean()])).
-
--spec t_gb_set() -> erl_type().
-
-t_gb_set() ->
- t_opaque(gb_sets, gb_set, [],
- t_tuple([t_non_neg_integer(), t_sup(t_atom('nil'), t_tuple(3))])).
-
--spec t_gb_tree() -> erl_type().
-
-t_gb_tree() ->
- t_opaque(gb_trees, gb_tree, [],
- t_tuple([t_non_neg_integer(), t_sup(t_atom('nil'), t_tuple(4))])).
-
--spec t_queue() -> erl_type().
-
-t_queue() ->
- t_opaque(queue, queue, [t_any()], t_tuple([t_list(), t_list()])).
-
--spec t_set() -> erl_type().
-
-t_set() ->
- t_opaque(sets, set, [t_any()],
- t_tuple([t_atom('set'), t_non_neg_integer(), t_non_neg_integer(),
- t_pos_integer(), t_non_neg_integer(), t_non_neg_integer(),
- t_non_neg_integer(),
- t_sup([t_atom('undefined'), t_tuple()]),
- t_sup([t_atom('undefined'), t_tuple()])])).
-
--spec t_tid() -> erl_type().
-
-t_tid() ->
- t_opaque(ets, tid, [], t_integer()).
-
--spec all_opaque_builtins() -> [erl_type(),...].
-
-all_opaque_builtins() ->
- [t_array(), t_dict(), t_digraph(), t_gb_set(),
- t_gb_tree(), t_queue(), t_set(), t_tid()].
-
%%------------------------------------
%% ?none is allowed in products. A product of size 1 is not a product.
@@ -2110,8 +2222,9 @@ t_has_var(?tuple(Elements, _, _)) ->
t_has_var_list(Elements);
t_has_var(?tuple_set(_) = T) ->
t_has_var_list(t_tuple_subtypes(T));
-t_has_var(?map(_)= Map) ->
- t_has_var_list(map_keys(Map)) orelse t_has_var_list(map_values(Map));
+t_has_var(?map(_, DefK, _)= Map) ->
+ t_has_var_list(map_all_values(Map)) orelse
+ t_has_var(DefK);
t_has_var(?opaque(Set)) ->
%% Assume variables in 'args' are also present i 'struct'
t_has_var_list([O#opaque.struct || O <- set_to_list(Set)]);
@@ -2146,9 +2259,9 @@ t_collect_vars(?tuple(Types, _, _), Acc) ->
t_collect_vars_list(Types, Acc);
t_collect_vars(?tuple_set(_) = TS, Acc) ->
t_collect_vars_list(t_tuple_subtypes(TS), Acc);
-t_collect_vars(?map(_) = Map, Acc0) ->
- Acc = t_collect_vars_list(map_keys(Map), Acc0),
- t_collect_vars_list(map_values(Map), Acc);
+t_collect_vars(?map(_, DefK, _) = Map, Acc0) ->
+ Acc = t_collect_vars_list(map_all_values(Map), Acc0),
+ t_collect_vars(DefK, Acc);
t_collect_vars(?opaque(Set), Acc) ->
%% Assume variables in 'args' are also present i 'struct'
t_collect_vars_list([O#opaque.struct || O <- set_to_list(Set)], Acc);
@@ -2183,7 +2296,15 @@ t_from_term(T) when is_function(T) ->
{arity, Arity} = erlang:fun_info(T, arity),
t_fun(Arity, t_any());
t_from_term(T) when is_integer(T) -> t_integer(T);
-t_from_term(T) when is_map(T) -> t_map();
+t_from_term(T) when is_map(T) ->
+ Pairs = [{t_from_term(K), ?mand, t_from_term(V)}
+ || {K, V} <- maps:to_list(T)],
+ {Stons, Rest} = lists:partition(fun({K,_,_}) -> is_singleton_type(K) end,
+ Pairs),
+ {DefK, DefV}
+ = lists:foldl(fun({K,_,V},{AK,AV}) -> {t_sup(K,AK), t_sup(V,AV)} end,
+ {t_none(), t_none()}, Rest),
+ t_map(lists:keysort(1, Stons), DefK, DefV);
t_from_term(T) when is_pid(T) -> t_pid();
t_from_term(T) when is_port(T) -> t_port();
t_from_term(T) when is_reference(T) -> t_reference();
@@ -2357,14 +2478,19 @@ expand_range_from_set(Range = ?int_range(From, To), Set) ->
-spec t_sup([erl_type()]) -> erl_type().
-t_sup([?any|_]) ->
- ?any;
-t_sup([H1, H2|T]) ->
- t_sup([t_sup(H1, H2)|T]);
-t_sup([H]) ->
- subst_all_vars_to_any(H);
-t_sup([]) ->
- ?none.
+t_sup([]) -> ?none;
+t_sup(Ts) ->
+ case lists:any(fun is_any/1, Ts) of
+ true -> ?any;
+ false ->
+ t_sup1(Ts, [])
+ end.
+
+t_sup1([H1, H2|T], L) ->
+ t_sup1(T, [t_sup(H1, H2)|L]);
+t_sup1([T], []) -> subst_all_vars_to_any(T);
+t_sup1(Ts, L) ->
+ t_sup1(Ts++L, []).
-spec t_sup(erl_type(), erl_type()) -> erl_type().
@@ -2393,8 +2519,6 @@ t_sup(?opaque(Set1), ?opaque(Set2)) ->
%% io:format("Debug: t_sup executed with args ~w and ~w~n",[T1, T2]), ?none;
%%t_sup(T1, T2=?opaque(_,_,_)) ->
%% io:format("Debug: t_sup executed with args ~w and ~w~n",[T1, T2]), ?none;
-t_sup(?remote(Set1), ?remote(Set2)) ->
- ?remote(set_union_no_limit(Set1, Set2));
t_sup(?matchstate(Pres1, Slots1), ?matchstate(Pres2, Slots2)) ->
?matchstate(t_sup(Pres1, Pres2), t_sup(Slots1, Slots2));
t_sup(?nil, ?nil) -> ?nil;
@@ -2470,6 +2594,13 @@ t_sup(?tuple_set(List1), T2 = ?tuple(_, Arity, _)) ->
sup_tuple_sets(List1, [{Arity, [T2]}]);
t_sup(?tuple(_, Arity, _) = T1, ?tuple_set(List2)) ->
sup_tuple_sets([{Arity, [T1]}], List2);
+t_sup(?map(_, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B) ->
+ Pairs =
+ map_pairwise_merge(
+ fun(K, MNess, V1, MNess, V2) -> {K, MNess, t_sup(V1, V2)};
+ (K, _, V1, _, V2) -> {K, ?opt, t_sup(V1, V2)}
+ end, A, B),
+ t_map(Pairs, t_sup(ADefK, BDefK), t_sup(ADefV, BDefV));
t_sup(T1, T2) ->
?union(U1) = force_union(T1),
?union(U2) = force_union(T2),
@@ -2588,8 +2719,7 @@ force_union(T = ?list(_, _, _)) -> ?list_union(T);
force_union(T = ?nil) -> ?list_union(T);
force_union(T = ?number(_, _)) -> ?number_union(T);
force_union(T = ?opaque(_)) -> ?opaque_union(T);
-force_union(T = ?remote(_)) -> ?remote_union(T);
-force_union(T = ?map(_)) -> ?map_union(T);
+force_union(T = ?map(_,_,_)) -> ?map_union(T);
force_union(T = ?tuple(_, _, _)) -> ?tuple_union(T);
force_union(T = ?tuple_set(_)) -> ?tuple_union(T);
force_union(T = ?matchstate(_, _)) -> ?matchstate_union(T);
@@ -2626,7 +2756,7 @@ t_elements(?number(_, _) = T) ->
end;
t_elements(?opaque(_) = T) ->
do_elements(T);
-t_elements(?map(_) = T) -> [T];
+t_elements(?map(_,_,_) = T) -> [T];
t_elements(?tuple(_, _, _) = T) -> [T];
t_elements(?tuple_set(_) = TS) ->
case t_tuple_subtypes(TS) of
@@ -2665,8 +2795,7 @@ t_inf(T1, T2) ->
t_inf(T1, T2, 'universe').
%% 'match' should be used from t_find_unknown_opaque() only
--type t_inf_opaques() :: 'universe'
- | [erl_type()] | {'match', [erl_type() | 'universe']}.
+-type t_inf_opaques() :: opaques() | {'match', [erl_type() | 'universe']}.
-spec t_inf(erl_type(), erl_type(), t_inf_opaques()) -> erl_type().
@@ -2709,6 +2838,20 @@ t_inf(?identifier(Set1), ?identifier(Set2), _Opaques) ->
?none -> ?none;
Set -> ?identifier(Set)
end;
+t_inf(?map(_, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B, _Opaques) ->
+ %% Because it simplifies the anonymous function, we allow Pairs to temporarily
+ %% contain mandatory pairs with none values, since all such cases should
+ %% result in a none result.
+ Pairs =
+ map_pairwise_merge(
+ %% For optional keys in both maps, when the infinimum is none, we have
+ %% essentially concluded that K must not be a key in the map.
+ fun(K, ?opt, V1, ?opt, V2) -> {K, ?opt, t_inf(V1, V2)};
+ %% When a key is optional in one map, but mandatory in another, it
+ %% becomes mandatory in the infinumum
+ (K, _, V1, _, V2) -> {K, ?mand, t_inf(V1, V2)}
+ end, A, B),
+ t_map(Pairs, t_inf(ADefK, BDefK), t_inf(ADefV, BDefV));
t_inf(?matchstate(Pres1, Slots1), ?matchstate(Pres2, Slots2), _Opaques) ->
?matchstate(t_inf(Pres1, Pres2), t_inf(Slots1, Slots2));
t_inf(?nil, ?nil, _Opaques) -> ?nil;
@@ -2832,7 +2975,7 @@ inf_opaque1(T1, ?opaque(Set2)=T2, Pos, Opaques) ->
end.
inf_is_opaque_type(T, Pos, {match, Opaques}) ->
- is_opaque_type(T, Opaques) orelse throw(Pos);
+ is_opaque_type(T, Opaques) orelse throw({pos, [Pos]});
inf_is_opaque_type(T, _Pos, Opaques) ->
is_opaque_type(T, Opaques).
@@ -2850,28 +2993,32 @@ inf_collect(_T1, [], _Opaques, OpL) ->
combine(S, T1, T2) ->
#opaque{mod = Mod1, name = Name1, args = Args1} = T1,
#opaque{mod = Mod2, name = Name2, args = Args2} = T2,
- case is_same_type_name({Mod1, Name1, Args1}, {Mod2, Name2, Args2}) of
- true -> [comb(Mod1, Name1, Args1, S, T1)];
- false -> [comb(Mod1, Name1, Args1, S, T1), comb(Mod2, Name2, Args2, S, T2)]
+ Comb1 = comb(Mod1, Name1, Args1, S, T1),
+ case is_compat_opaque_names({Mod1, Name1, Args1}, {Mod2, Name2, Args2}) of
+ true -> Comb1;
+ false -> Comb1 ++ comb(Mod2, Name2, Args2, S, T2)
end.
comb(Mod, Name, Args, S, T) ->
- case is_same_name(Mod, Name, Args, S) of
- true -> S;
- false -> T#opaque{struct = S}
+ case can_combine_opaque_names(Mod, Name, Args, S) of
+ true ->
+ ?opaque(Set) = S,
+ Set;
+ false ->
+ [T#opaque{struct = S}]
end.
-is_same_name(Mod1, Name1, Args1,
- ?opaque([#opaque{mod = Mod2, name = Name2, args = Args2}])) ->
- is_same_type_name({Mod1, Name1, Args1}, {Mod2, Name2, Args2});
-is_same_name(_, _, _, _) -> false.
+can_combine_opaque_names(Mod1, Name1, Args1,
+ ?opaque([#opaque{mod = Mod2, name = Name2, args = Args2}])) ->
+ is_compat_opaque_names({Mod1, Name1, Args1}, {Mod2, Name2, Args2});
+can_combine_opaque_names(_, _, _, _) -> false.
%% Combining two lists this way can be very time consuming...
%% Note: two parameterized opaque types are not the same if their
%% actual parameters differ
inf_opaque(Set1, Set2, Opaques) ->
- List1 = inf_look_up(Set1, 1, Opaques),
- List2 = inf_look_up(Set2, 2, Opaques),
+ List1 = inf_look_up(Set1, Opaques),
+ List2 = inf_look_up(Set2, Opaques),
List0 = [combine(Inf, T1, T2) ||
{Is1, ModNameArgs1, T1} <- List1,
{Is2, ModNameArgs2, T2} <- List2,
@@ -2882,14 +3029,14 @@ inf_opaque(Set1, Set2, Opaques) ->
sup_opaque(List).
%% Optimization: do just one lookup.
-inf_look_up(Set, Pos, Opaques) ->
- [{Opaques =:= 'universe' orelse inf_is_opaque_type2(T, Pos, Opaques),
+inf_look_up(Set, Opaques) ->
+ [{Opaques =:= 'universe' orelse inf_is_opaque_type2(T, Opaques),
{M, N, Args}, T} ||
#opaque{mod = M, name = N, args = Args} = T <- set_to_list(Set)].
-inf_is_opaque_type2(T, Pos, {match, Opaques}) ->
- is_opaque_type2(T, Opaques) orelse throw(Pos);
-inf_is_opaque_type2(T, _Pos, Opaques) ->
+inf_is_opaque_type2(T, {match, Opaques}) ->
+ is_opaque_type2(T, Opaques);
+inf_is_opaque_type2(T, Opaques) ->
is_opaque_type2(T, Opaques).
inf_opaque_types(IsOpaque1, ModNameArgs1, T1,
@@ -2898,18 +3045,119 @@ inf_opaque_types(IsOpaque1, ModNameArgs1, T1,
#opaque{struct = S2}=T2,
case
Opaques =:= 'universe' orelse
- is_same_type_name(ModNameArgs1, ModNameArgs2)
+ is_compat_opaque_names(ModNameArgs1, ModNameArgs2)
of
true -> t_inf(S1, S2, Opaques);
false ->
case {IsOpaque1, IsOpaque2} of
- {true, true} -> t_inf(S1, S2, Opaques);
- {true, false} -> t_inf(S1, ?opaque(set_singleton(T2)), Opaques);
- {false, true} -> t_inf(?opaque(set_singleton(T1)), S2, Opaques);
+ {true, true} -> t_inf(S1, S2, Opaques);
+ {true, false} -> t_inf(S1, ?opaque(set_singleton(T2)), Opaques);
+ {false, true} -> t_inf(?opaque(set_singleton(T1)), S2, Opaques);
+ {false, false} when element(1, Opaques) =:= match ->
+ throw({pos, [1, 2]});
{false, false} -> t_none()
end
end.
+is_compat_opaque_names(ModNameArgs, ModNameArgs) -> true;
+is_compat_opaque_names({Mod,Name,Args1}, {Mod,Name,Args2}) ->
+ is_compat_args(Args1, Args2);
+is_compat_opaque_names(_, _) -> false.
+
+is_compat_args([A1|Args1], [A2|Args2]) ->
+ is_compat_arg(A1, A2) andalso is_compat_args(Args1, Args2);
+is_compat_args([], []) -> true;
+is_compat_args(_, _) -> false.
+
+is_compat_arg(A1, A2) ->
+ is_specialization(A1, A2) orelse is_specialization(A2, A1).
+
+-spec is_specialization(erl_type(), erl_type()) -> boolean().
+
+%% Returns true if the first argument is a specialization of the
+%% second argument in the sense that every type is a specialization of
+%% any(). For example, {_,_} is a specialization of any(), but not of
+%% tuple(). Does not handle variables, but any() and unions (sort of).
+
+is_specialization(T, T) -> true;
+is_specialization(_, ?any) -> true;
+is_specialization(?any, _) -> false;
+is_specialization(?function(Domain1, Range1), ?function(Domain2, Range2)) ->
+ (is_specialization(Domain1, Domain2) andalso
+ is_specialization(Range1, Range2));
+is_specialization(?list(Contents1, Termination1, Size1),
+ ?list(Contents2, Termination2, Size2)) ->
+ (Size1 =:= Size2 andalso
+ is_specialization(Contents1, Contents2) andalso
+ is_specialization(Termination1, Termination2));
+is_specialization(?product(Types1), ?product(Types2)) ->
+ specialization_list(Types1, Types2);
+is_specialization(?tuple(?any, ?any, ?any), ?tuple(_, _, _)) -> false;
+is_specialization(?tuple(_, _, _), ?tuple(?any, ?any, ?any)) -> false;
+is_specialization(?tuple(Elements1, Arity, _),
+ ?tuple(Elements2, Arity, _)) when Arity =/= ?any ->
+ specialization_list(Elements1, Elements2);
+is_specialization(?tuple_set([{Arity, List}]),
+ ?tuple(Elements2, Arity, _)) when Arity =/= ?any ->
+ specialization_list(sup_tuple_elements(List), Elements2);
+is_specialization(?tuple(Elements1, Arity, _),
+ ?tuple_set([{Arity, List}])) when Arity =/= ?any ->
+ specialization_list(Elements1, sup_tuple_elements(List));
+is_specialization(?tuple_set(List1), ?tuple_set(List2)) ->
+ try
+ specialization_list_list([sup_tuple_elements(T) || {_Arity, T} <- List1],
+ [sup_tuple_elements(T) || {_Arity, T} <- List2])
+ catch _:_ -> false
+ end;
+is_specialization(?union(List1)=T1, ?union(List2)=T2) ->
+ case specialization_union2(T1, T2) of
+ {yes, Type1, Type2} -> is_specialization(Type1, Type2);
+ no -> specialization_list(List1, List2)
+ end;
+is_specialization(?union(List), T2) ->
+ case unify_union(List) of
+ {yes, Type} -> is_specialization(Type, T2);
+ no -> false
+ end;
+is_specialization(T1, ?union(List)) ->
+ case unify_union(List) of
+ {yes, Type} -> is_specialization(T1, Type);
+ no -> false
+ end;
+is_specialization(?opaque(_) = T1, T2) ->
+ is_specialization(t_opaque_structure(T1), T2);
+is_specialization(T1, ?opaque(_) = T2) ->
+ is_specialization(T1, t_opaque_structure(T2));
+is_specialization(?var(_), _) -> exit(error);
+is_specialization(_, ?var(_)) -> exit(error);
+is_specialization(?none, _) -> false;
+is_specialization(_, ?none) -> false;
+is_specialization(?unit, _) -> false;
+is_specialization(_, ?unit) -> false;
+is_specialization(#c{}, #c{}) -> false.
+
+specialization_list_list(LL1, LL2) ->
+ length(LL1) =:= length(LL2) andalso specialization_list_list1(LL1, LL2).
+
+specialization_list_list1([], []) -> true;
+specialization_list_list1([L1|LL1], [L2|LL2]) ->
+ specialization_list(L1, L2) andalso specialization_list_list1(LL1, LL2).
+
+specialization_list(L1, L2) ->
+ length(L1) =:= length(L2) andalso specialization_list1(L1, L2).
+
+specialization_list1([], []) -> true;
+specialization_list1([T1|L1], [T2|L2]) ->
+ is_specialization(T1, T2) andalso specialization_list1(L1, L2).
+
+specialization_union2(?union(List1)=T1, ?union(List2)=T2) ->
+ case {unify_union(List1), unify_union(List2)} of
+ {{yes, Type1}, {yes, Type2}} -> {yes, Type1, Type2};
+ {{yes, Type1}, no} -> {yes, Type1, T2};
+ {no, {yes, Type2}} -> {yes, T1, Type2};
+ {no, no} -> no
+ end.
+
-spec t_inf_lists([erl_type()], [erl_type()]) -> [erl_type()].
t_inf_lists(L1, L2) ->
@@ -2996,8 +3244,8 @@ inf_tuples_in_sets2(_, [], Acc, _Opaques) -> lists:reverse(Acc).
inf_union(U1, U2, Opaques) ->
OpaqueFun =
fun(Union1, Union2, InfFun) ->
- [_,_,_,_,_,_,_,_,Opaque,_,_] = Union1,
- [A,B,F,I,L,N,T,M,_,_R,Map] = Union2,
+ [_,_,_,_,_,_,_,_,Opaque,_] = Union1,
+ [A,B,F,I,L,N,T,M,_,Map] = Union2,
List = [A,B,F,I,L,N,T,M,Map],
inf_union_collect(List, Opaque, InfFun, [], [])
end,
@@ -3008,7 +3256,7 @@ inf_union(U1, U2, Opaques) ->
{Union, ThrowList3} = inf_union(U1, U2, 0, [], [], Opaques),
ThrowList = lists:merge3(ThrowList1, ThrowList2, ThrowList3),
case t_sup([O1, O2, Union]) of
- ?none when ThrowList =/= [] -> throw(hd(ThrowList));
+ ?none when ThrowList =/= [] -> throw({pos, lists:usort(ThrowList)});
Sup -> Sup
end.
@@ -3020,8 +3268,8 @@ inf_union_collect([E|L], Opaque, InfFun, InfList, ThrowList) ->
try InfFun(E, Opaque)of
Inf ->
inf_union_collect(L, Opaque, InfFun, [Inf|InfList], ThrowList)
- catch throw:N when is_integer(N) ->
- inf_union_collect(L, Opaque, InfFun, InfList, [N|ThrowList])
+ catch throw:{pos, Ns} ->
+ inf_union_collect(L, Opaque, InfFun, InfList, Ns ++ ThrowList)
end.
inf_union([?none|Left1], [?none|Left2], N, Acc, ThrowList, Opaques) ->
@@ -3030,8 +3278,8 @@ inf_union([T1|Left1], [T2|Left2], N, Acc, ThrowList, Opaques) ->
try t_inf(T1, T2, Opaques) of
?none -> inf_union(Left1, Left2, N, [?none|Acc], ThrowList, Opaques);
T -> inf_union(Left1, Left2, N+1, [T|Acc], ThrowList, Opaques)
- catch throw:N when is_integer(N) ->
- inf_union(Left1, Left2, N, [?none|Acc], [N|ThrowList], Opaques)
+ catch throw:{pos, Ns} ->
+ inf_union(Left1, Left2, N, [?none|Acc], Ns ++ ThrowList, Opaques)
end;
inf_union([], [], N, Acc, ThrowList, _Opaques) ->
if N =:= 0 -> {?none, ThrowList};
@@ -3066,87 +3314,33 @@ findfirst(N1, N2, U1, B1, U2, B2) ->
%%-----------------------------------------------------------------------------
%% Substitution of variables
%%
-%% Dialyzer versions prior to R15B used a dict data structure to map variables
-%% to types. Hans Bolinder suggested the use of lists of Key-Value pairs for
-%% this data structure and measurements showed a non-trivial speedup when using
-%% them for operations within this module (e.g. in t_unify/2). However, there
-%% is code outside erl_types that still passes a dict:dict() in the 2nd argument.
-%% So, for the time being, this module provides a t_subst/2 function for these
-%% external calls and a clone of it (t_subst_kv/2) which is used from all calls
-%% from within this module. This code duplication needs to be eliminated at
-%% some point.
-
--spec t_subst(erl_type(), dict:dict(atom(), erl_type())) -> erl_type().
-
-t_subst(T, Dict) ->
+
+-type subst_table() :: #{any() => erl_type()}.
+
+-spec t_subst(erl_type(), subst_table()) -> erl_type().
+
+t_subst(T, Map) ->
case t_has_var(T) of
- true -> t_subst_dict(T, Dict);
+ true -> t_subst_aux(T, Map);
false -> T
end.
-t_subst_dict(?var(Id), Dict) ->
- case dict:find(Id, Dict) of
- error -> ?any;
- {ok, Type} -> Type
- end;
-t_subst_dict(?list(Contents, Termination, Size), Dict) ->
- case t_subst_dict(Contents, Dict) of
- ?none -> ?none;
- NewContents ->
- %% Be careful here to make the termination collapse if necessary.
- case t_subst_dict(Termination, Dict) of
- ?nil -> ?list(NewContents, ?nil, Size);
- ?any -> ?list(NewContents, ?any, Size);
- Other ->
- ?list(NewContents2, NewTermination, _) = t_cons(NewContents, Other),
- ?list(NewContents2, NewTermination, Size)
- end
- end;
-t_subst_dict(?function(Domain, Range), Dict) ->
- ?function(t_subst_dict(Domain, Dict), t_subst_dict(Range, Dict));
-t_subst_dict(?product(Types), Dict) ->
- ?product([t_subst_dict(T, Dict) || T <- Types]);
-t_subst_dict(?tuple(?any, ?any, ?any) = T, _Dict) ->
- T;
-t_subst_dict(?tuple(Elements, _Arity, _Tag), Dict) ->
- t_tuple([t_subst_dict(E, Dict) || E <- Elements]);
-t_subst_dict(?tuple_set(_) = TS, Dict) ->
- t_sup([t_subst_dict(T, Dict) || T <- t_tuple_subtypes(TS)]);
-t_subst_dict(?map(Pairs), Dict) ->
- ?map([{t_subst_dict(K, Dict), t_subst_dict(V, Dict)} ||
- {K, V} <- Pairs]);
-t_subst_dict(?opaque(Es), Dict) ->
- List = [Opaque#opaque{args = [t_subst_dict(Arg, Dict) || Arg <- Args],
- struct = t_subst_dict(S, Dict)} ||
- Opaque = #opaque{args = Args, struct = S} <- set_to_list(Es)],
- ?opaque(ordsets:from_list(List));
-t_subst_dict(?union(List), Dict) ->
- ?union([t_subst_dict(E, Dict) || E <- List]);
-t_subst_dict(T, _Dict) ->
- T.
-
-spec subst_all_vars_to_any(erl_type()) -> erl_type().
subst_all_vars_to_any(T) ->
- t_subst_kv(T, []).
-
-t_subst_kv(T, KVMap) ->
- case t_has_var(T) of
- true -> t_subst_aux(T, KVMap);
- false -> T
- end.
+ t_subst(T, #{}).
-t_subst_aux(?var(Id), VarMap) ->
- case lists:keyfind(Id, 1, VarMap) of
- false -> ?any;
- {Id, Type} -> Type
+t_subst_aux(?var(Id), Map) ->
+ case maps:find(Id, Map) of
+ error -> ?any;
+ {ok, Type} -> Type
end;
-t_subst_aux(?list(Contents, Termination, Size), VarMap) ->
- case t_subst_aux(Contents, VarMap) of
+t_subst_aux(?list(Contents, Termination, Size), Map) ->
+ case t_subst_aux(Contents, Map) of
?none -> ?none;
NewContents ->
%% Be careful here to make the termination collapse if necessary.
- case t_subst_aux(Termination, VarMap) of
+ case t_subst_aux(Termination, Map) of
?nil -> ?list(NewContents, ?nil, Size);
?any -> ?list(NewContents, ?any, Size);
Other ->
@@ -3154,40 +3348,28 @@ t_subst_aux(?list(Contents, Termination, Size), VarMap) ->
?list(NewContents2, NewTermination, Size)
end
end;
-t_subst_aux(?function(Domain, Range), VarMap) ->
- ?function(t_subst_aux(Domain, VarMap), t_subst_aux(Range, VarMap));
-t_subst_aux(?product(Types), VarMap) ->
- ?product([t_subst_aux(T, VarMap) || T <- Types]);
-t_subst_aux(?tuple(?any, ?any, ?any) = T, _VarMap) ->
+t_subst_aux(?function(Domain, Range), Map) ->
+ ?function(t_subst_aux(Domain, Map), t_subst_aux(Range, Map));
+t_subst_aux(?product(Types), Map) ->
+ ?product([t_subst_aux(T, Map) || T <- Types]);
+t_subst_aux(?tuple(?any, ?any, ?any) = T, _Map) ->
T;
-t_subst_aux(?tuple(Elements, _Arity, _Tag), VarMap) ->
- t_tuple([t_subst_aux(E, VarMap) || E <- Elements]);
-t_subst_aux(?tuple_set(_) = TS, VarMap) ->
- t_sup([t_subst_aux(T, VarMap) || T <- t_tuple_subtypes(TS)]);
-t_subst_aux(?map(Pairs), VarMap) ->
- ?map([{t_subst_aux(K, VarMap), t_subst_aux(V, VarMap)} ||
- {K, V} <- Pairs]);
-t_subst_aux(?opaque(Es), VarMap) ->
- List = [Opaque#opaque{args = [t_subst_aux(Arg, VarMap) || Arg <- Args],
- struct = t_subst_aux(S, VarMap)} ||
- Opaque = #opaque{args = Args, struct = S} <- set_to_list(Es)],
- ?opaque(ordsets:from_list(List));
-t_subst_aux(?union(List), VarMap) ->
- ?union([t_subst_aux(E, VarMap) || E <- List]);
-t_subst_aux(T, _VarMap) ->
+t_subst_aux(?tuple(Elements, _Arity, _Tag), Map) ->
+ t_tuple([t_subst_aux(E, Map) || E <- Elements]);
+t_subst_aux(?tuple_set(_) = TS, Map) ->
+ t_sup([t_subst_aux(T, Map) || T <- t_tuple_subtypes(TS)]);
+t_subst_aux(?map(Pairs, DefK, DefV), Map) ->
+ t_map([{K, MNess, t_subst_aux(V, Map)} || {K, MNess, V} <- Pairs],
+ t_subst_aux(DefK, Map), t_subst_aux(DefV, Map));
+t_subst_aux(?opaque(Es), Map) ->
+ List = [Opaque#opaque{args = [t_subst_aux(Arg, Map) || Arg <- Args],
+ struct = t_subst_aux(S, Map)} ||
+ Opaque = #opaque{args = Args, struct = S} <- set_to_list(Es)],
+ ?opaque(ordsets:from_list(List));
+t_subst_aux(?union(List), Map) ->
+ ?union([t_subst_aux(E, Map) || E <- List]);
+t_subst_aux(T, _Map) ->
T.
-
--spec subst_all_remote(erl_type(), erl_type()) -> erl_type().
-
-subst_all_remote(Type0, Substitute) ->
- Map =
- fun(Type) ->
- case erl_types:t_is_remote(Type) of
- true -> Substitute;
- false -> Type
- end
- end,
- erl_types:t_map(Map, Type0).
%%-----------------------------------------------------------------------------
%% Unification
@@ -3198,33 +3380,33 @@ subst_all_remote(Type0, Substitute) ->
-spec t_unify(erl_type(), erl_type()) -> t_unify_ret().
t_unify(T1, T2) ->
- {T, VarMap} = t_unify(T1, T2, []),
- {t_subst_kv(T, VarMap), lists:keysort(1, VarMap)}.
+ {T, VarMap} = t_unify(T1, T2, #{}),
+ {t_subst(T, VarMap), lists:keysort(1, maps:to_list(VarMap))}.
t_unify(?var(Id) = T, ?var(Id), VarMap) ->
{T, VarMap};
t_unify(?var(Id1) = T, ?var(Id2), VarMap) ->
- case lists:keyfind(Id1, 1, VarMap) of
- false ->
- case lists:keyfind(Id2, 1, VarMap) of
- false -> {T, [{Id2, T} | VarMap]};
- {Id2, Type} -> t_unify(T, Type, VarMap)
+ case maps:find(Id1, VarMap) of
+ error ->
+ case maps:find(Id2, VarMap) of
+ error -> {T, VarMap#{Id2 => T}};
+ {ok, Type} -> t_unify(T, Type, VarMap)
end;
- {Id1, Type1} ->
- case lists:keyfind(Id2, 1, VarMap) of
- false -> {Type1, [{Id2, T} | VarMap]};
- {Id2, Type2} -> t_unify(Type1, Type2, VarMap)
+ {ok, Type1} ->
+ case maps:find(Id2, VarMap) of
+ error -> {Type1, VarMap#{Id2 => T}};
+ {ok, Type2} -> t_unify(Type1, Type2, VarMap)
end
end;
t_unify(?var(Id), Type, VarMap) ->
- case lists:keyfind(Id, 1, VarMap) of
- false -> {Type, [{Id, Type} | VarMap]};
- {Id, VarType} -> t_unify(VarType, Type, VarMap)
+ case maps:find(Id, VarMap) of
+ error -> {Type, VarMap#{Id => Type}};
+ {ok, VarType} -> t_unify(VarType, Type, VarMap)
end;
t_unify(Type, ?var(Id), VarMap) ->
- case lists:keyfind(Id, 1, VarMap) of
- false -> {Type, [{Id, Type} | VarMap]};
- {Id, VarType} -> t_unify(VarType, Type, VarMap)
+ case maps:find(Id, VarMap) of
+ error -> {Type, VarMap#{Id => Type}};
+ {ok, VarType} -> t_unify(VarType, Type, VarMap)
end;
t_unify(?function(Domain1, Range1), ?function(Domain2, Range2), VarMap) ->
{Domain, VarMap1} = t_unify(Domain1, Domain2, VarMap),
@@ -3258,6 +3440,23 @@ t_unify(?tuple_set(List1) = T1, ?tuple_set(List2) = T2, VarMap) ->
{Tuples, NewVarMap} -> {t_sup(Tuples), NewVarMap}
catch _:_ -> throw({mismatch, T1, T2})
end;
+t_unify(?map(_, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B, VarMap0) ->
+ {DefK, VarMap1} = t_unify(ADefK, BDefK, VarMap0),
+ {DefV, VarMap2} = t_unify(ADefV, BDefV, VarMap1),
+ {Pairs, VarMap} =
+ map_pairwise_merge_foldr(
+ fun(K, MNess, V1, MNess, V2, {Pairs0, VarMap3}) ->
+ %% We know that the keys unify and do not contain variables, or they
+ %% would not be singletons
+ %% TODO: Should V=?none (known missing keys) be handled special?
+ {V, VarMap4} = t_unify(V1, V2, VarMap3),
+ {[{K,MNess,V}|Pairs0], VarMap4};
+ (K, _, V1, _, V2, {Pairs0, VarMap3}) ->
+ %% One mandatory and one optional; what should be done in this case?
+ {V, VarMap4} = t_unify(V1, V2, VarMap3),
+ {[{K,?mand,V}|Pairs0], VarMap4}
+ end, {[], VarMap2}, A, B),
+ {t_map(Pairs, DefK, DefV), VarMap};
t_unify(?opaque(_) = T1, ?opaque(_) = T2, VarMap) ->
t_unify(t_opaque_structure(T1), t_opaque_structure(T2), VarMap);
t_unify(T1, ?opaque(_) = T2, VarMap) ->
@@ -3291,11 +3490,11 @@ unify_union1(?union(List), T1, T2) ->
end.
unify_union(List) ->
- [A,B,F,I,L,N,T,M,O,R,Map] = List,
+ [A,B,F,I,L,N,T,M,O,Map] = List,
if O =:= ?none -> no;
true ->
S = t_opaque_structure(O),
- {yes, t_sup([A,B,F,I,L,N,T,M,S,R,Map])}
+ {yes, t_sup([A,B,F,I,L,N,T,M,S,Map])}
end.
-spec is_opaque_type(erl_type(), [erl_type()]) -> boolean().
@@ -3317,8 +3516,8 @@ is_opaque_type2(#opaque{mod = Mod1, name = Name1, args = Args1}, Opaques) ->
is_type_name(Mod, Name, Args1, Mod, Name, Args2) ->
length(Args1) =:= length(Args2);
-is_type_name(Mod1, Name1, Args1, Mod2, Name2, Args2) ->
- is_same_type_name2(Mod1, Name1, Args1, Mod2, Name2, Args2).
+is_type_name(_Mod1, _Name1, _Args1, _Mod2, _Name2, _Args2) ->
+ false.
%% Two functions since t_unify is not symmetric.
unify_tuple_set_and_tuple1(?tuple_set([{Arity, List}]),
@@ -3461,7 +3660,7 @@ t_subtract_list(T, []) ->
-spec t_subtract(erl_type(), erl_type()) -> erl_type().
t_subtract(_, ?any) -> ?none;
-t_subtract(_, ?var(_)) -> ?none;
+t_subtract(T, ?var(_)) -> T;
t_subtract(?any, _) -> ?any;
t_subtract(?var(_) = T, _) -> T;
t_subtract(T, ?unit) -> T;
@@ -3614,8 +3813,50 @@ t_subtract(?product(Elements1) = T1, ?product(Elements2)) ->
_ -> T1
end
end;
-t_subtract(?map(_) = T, _) -> % XXX: very crude; will probably need refinement
- T;
+t_subtract(?map(APairs, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B) ->
+ case t_is_subtype(ADefK, BDefK) andalso t_is_subtype(ADefV, BDefV) of
+ false -> A;
+ true ->
+ %% We fold over the maps to produce a list of constraints, where
+ %% constraints are additional key-value pairs to put in Pairs. Only one
+ %% constraint need to be applied to produce a type that excludes the
+ %% right-hand-side type, so if more than one constraint is produced, we
+ %% just return the left-hand-side argument.
+ %%
+ %% Each case of the fold may either conclude that
+ %% * The arguments constrain A at least as much as B, i.e. that A so far
+ %% is a subtype of B. In that case they return false
+ %% * That for the particular arguments, A being a subtype of B does not
+ %% hold, but the infinimum of A and B is nonempty, and by narrowing a
+ %% pair in A, we can create a type that excludes some elements in the
+ %% infinumum. In that case, they will return that pair.
+ %% * That for the particular arguments, A being a subtype of B does not
+ %% hold, and either the infinumum of A and B is empty, or it is not
+ %% possible with the current representation to create a type that
+ %% excludes elements from B without also excluding elements that are
+ %% only in A. In that case, it will return the pair from A unchanged.
+ case
+ map_pairwise_merge(
+ %% If V1 is a subtype of V2, the case that K does not exist in A
+ %% remain.
+ fun(K, ?opt, V1, ?mand, V2) -> {K, ?opt, t_subtract(V1, V2)};
+ (K, _, V1, _, V2) ->
+ %% If we subtract an optional key, that leaves a mandatory key
+ case t_subtract(V1, V2) of
+ ?none -> false;
+ Partial -> {K, ?mand, Partial}
+ end
+ end, A, B)
+ of
+ %% We produce a list of keys that are constrained. As only one of
+ %% these should apply at a time, we can't represent the difference if
+ %% more than one constraint is produced. If we applied all of them,
+ %% that would make an underapproximation, which we must not do.
+ [] -> ?none; %% A is a subtype of B
+ [E] -> t_map(mapdict_store(E, APairs), ADefK, ADefV);
+ _ -> A
+ end
+ end;
t_subtract(?product(P1), _) ->
?product(P1);
t_subtract(T, ?product(_)) ->
@@ -3653,10 +3894,10 @@ t_subtract_lists([], [], Acc) ->
-spec subtract_union([erl_type(),...], [erl_type(),...]) -> erl_type().
subtract_union(U1, U2) ->
- [A1,B1,F1,I1,L1,N1,T1,M1,O1,R1,Map1] = U1,
- [A2,B2,F2,I2,L2,N2,T2,M2,O2,R2,Map2] = U2,
- List1 = [A1,B1,F1,I1,L1,N1,T1,M1,?none,R1,Map1],
- List2 = [A2,B2,F2,I2,L2,N2,T2,M2,?none,R2,Map2],
+ [A1,B1,F1,I1,L1,N1,T1,M1,O1,Map1] = U1,
+ [A2,B2,F2,I2,L2,N2,T2,M2,O2,Map2] = U2,
+ List1 = [A1,B1,F1,I1,L1,N1,T1,M1,?none,Map1],
+ List2 = [A2,B2,F2,I2,L2,N2,T2,M2,?none,Map2],
Sub1 = subtract_union(List1, List2, 0, []),
O = if O1 =:= ?none -> O1;
true -> t_subtract(O1, ?union(U2))
@@ -3746,12 +3987,17 @@ subtype_is_equal(T1, T2) ->
t_is_instance(ConcreteType, Type) ->
t_is_subtype(ConcreteType, t_unopaque(Type)).
+-spec t_do_overlap(erl_type(), erl_type()) -> boolean().
+
+t_do_overlap(TypeA, TypeB) ->
+ not (t_is_none_or_unit(t_inf(TypeA, TypeB))).
+
-spec t_unopaque(erl_type()) -> erl_type().
t_unopaque(T) ->
t_unopaque(T, 'universe').
--spec t_unopaque(erl_type(), 'universe' | [erl_type()]) -> erl_type().
+-spec t_unopaque(erl_type(), opaques()) -> erl_type().
t_unopaque(?opaque(_) = T, Opaques) ->
case Opaques =:= 'universe' orelse is_opaque_type(T, Opaques) of
@@ -3772,16 +4018,21 @@ t_unopaque(?product(Types), Opaques) ->
?product([t_unopaque(T, Opaques) || T <- Types]);
t_unopaque(?function(Domain, Range), Opaques) ->
?function(t_unopaque(Domain, Opaques), t_unopaque(Range, Opaques));
-t_unopaque(?union([A,B,F,I,L,N,T,M,O,R,Map]), Opaques) ->
+t_unopaque(?union([A,B,F,I,L,N,T,M,O,Map]), Opaques) ->
UL = t_unopaque(L, Opaques),
UT = t_unopaque(T, Opaques),
UF = t_unopaque(F, Opaques),
+ UM = t_unopaque(M, Opaques),
UMap = t_unopaque(Map, Opaques),
{OF,UO} = case t_unopaque(O, Opaques) of
?opaque(_) = O1 -> {O1, []};
Type -> {?none, [Type]}
end,
- t_sup([?union([A,B,UF,I,UL,N,UT,M,OF,R,UMap])|UO]);
+ t_sup([?union([A,B,UF,I,UL,N,UT,UM,OF,UMap])|UO]);
+t_unopaque(?map(Pairs,DefK,DefV), Opaques) ->
+ t_map([{K, MNess, t_unopaque(V, Opaques)} || {K, MNess, V} <- Pairs],
+ t_unopaque(DefK, Opaques),
+ t_unopaque(DefV, Opaques));
t_unopaque(T, _) ->
T.
@@ -3833,6 +4084,16 @@ t_limit_k(?opaque(Es), K) ->
Opaque#opaque{struct = NewS}
end || #opaque{struct = S} = Opaque <- set_to_list(Es)],
?opaque(ordsets:from_list(List));
+t_limit_k(?map(Pairs0, DefK0, DefV0), K) ->
+ Fun = fun({EK, MNess, EV}, {Exact, DefK1, DefV1}) ->
+ LV = t_limit_k(EV, K - 1),
+ case t_limit_k(EK, K - 1) of
+ EK -> {[{EK,MNess,LV}|Exact], DefK1, DefV1};
+ LK -> {Exact, t_sup(LK, DefK1), t_sup(LV, DefV1)}
+ end
+ end,
+ {Pairs, DefK2, DefV2} = lists:foldr(Fun, {[], DefK0, DefV0}, Pairs0),
+ t_map(Pairs, t_limit_k(DefK2, K - 1), t_limit_k(DefV2, K - 1));
t_limit_k(T, _K) -> T.
%%============================================================================
@@ -3869,7 +4130,7 @@ t_abstract_records(?tuple(Elements, Arity, ?atom(_) = Tag), RecDict) ->
[TagAtom] = atom_vals(Tag),
case lookup_record(TagAtom, Arity - 1, RecDict) of
error -> t_tuple([t_abstract_records(E, RecDict) || E <- Elements]);
- {ok, Fields} -> t_tuple([Tag|[T || {_Name, T} <- Fields]])
+ {ok, Fields} -> t_tuple([Tag|[T || {_Name, _Abstr, T} <- Fields]])
end;
t_abstract_records(?tuple(Elements, _Arity, _Tag), RecDict) ->
t_tuple([t_abstract_records(E, RecDict) || E <- Elements]);
@@ -3907,6 +4168,9 @@ t_map(Fun, ?opaque(Set)) ->
[] -> ?none;
_ -> ?opaque(ordsets:from_list(L))
end);
+t_map(Fun, ?map(Pairs,DefK,DefV)) ->
+ %% TODO:
+ Fun(t_map(Pairs, Fun(DefK), Fun(DefV)));
t_map(Fun, T) ->
Fun(T).
@@ -4048,18 +4312,22 @@ t_to_string(?float, _RecDict) -> "float()";
t_to_string(?number(?any, ?unknown_qual), _RecDict) -> "number()";
t_to_string(?product(List), RecDict) ->
"<" ++ comma_sequence(List, RecDict) ++ ">";
-t_to_string(?remote(Set), RecDict) ->
- string:join([case Args =:= [] of
- true -> flat_format("~w:~w()", [Mod, Name]);
- false ->
- ArgString = comma_sequence(Args, RecDict),
- flat_format("~w:~w(~s)", [Mod, Name, ArgString])
- end
- || #remote{mod = Mod, name = Name, args = Args} <-
- set_to_list(Set)],
- " | ");
-t_to_string(?map(Pairs), RecDict) ->
- "#{" ++ map_pairs_to_string(Pairs,RecDict) ++ "}";
+t_to_string(?map([],?any,?any), _RecDict) -> "map()";
+t_to_string(?map(Pairs0,DefK,DefV), RecDict) ->
+ {Pairs, ExtraEl} =
+ case {DefK, DefV} of
+ {?none, ?none} -> {Pairs0, []};
+ _ -> {Pairs0 ++ [{DefK,?opt,DefV}], []}
+ end,
+ Tos = fun(T) -> case T of
+ ?any -> "_";
+ _ -> t_to_string(T, RecDict)
+ end end,
+ StrMand = [{Tos(K),Tos(V)}||{K,?mand,V}<-Pairs],
+ StrOpt = [{Tos(K),Tos(V)}||{K,?opt,V}<-Pairs],
+ "#{" ++ string:join([K ++ ":=" ++ V||{K,V}<-StrMand]
+ ++ [K ++ "=>" ++ V||{K,V}<-StrOpt]
+ ++ ExtraEl, ", ") ++ "}";
t_to_string(?tuple(?any, ?any, ?any), _RecDict) -> "tuple()";
t_to_string(?tuple(Elements, _Arity, ?any), RecDict) ->
"{" ++ comma_sequence(Elements, RecDict) ++ "}";
@@ -4080,27 +4348,21 @@ t_to_string(?var(Id), _RecDict) when is_integer(Id) ->
flat_format("var(~w)", [Id]).
-map_pairs_to_string([],_) -> [];
-map_pairs_to_string(Pairs,RecDict) ->
- StrPairs = [{t_to_string(K,RecDict),t_to_string(V,RecDict)}||{K,V}<-Pairs],
- string:join([K ++ "=>" ++ V||{K,V}<-StrPairs], ", ").
-
-
record_to_string(Tag, [_|Fields], FieldNames, RecDict) ->
FieldStrings = record_fields_to_string(Fields, FieldNames, RecDict, []),
"#" ++ atom_to_string(Tag) ++ "{" ++ string:join(FieldStrings, ",") ++ "}".
-record_fields_to_string([F|Fs], [{FName, _DefType}|FDefs], RecDict, Acc) ->
+record_fields_to_string([F|Fs], [{FName, _Abstr, DefType}|FDefs],
+ RecDict, Acc) ->
NewAcc =
- case t_is_equal(F, t_any()) orelse t_is_any_atom('undefined', F) of
+ case
+ t_is_equal(F, t_any()) orelse
+ (t_is_any_atom('undefined', F) andalso
+ not t_is_none(t_inf(F, DefType)))
+ of
true -> Acc;
false ->
StrFV = atom_to_string(FName) ++ "::" ++ t_to_string(F, RecDict),
- %% ActualDefType = t_subtract(DefType, t_atom('undefined')),
- %% Str = case t_is_any(ActualDefType) of
- %% true -> StrFV;
- %% false -> StrFV ++ "::" ++ t_to_string(ActualDefType, RecDict)
- %% end,
[StrFV|Acc]
end,
record_fields_to_string(Fs, FDefs, RecDict, NewAcc);
@@ -4116,7 +4378,7 @@ record_field_diffs_to_string(?tuple([_|Fs], Arity, Tag), RecDict) ->
FieldDiffs = field_diffs(Fs, FieldNames, RecDict, []),
string:join(FieldDiffs, " and ").
-field_diffs([F|Fs], [{FName, DefType}|FDefs], RecDict, Acc) ->
+field_diffs([F|Fs], [{FName, _Abstr, DefType}|FDefs], RecDict, Acc) ->
%% Don't care about opaqueness for now.
NewAcc =
case not t_is_none(t_inf(F, DefType)) of
@@ -4156,15 +4418,7 @@ opaque_name(Mod, Name, Extra) ->
flat_format("~s(~s)", [S, Extra]).
mod_name(Mod, Name) ->
- case is_obsolete_opaque_builtin(Mod, Name) of
- true -> flat_format("~w", [Name]);
- false -> flat_format("~w:~w", [Mod, Name])
- end.
-
-is_obsolete_opaque_builtin(digraph, digraph) -> true;
-is_obsolete_opaque_builtin(gb_sets, gb_set) -> true;
-is_obsolete_opaque_builtin(gb_trees, gb_tree) -> true;
-is_obsolete_opaque_builtin(_, _) -> false.
+ flat_format("~w:~w", [Mod, Name]).
%%=============================================================================
%%
@@ -4172,374 +4426,728 @@ is_obsolete_opaque_builtin(_, _) -> false.
%%
%%=============================================================================
--spec t_from_form(parse_form()) -> erl_type().
-
-t_from_form(Form) ->
- t_from_form(Form, dict:new()).
-
--spec t_from_form(parse_form(), type_table()) -> erl_type().
-
-t_from_form(Form, RecDict) ->
- t_from_form(Form, RecDict, dict:new()).
+-type type_names() :: [type_key() | record_key()].
--spec t_from_form(parse_form(), type_table(), var_table()) -> erl_type().
+-type mta() :: {module(), atom(), arity()}.
+-type mra() :: {module(), atom(), arity()}.
+-type site() :: {'type', mta()} | {'spec', mfa()} | {'record', mra()}.
+-type cache_key() :: {module(), atom(), expand_depth(),
+ [erl_type()], type_names()}.
+-opaque cache() :: #{cache_key() => {erl_type(), expand_limit()}}.
+
+-spec t_from_form(parse_form(), sets:set(mfa()), site(), mod_records(),
+ var_table(), cache()) -> {erl_type(), cache()}.
+
+t_from_form(Form, ExpTypes, Site, RecDict, VarTab, Cache) ->
+ t_from_form1(Form, ExpTypes, Site, RecDict, VarTab, Cache).
+
+%% Replace external types with with none().
+-spec t_from_form_without_remote(parse_form(), site(), type_table()) ->
+ {erl_type(), cache()}.
+
+t_from_form_without_remote(Form, Site, TypeTable) ->
+ Module = site_module(Site),
+ RecDict = dict:from_list([{Module, TypeTable}]),
+ ExpTypes = replace_by_none,
+ VarTab = var_table__new(),
+ Cache = cache__new(),
+ t_from_form1(Form, ExpTypes, Site, RecDict, VarTab, Cache).
+
+%% REC_TYPE_LIMIT is used for limiting the depth of recursive types.
+%% EXPAND_LIMIT is used for limiting the size of types by
+%% limiting the number of elements of lists within one type form.
+%% EXPAND_DEPTH is used in conjunction with EXPAND_LIMIT to make the
+%% types balanced (unions will otherwise collapse to any()) by limiting
+%% the depth the same way as t_limit/2 does.
+
+-type expand_limit() :: integer().
+
+-type expand_depth() :: integer().
+
+-record(from_form, {site :: site(),
+ xtypes :: sets:set(mfa()) | 'replace_by_none',
+ mrecs :: mod_records(),
+ vtab :: var_table(),
+ tnames :: type_names()}).
+
+-spec t_from_form1(parse_form(), sets:set(mfa()) | 'replace_by_none',
+ site(), mod_records(), var_table(), cache()) ->
+ {erl_type(), cache()}.
+
+t_from_form1(Form, ET, Site, MR, V, C) ->
+ TypeNames = initial_typenames(Site),
+ State = #from_form{site = Site,
+ xtypes = ET,
+ mrecs = MR,
+ vtab = V,
+ tnames = TypeNames},
+ L = ?EXPAND_LIMIT,
+ {T1, L1, C1} = from_form(Form, State, ?EXPAND_DEPTH, L, C),
+ if
+ L1 =< 0 ->
+ from_form_loop(Form, State, 1, L, C1);
+ true ->
+ {T1, C1}
+ end.
-t_from_form(Form, RecDict, VarDict) ->
- {T, _R} = t_from_form(Form, [], RecDict, VarDict),
- T.
+initial_typenames({type, _MTA}=Site) -> [Site];
+initial_typenames({spec, _MFA}) -> [];
+initial_typenames({record, _MRA}) -> [].
--type type_names() :: [type_key() | record_key()].
-
--spec t_from_form(parse_form(), type_names(), type_table(), var_table()) ->
- {erl_type(), type_names()}.
+from_form_loop(Form, State, D, Limit, C) ->
+ {T1, L1, C1} = from_form(Form, State, D, Limit, C),
+ Delta = Limit - L1,
+ if
+ %% Save some time by assuming next depth will exceed the limit.
+ Delta * 8 > Limit ->
+ {T1, C1};
+ true ->
+ D1 = D + 1,
+ from_form_loop(Form, State, D1, Limit, C1)
+ end.
-t_from_form({var, _L, '_'}, _TypeNames, _RecDict, _VarDict) ->
- {t_any(), []};
-t_from_form({var, _L, Name}, _TypeNames, _RecDict, VarDict) ->
- case dict:find(Name, VarDict) of
- error -> {t_var(Name), []};
- {ok, Val} -> {Val, []}
+-spec from_form(parse_form(),
+ #from_form{},
+ expand_depth(),
+ expand_limit(),
+ cache()) -> {erl_type(), expand_limit(), cache()}.
+
+%% If there is something wrong with parse_form()
+%% throw({error, io_lib:chars()} is called;
+%% for unknown remote types
+%% self() ! {self(), ext_types, {RemMod, Name, ArgsLen}}
+%% is called, unless 'replace_by_none' is given.
+%%
+%% It is assumed that site_module(S) can be found in MR.
+
+from_form(_, _S, D, L, C) when D =< 0 ; L =< 0 ->
+ {t_any(), L, C};
+from_form({var, _L, '_'}, _S, _D, L, C) ->
+ {t_any(), L, C};
+from_form({var, _L, Name}, S, _D, L, C) ->
+ V = S#from_form.vtab,
+ case maps:find(Name, V) of
+ error -> {t_var(Name), L, C};
+ {ok, Val} -> {Val, L, C}
end;
-t_from_form({ann_type, _L, [_Var, Type]}, TypeNames, RecDict, VarDict) ->
- t_from_form(Type, TypeNames, RecDict, VarDict);
-t_from_form({paren_type, _L, [Type]}, TypeNames, RecDict, VarDict) ->
- t_from_form(Type, TypeNames, RecDict, VarDict);
-t_from_form({remote_type, _L, [{atom, _, Module}, {atom, _, Type}, Args]},
- TypeNames, RecDict, VarDict) ->
- {L, R} = list_from_form(Args, TypeNames, RecDict, VarDict),
- {t_remote(Module, Type, L), R};
-t_from_form({atom, _L, Atom}, _TypeNames, _RecDict, _VarDict) ->
- {t_atom(Atom), []};
-t_from_form({integer, _L, Int}, _TypeNames, _RecDict, _VarDict) ->
- {t_integer(Int), []};
-t_from_form({op, _L, _Op, _Arg} = Op, _TypeNames, _RecDict, _VarDict) ->
+from_form({ann_type, _L, [_Var, Type]}, S, D, L, C) ->
+ from_form(Type, S, D, L, C);
+from_form({paren_type, _L, [Type]}, S, D, L, C) ->
+ from_form(Type, S, D, L, C);
+from_form({remote_type, _L, [{atom, _, Module}, {atom, _, Type}, Args]},
+ S, D, L, C) ->
+ remote_from_form(Module, Type, Args, S, D, L, C);
+from_form({atom, _L, Atom}, _S, _D, L, C) ->
+ {t_atom(Atom), L, C};
+from_form({integer, _L, Int}, _S, _D, L, C) ->
+ {t_integer(Int), L, C};
+from_form({op, _L, _Op, _Arg} = Op, _S, _D, L, C) ->
case erl_eval:partial_eval(Op) of
{integer, _, Val} ->
- {t_integer(Val), []};
+ {t_integer(Val), L, C};
_ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Op])})
end;
-t_from_form({op, _L, _Op, _Arg1, _Arg2} = Op, _TypeNames,
- _RecDict, _VarDict) ->
+from_form({op, _L, _Op, _Arg1, _Arg2} = Op, _S, _D, L, C) ->
case erl_eval:partial_eval(Op) of
{integer, _, Val} ->
- {t_integer(Val), []};
+ {t_integer(Val), L, C};
_ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Op])})
end;
-t_from_form({type, _L, any, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_any(), []};
-t_from_form({type, _L, arity, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_arity(), []};
-t_from_form({type, _L, array, []}, TypeNames, RecDict, VarDict) ->
- builtin_type(array, t_array(), [], TypeNames, RecDict, VarDict);
-t_from_form({type, _L, atom, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_atom(), []};
-t_from_form({type, _L, binary, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_binary(), []};
-t_from_form({type, _L, binary, [Base, Unit]} = Type,
- _TypeNames, _RecDict, _VarDict) ->
+from_form({type, _L, any, []}, _S, _D, L, C) ->
+ {t_any(), L, C};
+from_form({type, _L, arity, []}, _S, _D, L, C) ->
+ {t_arity(), L, C};
+from_form({type, _L, atom, []}, _S, _D, L, C) ->
+ {t_atom(), L, C};
+from_form({type, _L, binary, []}, _S, _D, L, C) ->
+ {t_binary(), L, C};
+from_form({type, _L, binary, [Base, Unit]} = Type, _S, _D, L, C) ->
case {erl_eval:partial_eval(Base), erl_eval:partial_eval(Unit)} of
{{integer, _, B}, {integer, _, U}} when B >= 0, U >= 0 ->
- {t_bitstr(U, B), []};
+ {t_bitstr(U, B), L, C};
_ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Type])})
end;
-t_from_form({type, _L, bitstring, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_bitstr(), []};
-t_from_form({type, _L, bool, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_boolean(), []}; % XXX: Temporarily
-t_from_form({type, _L, boolean, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_boolean(), []};
-t_from_form({type, _L, byte, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_byte(), []};
-t_from_form({type, _L, char, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_char(), []};
-t_from_form({type, _L, dict, []}, TypeNames, RecDict, VarDict) ->
- builtin_type(dict, t_dict(), [], TypeNames, RecDict, VarDict);
-t_from_form({type, _L, digraph, []}, TypeNames, RecDict, VarDict) ->
- builtin_type(digraph, t_digraph(), [], TypeNames, RecDict, VarDict);
-t_from_form({type, _L, float, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_float(), []};
-t_from_form({type, _L, function, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_fun(), []};
-t_from_form({type, _L, 'fun', []}, _TypeNames, _RecDict, _VarDict) ->
- {t_fun(), []};
-t_from_form({type, _L, 'fun', [{type, _, any}, Range]}, TypeNames,
- RecDict, VarDict) ->
- {T, R} = t_from_form(Range, TypeNames, RecDict, VarDict),
- {t_fun(T), R};
-t_from_form({type, _L, 'fun', [{type, _, product, Domain}, Range]},
- TypeNames, RecDict, VarDict) ->
- {L, R1} = list_from_form(Domain, TypeNames, RecDict, VarDict),
- {T, R2} = t_from_form(Range, TypeNames, RecDict, VarDict),
- {t_fun(L, T), R1 ++ R2};
-t_from_form({type, _L, gb_set, []}, TypeNames, RecDict, VarDict) ->
- builtin_type(gb_set, t_gb_set(), [], TypeNames, RecDict, VarDict);
-t_from_form({type, _L, gb_tree, []}, TypeNames, RecDict, VarDict) ->
- builtin_type(gb_tree, t_gb_tree(), [], TypeNames, RecDict, VarDict);
-t_from_form({type, _L, identifier, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_identifier(), []};
-t_from_form({type, _L, integer, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_integer(), []};
-t_from_form({type, _L, iodata, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_iodata(), []};
-t_from_form({type, _L, iolist, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_iolist(), []};
-t_from_form({type, _L, list, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_list(), []};
-t_from_form({type, _L, list, [Type]}, TypeNames, RecDict, VarDict) ->
- {T, R} = t_from_form(Type, TypeNames, RecDict, VarDict),
- {t_list(T), R};
-t_from_form({type, _L, map, As0}, TypeNames, RecDict, VarDict) ->
- As = case is_list(As0) of
- true -> As0;
- false -> []
- end,
- builtin_type(map, t_map([]), As, TypeNames, RecDict, VarDict);
-t_from_form({type, _L, mfa, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_mfa(), []};
-t_from_form({type, _L, module, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_module(), []};
-t_from_form({type, _L, nil, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_nil(), []};
-t_from_form({type, _L, neg_integer, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_neg_integer(), []};
-t_from_form({type, _L, non_neg_integer, []}, _TypeNames, _RecDict,
- _VarDict) ->
- {t_non_neg_integer(), []};
-t_from_form({type, _L, no_return, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_unit(), []};
-t_from_form({type, _L, node, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_node(), []};
-t_from_form({type, _L, none, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_none(), []};
-t_from_form({type, _L, nonempty_list, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_nonempty_list(), []};
-t_from_form({type, _L, nonempty_list, [Type]}, TypeNames, RecDict, VarDict) ->
- {T, R} = t_from_form(Type, TypeNames, RecDict, VarDict),
- {t_nonempty_list(T), R};
-t_from_form({type, _L, nonempty_improper_list, [Cont, Term]}, TypeNames,
- RecDict, VarDict) ->
- {T1, R1} = t_from_form(Cont, TypeNames, RecDict, VarDict),
- {T2, R2} = t_from_form(Term, TypeNames, RecDict, VarDict),
- {t_cons(T1, T2), R1 ++ R2};
-t_from_form({type, _L, nonempty_maybe_improper_list, []}, _TypeNames,
- _RecDict, _VarDict) ->
- {t_cons(?any, ?any), []};
-t_from_form({type, _L, nonempty_maybe_improper_list, [Cont, Term]},
- TypeNames, RecDict, VarDict) ->
- {T1, R1} = t_from_form(Cont, TypeNames, RecDict, VarDict),
- {T2, R2} = t_from_form(Term, TypeNames, RecDict, VarDict),
- {t_cons(T1, T2), R1 ++ R2};
-t_from_form({type, _L, nonempty_string, []}, _TypeNames, _RecDict,
- _VarDict) ->
- {t_nonempty_string(), []};
-t_from_form({type, _L, number, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_number(), []};
-t_from_form({type, _L, pid, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_pid(), []};
-t_from_form({type, _L, port, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_port(), []};
-t_from_form({type, _L, pos_integer, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_pos_integer(), []};
-t_from_form({type, _L, maybe_improper_list, []}, _TypeNames,
- _RecDict, _VarDict) ->
- {t_maybe_improper_list(), []};
-t_from_form({type, _L, maybe_improper_list, [Content, Termination]},
- TypeNames, RecDict, VarDict) ->
- {T1, R1} = t_from_form(Content, TypeNames, RecDict, VarDict),
- {T2, R2} = t_from_form(Termination, TypeNames, RecDict, VarDict),
- {t_maybe_improper_list(T1, T2), R1 ++ R2};
-t_from_form({type, _L, product, Elements}, TypeNames, RecDict, VarDict) ->
- {L, R} = list_from_form(Elements, TypeNames, RecDict, VarDict),
- {t_product(L), R};
-t_from_form({type, _L, queue, []}, TypeNames, RecDict, VarDict) ->
- builtin_type(queue, t_queue(), [], TypeNames, RecDict, VarDict);
-t_from_form({type, _L, range, [From, To]} = Type,
- _TypeNames, _RecDict, _VarDict) ->
+from_form({type, _L, bitstring, []}, _S, _D, L, C) ->
+ {t_bitstr(), L, C};
+from_form({type, _L, bool, []}, _S, _D, L, C) ->
+ {t_boolean(), L, C}; % XXX: Temporarily
+from_form({type, _L, boolean, []}, _S, _D, L, C) ->
+ {t_boolean(), L, C};
+from_form({type, _L, byte, []}, _S, _D, L, C) ->
+ {t_byte(), L, C};
+from_form({type, _L, char, []}, _S, _D, L, C) ->
+ {t_char(), L, C};
+from_form({type, _L, float, []}, _S, _D, L, C) ->
+ {t_float(), L, C};
+from_form({type, _L, function, []}, _S, _D, L, C) ->
+ {t_fun(), L, C};
+from_form({type, _L, 'fun', []}, _S, _D, L, C) ->
+ {t_fun(), L, C};
+from_form({type, _L, 'fun', [{type, _, any}, Range]}, S, D, L, C) ->
+ {T, L1, C1} = from_form(Range, S, D - 1, L - 1, C),
+ {t_fun(T), L1, C1};
+from_form({type, _L, 'fun', [{type, _, product, Domain}, Range]},
+ S, D, L, C) ->
+ {Dom1, L1, C1} = list_from_form(Domain, S, D, L, C),
+ {Ran1, L2, C2} = from_form(Range, S, D, L1, C1),
+ {t_fun(Dom1, Ran1), L2, C2};
+from_form({type, _L, identifier, []}, _S, _D, L, C) ->
+ {t_identifier(), L, C};
+from_form({type, _L, integer, []}, _S, _D, L, C) ->
+ {t_integer(), L, C};
+from_form({type, _L, iodata, []}, _S, _D, L, C) ->
+ {t_iodata(), L, C};
+from_form({type, _L, iolist, []}, _S, _D, L, C) ->
+ {t_iolist(), L, C};
+from_form({type, _L, list, []}, _S, _D, L, C) ->
+ {t_list(), L, C};
+from_form({type, _L, list, [Type]}, S, D, L, C) ->
+ {T, L1, C1} = from_form(Type, S, D - 1, L - 1, C),
+ {t_list(T), L1, C1};
+from_form({type, _L, map, any}, S, D, L, C) ->
+ builtin_type(map, t_map(), S, D, L, C);
+from_form({type, _L, map, List}, S, D0, L, C) ->
+ {Pairs1, L5, C5} =
+ fun PairsFromForm(_, L1, C1) when L1 =< 0 -> {[{?any,?opt,?any}], L1, C1};
+ PairsFromForm([], L1, C1) -> {[], L1, C1};
+ PairsFromForm([{type, _, Oper, [KF, VF]}|T], L1, C1) ->
+ D = D0 - 1,
+ {Key, L2, C2} = from_form(KF, S, D, L1, C1),
+ {Val, L3, C3} = from_form(VF, S, D, L2, C2),
+ {Pairs0, L4, C4} = PairsFromForm(T, L3 - 1, C3),
+ case Oper of
+ map_field_assoc -> {[{Key,?opt, Val}|Pairs0], L4, C4};
+ map_field_exact -> {[{Key,?mand,Val}|Pairs0], L4, C4}
+ end
+ end(List, L, C),
+ try
+ {Pairs, DefK, DefV} = map_from_form(Pairs1, [], [], [], ?none, ?none),
+ {t_map(Pairs, DefK, DefV), L5, C5}
+ catch none -> {t_none(), L5, C5}
+ end;
+from_form({type, _L, mfa, []}, _S, _D, L, C) ->
+ {t_mfa(), L, C};
+from_form({type, _L, module, []}, _S, _D, L, C) ->
+ {t_module(), L, C};
+from_form({type, _L, nil, []}, _S, _D, L, C) ->
+ {t_nil(), L, C};
+from_form({type, _L, neg_integer, []}, _S, _D, L, C) ->
+ {t_neg_integer(), L, C};
+from_form({type, _L, non_neg_integer, []}, _S, _D, L, C) ->
+ {t_non_neg_integer(), L, C};
+from_form({type, _L, no_return, []}, _S, _D, L, C) ->
+ {t_unit(), L, C};
+from_form({type, _L, node, []}, _S, _D, L, C) ->
+ {t_node(), L, C};
+from_form({type, _L, none, []}, _S, _D, L, C) ->
+ {t_none(), L, C};
+from_form({type, _L, nonempty_list, []}, _S, _D, L, C) ->
+ {t_nonempty_list(), L, C};
+from_form({type, _L, nonempty_list, [Type]}, S, D, L, C) ->
+ {T, L1, C1} = from_form(Type, S, D, L - 1, C),
+ {t_nonempty_list(T), L1, C1};
+from_form({type, _L, nonempty_improper_list, [Cont, Term]}, S, D, L, C) ->
+ {T1, L1, C1} = from_form(Cont, S, D, L - 1, C),
+ {T2, L2, C2} = from_form(Term, S, D, L1, C1),
+ {t_cons(T1, T2), L2, C2};
+from_form({type, _L, nonempty_maybe_improper_list, []}, _S, _D, L, C) ->
+ {t_cons(?any, ?any), L, C};
+from_form({type, _L, nonempty_maybe_improper_list, [Cont, Term]},
+ S, D, L, C) ->
+ {T1, L1, C1} = from_form(Cont, S, D, L - 1, C),
+ {T2, L2, C2} = from_form(Term, S, D, L1, C1),
+ {t_cons(T1, T2), L2, C2};
+from_form({type, _L, nonempty_string, []}, _S, _D, L, C) ->
+ {t_nonempty_string(), L, C};
+from_form({type, _L, number, []}, _S, _D, L, C) ->
+ {t_number(), L, C};
+from_form({type, _L, pid, []}, _S, _D, L, C) ->
+ {t_pid(), L, C};
+from_form({type, _L, port, []}, _S, _D, L, C) ->
+ {t_port(), L, C};
+from_form({type, _L, pos_integer, []}, _S, _D, L, C) ->
+ {t_pos_integer(), L, C};
+from_form({type, _L, maybe_improper_list, []}, _S, _D, L, C) ->
+ {t_maybe_improper_list(), L, C};
+from_form({type, _L, maybe_improper_list, [Content, Termination]},
+ S, D, L, C) ->
+ {T1, L1, C1} = from_form(Content, S, D, L - 1, C),
+ {T2, L2, C2} = from_form(Termination, S, D, L1, C1),
+ {t_maybe_improper_list(T1, T2), L2, C2};
+from_form({type, _L, product, Elements}, S, D, L, C) ->
+ {Lst, L1, C1} = list_from_form(Elements, S, D - 1, L, C),
+ {t_product(Lst), L1, C1};
+from_form({type, _L, range, [From, To]} = Type, _S, _D, L, C) ->
case {erl_eval:partial_eval(From), erl_eval:partial_eval(To)} of
{{integer, _, FromVal}, {integer, _, ToVal}} ->
- {t_from_range(FromVal, ToVal), []};
+ {t_from_range(FromVal, ToVal), L, C};
_ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Type])})
end;
-t_from_form({type, _L, record, [Name|Fields]}, TypeNames, RecDict, VarDict) ->
- record_from_form(Name, Fields, TypeNames, RecDict, VarDict);
-t_from_form({type, _L, reference, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_reference(), []};
-t_from_form({type, _L, set, []}, TypeNames, RecDict, VarDict) ->
- builtin_type(set, t_set(), [], TypeNames, RecDict, VarDict);
-t_from_form({type, _L, string, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_string(), []};
-t_from_form({type, _L, term, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_any(), []};
-t_from_form({type, _L, tid, []}, TypeNames, RecDict, VarDict) ->
- builtin_type(tid, t_tid(), [], TypeNames, RecDict, VarDict);
-t_from_form({type, _L, timeout, []}, _TypeNames, _RecDict, _VarDict) ->
- {t_timeout(), []};
-t_from_form({type, _L, tuple, any}, _TypeNames, _RecDict, _VarDict) ->
- {t_tuple(), []};
-t_from_form({type, _L, tuple, Args}, TypeNames, RecDict, VarDict) ->
- {L, R} = list_from_form(Args, TypeNames, RecDict, VarDict),
- {t_tuple(L), R};
-t_from_form({type, _L, union, Args}, TypeNames, RecDict, VarDict) ->
- {L, R} = list_from_form(Args, TypeNames, RecDict, VarDict),
- {t_sup(L), R};
-t_from_form({type, _L, Name, Args}, TypeNames, RecDict, VarDict) ->
- type_from_form(Name, Args, TypeNames, RecDict, VarDict);
-t_from_form({opaque, _L, Name, {Mod, Args, Rep}}, _TypeNames,
- _RecDict, _VarDict) ->
- {t_opaque(Mod, Name, Args, Rep), []}.
-
-builtin_type(Name, Type, Args, TypeNames, RecDict, VarDict) ->
- case lookup_type(Name, length(Args), RecDict) of
- {_, {_M, _T, _A}} ->
- type_from_form(Name, Args, TypeNames, RecDict, VarDict);
+from_form({type, _L, record, [Name|Fields]}, S, D, L, C) ->
+ record_from_form(Name, Fields, S, D, L, C);
+from_form({type, _L, reference, []}, _S, _D, L, C) ->
+ {t_reference(), L, C};
+from_form({type, _L, string, []}, _S, _D, L, C) ->
+ {t_string(), L, C};
+from_form({type, _L, term, []}, _S, _D, L, C) ->
+ {t_any(), L, C};
+from_form({type, _L, timeout, []}, _S, _D, L, C) ->
+ {t_timeout(), L, C};
+from_form({type, _L, tuple, any}, _S, _D, L, C) ->
+ {t_tuple(), L, C};
+from_form({type, _L, tuple, Args}, S, D, L, C) ->
+ {Lst, L1, C1} = list_from_form(Args, S, D - 1, L, C),
+ {t_tuple(Lst), L1, C1};
+from_form({type, _L, union, Args}, S, D, L, C) ->
+ {Lst, L1, C1} = list_from_form(Args, S, D, L, C),
+ {t_sup(Lst), L1, C1};
+from_form({user_type, _L, Name, Args}, S, D, L, C) ->
+ type_from_form(Name, Args, S, D, L, C);
+from_form({type, _L, Name, Args}, S, D, L, C) ->
+ %% Compatibility: modules compiled before Erlang/OTP 18.0.
+ type_from_form(Name, Args, S, D, L, C);
+from_form({opaque, _L, Name, {Mod, Args, Rep}}, _S, _D, L, C) ->
+ %% XXX. To be removed.
+ {t_opaque(Mod, Name, Args, Rep), L, C}.
+
+builtin_type(Name, Type, S, D, L, C) ->
+ #from_form{site = Site, mrecs = MR} = S,
+ M = site_module(Site),
+ case dict:find(M, MR) of
+ {ok, R} ->
+ case lookup_type(Name, 0, R) of
+ {_, {{_M, _FL, _F, _A}, _T}} ->
+ type_from_form(Name, [], S, D, L, C);
+ error ->
+ {Type, L, C}
+ end;
error ->
- {Type, []}
+ {Type, L, C}
end.
-type_from_form(Name, Args, TypeNames, RecDict, VarDict) ->
+type_from_form(Name, Args, S, D, L, C) ->
+ #from_form{site = Site, mrecs = MR, tnames = TypeNames} = S,
ArgsLen = length(Args),
- ArgTypes = forms_to_types(Args, TypeNames, RecDict, VarDict),
- case lookup_type(Name, ArgsLen, RecDict) of
- {type, {_Module, Type, ArgNames}} ->
- TypeName = {type, Name, ArgsLen},
- case can_unfold_more(TypeName, TypeNames) of
- true ->
+ Module = site_module(Site),
+ TypeName = {type, {Module, Name, ArgsLen}},
+ case can_unfold_more(TypeName, TypeNames) of
+ true ->
+ {ok, R} = dict:find(Module, MR),
+ type_from_form1(Name, Args, ArgsLen, R, TypeName, TypeNames,
+ S, D, L, C);
+ false ->
+ {t_any(), L, C}
+ end.
+
+type_from_form1(Name, Args, ArgsLen, R, TypeName, TypeNames, S, D, L, C) ->
+ case lookup_type(Name, ArgsLen, R) of
+ {Tag, {{Module, _FileName, Form, ArgNames}, Type}} ->
+ NewTypeNames = [TypeName|TypeNames],
+ S1 = S#from_form{tnames = NewTypeNames},
+ {ArgTypes, L1, C1} = list_from_form(Args, S1, D, L, C),
+ CKey = cache_key(Module, Name, ArgTypes, TypeNames, D),
+ case cache_find(CKey, C) of
+ {CachedType, DeltaL} ->
+ {CachedType, L1 - DeltaL, C};
+ error ->
List = lists:zip(ArgNames, ArgTypes),
- TmpVarDict = dict:from_list(List),
- {T, R} = t_from_form(Type, [TypeName|TypeNames],
- RecDict, TmpVarDict),
- case lists:member(TypeName, R) of
- true -> {t_limit(T, ?REC_TYPE_LIMIT), R};
- false -> {T, R}
- end;
- false -> {t_any(), [TypeName]}
+ TmpV = maps:from_list(List),
+ S2 = S1#from_form{site = TypeName, vtab = TmpV},
+ Fun = fun(DD, LL) -> from_form(Form, S2, DD, LL, C1) end,
+ {NewType, L3, C3} =
+ case Tag of
+ type ->
+ recur_limit(Fun, D, L1, TypeName, TypeNames);
+ opaque ->
+ {Rep, L2, C2} = recur_limit(Fun, D, L1, TypeName, TypeNames),
+ Rep1 = choose_opaque_type(Rep, Type),
+ Rep2 = case cannot_have_opaque(Rep1, TypeName, TypeNames) of
+ true -> Rep;
+ false ->
+ ArgTypes2 = subst_all_vars_to_any_list(ArgTypes),
+ t_opaque(Module, Name, ArgTypes2, Rep1)
+ end,
+ {Rep2, L2, C2}
+ end,
+ C4 = cache_put(CKey, NewType, L1 - L3, C3),
+ {NewType, L3, C4}
+ end;
+ error ->
+ Msg = io_lib:format("Unable to find type ~w/~w\n",
+ [Name, ArgsLen]),
+ throw({error, Msg})
+ end.
+
+remote_from_form(RemMod, Name, Args, S, D, L, C) ->
+ #from_form{xtypes = ET, mrecs = MR, tnames = TypeNames} = S,
+ if
+ ET =:= replace_by_none ->
+ {t_none(), L, C};
+ true ->
+ ArgsLen = length(Args),
+ MFA = {RemMod, Name, ArgsLen},
+ case dict:find(RemMod, MR) of
+ error ->
+ self() ! {self(), ext_types, MFA},
+ {t_any(), L, C};
+ {ok, RemDict} ->
+ case sets:is_element(MFA, ET) of
+ true ->
+ RemType = {type, MFA},
+ case can_unfold_more(RemType, TypeNames) of
+ true ->
+ remote_from_form1(RemMod, Name, Args, ArgsLen, RemDict,
+ RemType, TypeNames, S, D, L, C);
+ false ->
+ {t_any(), L, C}
+ end;
+ false ->
+ self() ! {self(), ext_types, {RemMod, Name, ArgsLen}},
+ {t_any(), L, C}
+ end
+ end
+ end.
+
+remote_from_form1(RemMod, Name, Args, ArgsLen, RemDict, RemType, TypeNames,
+ S, D, L, C) ->
+ case lookup_type(Name, ArgsLen, RemDict) of
+ {Tag, {{Mod, _FileLine, Form, ArgNames}, Type}} ->
+ NewTypeNames = [RemType|TypeNames],
+ S1 = S#from_form{tnames = NewTypeNames},
+ {ArgTypes, L1, C1} = list_from_form(Args, S1, D, L, C),
+ CKey = cache_key(RemMod, Name, ArgTypes, TypeNames, D),
+ %% case error of
+ case cache_find(CKey, C) of
+ {CachedType, DeltaL} ->
+ {CachedType, L - DeltaL, C};
+ error ->
+ List = lists:zip(ArgNames, ArgTypes),
+ TmpVarTab = maps:from_list(List),
+ S2 = S1#from_form{site = RemType, vtab = TmpVarTab},
+ Fun = fun(DD, LL) -> from_form(Form, S2, DD, LL, C1) end,
+ {NewType, L3, C3} =
+ case Tag of
+ type ->
+ recur_limit(Fun, D, L1, RemType, TypeNames);
+ opaque ->
+ {NewRep, L2, C2} = recur_limit(Fun, D, L1, RemType, TypeNames),
+ NewRep1 = choose_opaque_type(NewRep, Type),
+ NewRep2 =
+ case cannot_have_opaque(NewRep1, RemType, TypeNames) of
+ true -> NewRep;
+ false ->
+ ArgTypes2 = subst_all_vars_to_any_list(ArgTypes),
+ t_opaque(Mod, Name, ArgTypes2, NewRep1)
+ end,
+ {NewRep2, L2, C2}
+ end,
+ C4 = cache_put(CKey, NewType, L1 - L3, C3),
+ {NewType, L3, C4}
end;
- {opaque, {Module, Type, ArgNames}} ->
- TypeName = {opaque, Name, ArgsLen},
- {Rep, Rret} =
- case can_unfold_more(TypeName, TypeNames) of
- true ->
- List = lists:zip(ArgNames, ArgTypes),
- TmpVarDict = dict:from_list(List),
- {T, R} = t_from_form(Type, [TypeName|TypeNames],
- RecDict, TmpVarDict),
- case lists:member(TypeName, R) of
- true -> {t_limit(T, ?REC_TYPE_LIMIT), R};
- false -> {T, R}
- end;
- false -> {t_any(), [TypeName]}
- end,
- Args2 = [subst_all_vars_to_any(ArgType) || ArgType <- ArgTypes],
- {skip_opaque_alias(Rep, Module, Name, Args2), Rret};
error ->
- Msg = io_lib:format("Unable to find type ~w/~w\n", [Name, ArgsLen]),
+ Msg = io_lib:format("Unable to find remote type ~w:~w()\n",
+ [RemMod, Name]),
throw({error, Msg})
end.
-forms_to_types(Forms, TypeNames, RecDict, VarDict) ->
- {Types, _} = list_from_form(Forms, TypeNames, RecDict, VarDict),
- Types.
+subst_all_vars_to_any_list(Types) ->
+ [subst_all_vars_to_any(Type) || Type <- Types].
-skip_opaque_alias(?opaque(_) = T, _Mod, _Name, _Args) -> T;
-skip_opaque_alias(T, Module, Name, Args) ->
- t_opaque(Module, Name, Args, T).
+%% Opaque types (both local and remote) are problematic when it comes
+%% to the limits (TypeNames, D, and L). The reason is that if any() is
+%% substituted for a more specialized subtype of an opaque type, the
+%% property stated along with decorate_with_opaque() (the type has to
+%% be a subtype of the declared type) no longer holds.
+%%
+%% The less than perfect remedy: if the opaque type created from a
+%% form is not a subset of the declared type, the declared type is
+%% used instead, effectively bypassing the limits, and potentially
+%% resulting in huge types.
+choose_opaque_type(Type, DeclType) ->
+ case
+ t_is_subtype(subst_all_vars_to_any(Type),
+ subst_all_vars_to_any(DeclType))
+ of
+ true -> Type;
+ false -> DeclType
+ end.
-record_from_form({atom, _, Name}, ModFields, TypeNames, RecDict, VarDict) ->
- case can_unfold_more({record, Name}, TypeNames) of
+record_from_form({atom, _, Name}, ModFields, S, D0, L0, C) ->
+ #from_form{site = Site, mrecs = MR, tnames = TypeNames} = S,
+ RecordType = {record, Name},
+ case can_unfold_more(RecordType, TypeNames) of
true ->
- case lookup_record(Name, RecDict) of
+ M = site_module(Site),
+ {ok, R} = dict:find(M, MR),
+ case lookup_record(Name, R) of
{ok, DeclFields} ->
- TypeNames1 = [{record, Name}|TypeNames],
- AreTyped = [is_erl_type(FieldType)
- || {_FieldName, FieldType} <- DeclFields],
- {DeclFields1, R1} =
- case lists:all(fun(Elem) -> Elem end, AreTyped) of
- true -> {DeclFields, []};
- false -> fields_from_form(DeclFields, TypeNames1,
- RecDict, dict:new())
- end,
- {GetModRec, R2} = get_mod_record(ModFields, DeclFields1,
- TypeNames1,
- RecDict, VarDict),
- case GetModRec of
- {error, FieldName} ->
- throw({error, io_lib:format("Illegal declaration of #~w{~w}\n",
- [Name, FieldName])});
- {ok, NewFields} ->
- {t_tuple(
- [t_atom(Name)|[Type || {_FieldName, Type} <- NewFields]]),
- R1 ++ R2}
- end;
+ NewTypeNames = [RecordType|TypeNames],
+ Site1 = {record, {M, Name, length(DeclFields)}},
+ S1 = S#from_form{site = Site1, tnames = NewTypeNames},
+ Fun = fun(D, L) ->
+ {GetModRec, L1, C1} =
+ get_mod_record(ModFields, DeclFields, S1, D, L, C),
+ case GetModRec of
+ {error, FieldName} ->
+ throw({error,
+ io_lib:format("Illegal declaration of #~w{~w}\n",
+ [Name, FieldName])});
+ {ok, NewFields} ->
+ S2 = S1#from_form{vtab = var_table__new()},
+ {NewFields1, L2, C2} =
+ fields_from_form(NewFields, S2, D, L1, C1),
+ Rec = t_tuple(
+ [t_atom(Name)|[Type
+ || {_FieldName, Type} <- NewFields1]]),
+ {Rec, L2, C2}
+ end
+ end,
+ recur_limit(Fun, D0, L0, RecordType, TypeNames);
error ->
throw({error, io_lib:format("Unknown record #~w{}\n", [Name])})
end;
- false -> {t_any(), []}
+ false ->
+ {t_any(), L0, C}
end.
-get_mod_record([], DeclFields, _TypeNames, _RecDict, _VarDict) ->
- {{ok, DeclFields}, []};
-get_mod_record(ModFields, DeclFields, TypeNames, RecDict, VarDict) ->
- DeclFieldsDict = orddict:from_list(DeclFields),
- {ModFieldsDict, R} = build_field_dict(ModFields, TypeNames,
- RecDict, VarDict),
- case get_mod_record(DeclFieldsDict, ModFieldsDict, []) of
- {error, _FieldName} = Error -> {Error, R};
- {ok, FinalOrdDict} ->
- {{ok, [{FieldName, orddict:fetch(FieldName, FinalOrdDict)}
- || {FieldName, _} <- DeclFields]},
- R}
+get_mod_record([], DeclFields, _S, _D, L, C) ->
+ {{ok, DeclFields}, L, C};
+get_mod_record(ModFields, DeclFields, S, D, L, C) ->
+ DeclFieldsDict = lists:keysort(1, DeclFields),
+ {ModFieldsDict, L1, C1} = build_field_dict(ModFields, S, D, L, C),
+ case get_mod_record_types(DeclFieldsDict, ModFieldsDict, []) of
+ {error, _FieldName} = Error -> {Error, L1, C1};
+ {ok, FinalKeyDict} ->
+ Fields = [lists:keyfind(FieldName, 1, FinalKeyDict)
+ || {FieldName, _, _} <- DeclFields],
+ {{ok, Fields}, L1, C1}
end.
-build_field_dict(FieldTypes, TypeNames, RecDict, VarDict) ->
- build_field_dict(FieldTypes, TypeNames, RecDict, VarDict, []).
-
-build_field_dict([{type, _, field_type, [{atom, _, Name}, Type]}|Left],
- TypeNames, RecDict, VarDict, Acc) ->
- {T, R1} = t_from_form(Type, TypeNames, RecDict, VarDict),
- NewAcc = [{Name, T}|Acc],
- {D, R2} = build_field_dict(Left, TypeNames, RecDict, VarDict, NewAcc),
- {D, R1 ++ R2};
-build_field_dict([], _TypeNames, _RecDict, _VarDict, Acc) ->
- {orddict:from_list(Acc), []}.
-
-get_mod_record([{FieldName, DeclType}|Left1],
- [{FieldName, ModType}|Left2], Acc) ->
- ModTypeNoVars = subst_all_vars_to_any(ModType),
- case
- contains_remote(ModTypeNoVars)
- orelse contains_remote(DeclType)
- orelse t_is_subtype(ModTypeNoVars, DeclType)
- of
- false -> {error, FieldName};
- true -> get_mod_record(Left1, Left2, [{FieldName, ModType}|Acc])
- end;
-get_mod_record([{FieldName1, _DeclType} = DT|Left1],
- [{FieldName2, _ModType}|_] = List2,
- Acc) when FieldName1 < FieldName2 ->
- get_mod_record(Left1, List2, [DT|Acc]);
-get_mod_record(DeclFields, [], Acc) ->
- {ok, orddict:from_list(Acc ++ DeclFields)};
-get_mod_record(_, [{FieldName2, _ModType}|_], _Acc) ->
+build_field_dict(FieldTypes, S, D, L, C) ->
+ build_field_dict(FieldTypes, S, D, L, C, []).
+
+build_field_dict([{type, _, field_type, [{atom, _, Name}, Type]}|Left],
+ S, D, L, C, Acc) ->
+ {T, L1, C1} = from_form(Type, S, D, L - 1, C),
+ NewAcc = [{Name, Type, T}|Acc],
+ build_field_dict(Left, S, D, L1, C1, NewAcc);
+build_field_dict([], _S, _D, L, C, Acc) ->
+ {lists:keysort(1, Acc), L, C}.
+
+get_mod_record_types([{FieldName, _Abstr, _DeclType}|Left1],
+ [{FieldName, TypeForm, ModType}|Left2],
+ Acc) ->
+ get_mod_record_types(Left1, Left2, [{FieldName, TypeForm, ModType}|Acc]);
+get_mod_record_types([{FieldName1, _Abstr, _DeclType} = DT|Left1],
+ [{FieldName2, _FormType, _ModType}|_] = List2,
+ Acc) when FieldName1 < FieldName2 ->
+ get_mod_record_types(Left1, List2, [DT|Acc]);
+get_mod_record_types(Left1, [], Acc) ->
+ {ok, lists:keysort(1, Left1++Acc)};
+get_mod_record_types(_, [{FieldName2, _FormType, _ModType}|_], _Acc) ->
{error, FieldName2}.
-contains_remote(Type) ->
- TypeNoRemote = subst_all_remote(Type, t_none()),
- not t_is_equal(Type, TypeNoRemote).
-
-fields_from_form([], _TypeNames, _RecDict, _VarDict) ->
- {[], []};
-fields_from_form([{Name, Type}|Tail], TypeNames, RecDict,
- VarDict) ->
- {T, R1} = t_from_form(Type, TypeNames, RecDict, VarDict),
- {F, R2} = fields_from_form(Tail, TypeNames, RecDict, VarDict),
- {[{Name, T}|F], R1 ++ R2}.
-
-list_from_form([], _TypeNames, _RecDict, _VarDict) ->
- {[], []};
-list_from_form([H|Tail], TypeNames, RecDict, VarDict) ->
- {T, R1} = t_from_form(H, TypeNames, RecDict, VarDict),
- {L, R2} = list_from_form(Tail, TypeNames, RecDict, VarDict),
- {[T|L], R1 ++ R2}.
+%% It is important to create a limited version of the record type
+%% since nested record types can otherwise easily result in huge
+%% terms.
+fields_from_form([], _S, _D, L, C) ->
+ {[], L, C};
+fields_from_form([{Name, Abstr, _Type}|Tail], S, D, L, C) ->
+ {T, L1, C1} = from_form(Abstr, S, D, L, C),
+ {F, L2, C2} = fields_from_form(Tail, S, D, L1, C1),
+ {[{Name, T}|F], L2, C2}.
+
+list_from_form([], _S, _D, L, C) ->
+ {[], L, C};
+list_from_form([H|Tail], S, D, L, C) ->
+ {H1, L1, C1} = from_form(H, S, D, L - 1, C),
+ {T1, L2, C2} = list_from_form(Tail, S, D, L1, C1),
+ {[H1|T1], L2, C2}.
+
+%% Sorts, combines non-singleton pairs, and applies precendence and
+%% mandatoriness rules.
+map_from_form([], ShdwPs, MKs, Pairs, DefK, DefV) ->
+ verify_possible(MKs, ShdwPs),
+ {promote_to_mand(MKs, Pairs), DefK, DefV};
+map_from_form([{SKey,MNess,Val}|SPairs], ShdwPs0, MKs0, Pairs0, DefK0, DefV0) ->
+ Key = lists:foldl(fun({K,_},S)->t_subtract(S,K)end, SKey, ShdwPs0),
+ ShdwPs = case Key of ?none -> ShdwPs0; _ -> [{Key,Val}|ShdwPs0] end,
+ MKs = case MNess of ?mand -> [SKey|MKs0]; ?opt -> MKs0 end,
+ if MNess =:= ?mand, SKey =:= ?none -> throw(none);
+ true -> ok
+ end,
+ {Pairs, DefK, DefV} =
+ case is_singleton_type(Key) of
+ true ->
+ MNess1 = case Val =:= ?none of true -> ?opt; false -> MNess end,
+ {mapdict_insert({Key,MNess1,Val}, Pairs0), DefK0, DefV0};
+ false ->
+ case Key =:= ?none orelse Val =:= ?none of
+ true -> {Pairs0, DefK0, DefV0};
+ false -> {Pairs0, t_sup(DefK0, Key), t_sup(DefV0, Val)}
+ end
+ end,
+ map_from_form(SPairs, ShdwPs, MKs, Pairs, DefK, DefV).
+
+%% Verifies that all mandatory keys are possible, throws 'none' otherwise
+verify_possible(MKs, ShdwPs) ->
+ lists:foreach(fun(M) -> verify_possible_1(M, ShdwPs) end, MKs).
+
+verify_possible_1(M, ShdwPs) ->
+ case lists:any(fun({K,_}) -> t_inf(M, K) =/= ?none end, ShdwPs) of
+ true -> ok;
+ false -> throw(none)
+ end.
+
+-spec promote_to_mand([erl_type()], t_map_dict()) -> t_map_dict().
+
+promote_to_mand(_, []) -> [];
+promote_to_mand(MKs, [E={K,_,V}|T]) ->
+ [case lists:any(fun(M) -> t_is_equal(K,M) end, MKs) of
+ true -> {K, ?mand, V};
+ false -> E
+ end|promote_to_mand(MKs, T)].
+
+-define(RECUR_EXPAND_LIMIT, 10).
+-define(RECUR_EXPAND_DEPTH, 2).
+
+%% If more of the limited resources is spent on the non-recursive
+%% forms, more warnings are found. And the analysis is also a bit
+%% faster.
+%%
+%% Setting REC_TYPE_LIMIT to 1 would work also work well.
+
+recur_limit(Fun, D, L, _, _) when L =< ?RECUR_EXPAND_DEPTH,
+ D =< ?RECUR_EXPAND_LIMIT ->
+ Fun(D, L);
+recur_limit(Fun, D, L, TypeName, TypeNames) ->
+ case is_recursive(TypeName, TypeNames) of
+ true ->
+ {T, L1, C1} = Fun(?RECUR_EXPAND_DEPTH, ?RECUR_EXPAND_LIMIT),
+ {T, L - L1, C1};
+ false ->
+ Fun(D, L)
+ end.
+
+-spec t_check_record_fields(parse_form(), sets:set(mfa()), site(),
+ mod_records(), var_table(), cache()) -> cache().
+
+t_check_record_fields(Form, ExpTypes, Site, RecDict, VarTable, Cache) ->
+ State = #from_form{site = Site,
+ xtypes = ExpTypes,
+ mrecs = RecDict,
+ vtab = VarTable,
+ tnames = []},
+ check_record_fields(Form, State, Cache).
+
+-spec check_record_fields(parse_form(), #from_form{}, cache()) -> cache().
+
+%% If there is something wrong with parse_form()
+%% throw({error, io_lib:chars()} is called.
+
+check_record_fields({var, _L, _}, _S, C) -> C;
+check_record_fields({ann_type, _L, [_Var, Type]}, S, C) ->
+ check_record_fields(Type, S, C);
+check_record_fields({paren_type, _L, [Type]}, S, C) ->
+ check_record_fields(Type, S, C);
+check_record_fields({remote_type, _L, [{atom, _, _}, {atom, _, _}, Args]},
+ S, C) ->
+ list_check_record_fields(Args, S, C);
+check_record_fields({atom, _L, _}, _S, C) -> C;
+check_record_fields({integer, _L, _}, _S, C) -> C;
+check_record_fields({op, _L, _Op, _Arg}, _S, C) -> C;
+check_record_fields({op, _L, _Op, _Arg1, _Arg2}, _S, C) -> C;
+check_record_fields({type, _L, tuple, any}, _S, C) -> C;
+check_record_fields({type, _L, map, any}, _S, C) -> C;
+check_record_fields({type, _L, binary, [_Base, _Unit]}, _S, C) -> C;
+check_record_fields({type, _L, 'fun', [{type, _, any}, Range]}, S, C) ->
+ check_record_fields(Range, S, C);
+check_record_fields({type, _L, range, [_From, _To]}, _S, C) -> C;
+check_record_fields({type, _L, record, [Name|Fields]}, S, C) ->
+ check_record(Name, Fields, S, C);
+check_record_fields({type, _L, _, Args}, S, C) ->
+ list_check_record_fields(Args, S, C);
+check_record_fields({user_type, _L, _Name, Args}, S, C) ->
+ list_check_record_fields(Args, S, C).
+
+check_record({atom, _, Name}, ModFields, S, C) ->
+ #from_form{site = Site, mrecs = MR} = S,
+ M = site_module(Site),
+ {ok, R} = dict:find(M, MR),
+ {ok, DeclFields} = lookup_record(Name, R),
+ case check_fields(Name, ModFields, DeclFields, S, C) of
+ {error, FieldName} ->
+ throw({error, io_lib:format("Illegal declaration of #~w{~w}\n",
+ [Name, FieldName])});
+ C1 -> C1
+ end.
+
+check_fields(RecName, [{type, _, field_type, [{atom, _, Name}, Abstr]}|Left],
+ DeclFields, S, C) ->
+ #from_form{site = Site0, xtypes = ET, mrecs = MR, vtab = V} = S,
+ M = site_module(Site0),
+ Site = {record, {M, RecName, length(DeclFields)}},
+ {Type, C1} = t_from_form(Abstr, ET, Site, MR, V, C),
+ {Name, _, DeclType} = lists:keyfind(Name, 1, DeclFields),
+ TypeNoVars = subst_all_vars_to_any(Type),
+ case t_is_subtype(TypeNoVars, DeclType) of
+ false -> {error, Name};
+ true -> check_fields(RecName, Left, DeclFields, S, C1)
+ end;
+check_fields(_RecName, [], _Decl, _S, C) ->
+ C.
+
+list_check_record_fields([], _S, C) ->
+ C;
+list_check_record_fields([H|Tail], S, C) ->
+ C1 = check_record_fields(H, S, C),
+ list_check_record_fields(Tail, S, C1).
+
+site_module({_, {Module, _, _}}) ->
+ Module.
+
+-spec cache__new() -> cache().
+
+cache__new() ->
+ maps:new().
+
+-spec cache_key(module(), atom(), [erl_type()],
+ type_names(), expand_depth()) -> cache_key().
+
+%% If TypeNames is left out from the key, the cache is smaller, and
+%% the form-to-type translation is faster. But it would be a shame if,
+%% for example, any() is used, where a more complex type should be
+%% used. There is also a slight risk of creating unnecessarily big
+%% types.
+
+cache_key(Module, Name, ArgTypes, TypeNames, D) ->
+ {Module, Name, D, ArgTypes, TypeNames}.
+
+-spec cache_find(cache_key(), cache()) ->
+ {erl_type(), expand_limit()} | 'error'.
+
+cache_find(Key, Cache) ->
+ case maps:find(Key, Cache) of
+ {ok, Value} ->
+ Value;
+ error ->
+ error
+ end.
+
+-spec cache_put(cache_key(), erl_type(), expand_limit(), cache()) -> cache().
+
+cache_put(_Key, _Type, DeltaL, Cache) when DeltaL < 0 ->
+ %% The type is truncated; do not reuse it.
+ Cache;
+cache_put(Key, Type, DeltaL, Cache) ->
+ maps:put(Key, {Type, DeltaL}, Cache).
+
+-spec t_var_names([erl_type()]) -> [atom()].
+
+t_var_names([{var, _, Name}|L]) when L =/= '_' ->
+ [Name|t_var_names(L)];
+t_var_names([]) ->
+ [].
-spec t_form_to_string(parse_form()) -> string().
@@ -4592,8 +5200,13 @@ t_form_to_string({type, _L, iodata, []}) -> "iodata()";
t_form_to_string({type, _L, iolist, []}) -> "iolist()";
t_form_to_string({type, _L, list, [Type]}) ->
"[" ++ t_form_to_string(Type) ++ "]";
-t_form_to_string({type, _L, map, Args}) when not is_list(Args) ->
- "#{}";
+t_form_to_string({type, _L, map, any}) -> "map()";
+t_form_to_string({type, _L, map, Args}) ->
+ "#{" ++ string:join(t_form_to_string_list(Args), ",") ++ "}";
+t_form_to_string({type, _L, map_field_assoc, [Key, Val]}) ->
+ t_form_to_string(Key) ++ "=>" ++ t_form_to_string(Val);
+t_form_to_string({type, _L, map_field_exact, [Key, Val]}) ->
+ t_form_to_string(Key) ++ ":=" ++ t_form_to_string(Val);
t_form_to_string({type, _L, mfa, []}) -> "mfa()";
t_form_to_string({type, _L, module, []}) -> "module()";
t_form_to_string({type, _L, node, []}) -> "node()";
@@ -4623,12 +5236,28 @@ t_form_to_string({type, _L, tuple, Args}) ->
t_form_to_string({type, _L, union, Args}) ->
string:join(t_form_to_string_list(Args), " | ");
t_form_to_string({type, _L, Name, []} = T) ->
- try t_to_string(t_from_form(T))
+ try
+ M = mod,
+ D0 = dict:new(),
+ MR = dict:from_list([{M, D0}]),
+ Site = {type, {M,Name,0}},
+ V = var_table__new(),
+ C = cache__new(),
+ State = #from_form{site = Site,
+ xtypes = sets:new(),
+ mrecs = MR,
+ vtab = V,
+ tnames = []},
+ {T1, _, _} = from_form(T, State, _Deep=1000, _ALot=1000000, C),
+ t_to_string(T1)
catch throw:{error, _} -> atom_to_string(Name) ++ "()"
end;
-t_form_to_string({type, _L, Name, List}) ->
+t_form_to_string({user_type, _L, Name, List}) ->
flat_format("~w(~s)",
- [Name, string:join(t_form_to_string_list(List), ",")]).
+ [Name, string:join(t_form_to_string_list(List), ",")]);
+t_form_to_string({type, L, Name, List}) ->
+ %% Compatibility: modules compiled before Erlang/OTP 18.0.
+ t_form_to_string({user_type, L, Name, List}).
t_form_to_string_list(List) ->
t_form_to_string_list(List, []).
@@ -4671,13 +5300,13 @@ is_erl_type(#c{}) -> true;
is_erl_type(_) -> false.
-spec lookup_record(atom(), type_table()) ->
- 'error' | {'ok', [{atom(), parse_form() | erl_type()}]}.
+ 'error' | {'ok', [{atom(), parse_form(), erl_type()}]}.
lookup_record(Tag, RecDict) when is_atom(Tag) ->
case dict:find({record, Tag}, RecDict) of
- {ok, [{_Arity, Fields}]} ->
+ {ok, {_FileLine, [{_Arity, Fields}]}} ->
{ok, Fields};
- {ok, List} when is_list(List) ->
+ {ok, {_FileLine, List}} when is_list(List) ->
%% This will have to do, since we do not know which record we
%% are looking for.
error;
@@ -4686,15 +5315,16 @@ lookup_record(Tag, RecDict) when is_atom(Tag) ->
end.
-spec lookup_record(atom(), arity(), type_table()) ->
- 'error' | {'ok', [{atom(), erl_type()}]}.
+ 'error' | {'ok', [{atom(), parse_form(), erl_type()}]}.
lookup_record(Tag, Arity, RecDict) when is_atom(Tag) ->
case dict:find({record, Tag}, RecDict) of
- {ok, [{Arity, Fields}]} -> {ok, Fields};
- {ok, OrdDict} -> orddict:find(Arity, OrdDict);
+ {ok, {_FileLine, [{Arity, Fields}]}} -> {ok, Fields};
+ {ok, {_FileLine, OrdDict}} -> orddict:find(Arity, OrdDict);
error -> error
end.
+-spec lookup_type(_, _, _) -> {'type' | 'opaque', type_value()} | 'error'.
lookup_type(Name, Arity, RecDict) ->
case dict:find({type, Name, Arity}, RecDict) of
error ->
@@ -4711,6 +5341,12 @@ lookup_type(Name, Arity, RecDict) ->
type_is_defined(TypeOrOpaque, Name, Arity, RecDict) ->
dict:is_key({TypeOrOpaque, Name, Arity}, RecDict).
+cannot_have_opaque(Type, TypeName, TypeNames) ->
+ t_is_none(Type) orelse is_recursive(TypeName, TypeNames).
+
+is_recursive(TypeName, TypeNames) ->
+ lists:member(TypeName, TypeNames).
+
can_unfold_more(TypeName, TypeNames) ->
Fun = fun(E, Acc) -> case E of TypeName -> Acc + 1; _ -> Acc end end,
lists:foldl(Fun, 0, TypeNames) < ?REC_TYPE_LIMIT.
@@ -4725,48 +5361,83 @@ do_opaque(?opaque(_) = Type, Opaques, Pred) ->
false -> Pred(Type)
end;
do_opaque(?union(List) = Type, Opaques, Pred) ->
- [A,B,F,I,L,N,T,M,O,R,Map] = List,
+ [A,B,F,I,L,N,T,M,O,Map] = List,
if O =:= ?none -> Pred(Type);
true ->
case Opaques =:= 'universe' orelse is_opaque_type(O, Opaques) of
true ->
S = t_opaque_structure(O),
- do_opaque(t_sup([A,B,F,I,L,N,T,M,S,R,Map]), Opaques, Pred);
+ do_opaque(t_sup([A,B,F,I,L,N,T,M,S,Map]), Opaques, Pred);
false -> Pred(Type)
end
end;
do_opaque(Type, _Opaques, Pred) ->
Pred(Type).
-is_same_type_name(ModNameArgs, ModNameArgs) -> true;
-is_same_type_name({Mod, Name, Args1}, {Mod, Name, Args2}) ->
- all_any(Args1) orelse all_any(Args2);
-is_same_type_name({Mod1, Name1, Args1}, {Mod2, Name2, Args2}) ->
- is_same_type_name2(Mod1, Name1, Args1, Mod2, Name2, Args2).
-
-all_any([]) -> true;
-all_any([T|L]) ->
- t_is_any(T) andalso all_any(L);
-all_any(_) -> false.
-
-%% Compatibility. In Erlang/OTP 17 the pre-defined opaque types
-%% digraph() and so on can be used, but there are also new types such
-%% as digraph:graph() with the exact same meaning. In Erlang/OTP R18.0
-%% all but the last clause can be removed.
-
-is_same_type_name2(digraph, digraph, [], digraph, graph, []) -> true;
-is_same_type_name2(digraph, graph, [], digraph, digraph, []) -> true;
-is_same_type_name2(gb_sets, gb_set, [], gb_sets, set, [_]) -> true;
-is_same_type_name2(gb_sets, set, [_], gb_sets, gb_set, []) -> true;
-is_same_type_name2(gb_trees, gb_tree, [], gb_trees, tree, [_, _]) -> true;
-is_same_type_name2(gb_trees, tree, [_, _], gb_trees, gb_tree, []) -> true;
-is_same_type_name2(_, _, _, _, _, _) -> false.
-
-map_keys(?map(Pairs)) ->
- [K || {K, _} <- Pairs].
-
-map_values(?map(Pairs)) ->
- [V || {_, V} <- Pairs].
+map_all_values(?map(Pairs,_,DefV)) ->
+ [DefV|[V || {V, _, _} <- Pairs]].
+
+map_all_keys(?map(Pairs,DefK,_)) ->
+ [DefK|[K || {_, _, K} <- Pairs]].
+
+map_all_types(M) ->
+ map_all_keys(M) ++ map_all_values(M).
+
+%% Tests if a type has exactly one possible value.
+-spec t_is_singleton(erl_type()) -> boolean().
+
+t_is_singleton(Type) ->
+ t_is_singleton(Type, 'universe').
+
+-spec t_is_singleton(erl_type(), opaques()) -> boolean().
+
+t_is_singleton(Type, Opaques) ->
+ do_opaque(Type, Opaques, fun is_singleton_type/1).
+
+%% Incomplete; not all representable singleton types are included.
+is_singleton_type(?nil) -> true;
+is_singleton_type(?atom(?any)) -> false;
+is_singleton_type(?atom(Set)) ->
+ ordsets:size(Set) =:= 1;
+is_singleton_type(?int_range(V, V)) -> true;
+is_singleton_type(?int_set(Set)) ->
+ ordsets:size(Set) =:= 1;
+is_singleton_type(?tuple(Types, Arity, _)) when is_integer(Arity) ->
+ lists:all(fun is_singleton_type/1, Types);
+is_singleton_type(?tuple_set([{Arity, [OnlyTuple]}])) when is_integer(Arity) ->
+ is_singleton_type(OnlyTuple);
+is_singleton_type(?map(Pairs, ?none, ?none)) ->
+ lists:all(fun({_,MNess,V}) -> MNess =:= ?mand andalso is_singleton_type(V)
+ end, Pairs);
+is_singleton_type(_) ->
+ false.
+
+%% Returns the only possible value of a singleton type.
+-spec t_singleton_to_term(erl_type(), opaques()) -> term().
+
+t_singleton_to_term(Type, Opaques) ->
+ do_opaque(Type, Opaques, fun singleton_type_to_term/1).
+
+singleton_type_to_term(?nil) -> [];
+singleton_type_to_term(?atom(Set)) when Set =/= ?any ->
+ case ordsets:size(Set) of
+ 1 -> hd(ordsets:to_list(Set));
+ _ -> error(badarg)
+ end;
+singleton_type_to_term(?int_range(V, V)) -> V;
+singleton_type_to_term(?int_set(Set)) ->
+ case ordsets:size(Set) of
+ 1 -> hd(ordsets:to_list(Set));
+ _ -> error(badarg)
+ end;
+singleton_type_to_term(?tuple(Types, Arity, _)) when is_integer(Arity) ->
+ lists:map(fun singleton_type_to_term/1, Types);
+singleton_type_to_term(?tuple_set([{Arity, [OnlyTuple]}]))
+ when is_integer(Arity) ->
+ singleton_type_to_term(OnlyTuple);
+singleton_type_to_term(?map(Pairs, ?none, ?none)) ->
+ maps:from_list([{singleton_type_to_term(K), singleton_type_to_term(V)}
+ || {K,?mand,V} <- Pairs]).
%% -----------------------------------
%% Set
@@ -4789,10 +5460,6 @@ set_union(S1, S2) ->
_ -> ?any
end.
-set_union_no_limit(?any, _) -> ?any;
-set_union_no_limit(_, ?any) -> ?any;
-set_union_no_limit(S1, S2) -> ordsets:union(S1, S2).
-
%% The intersection and subtraction can return ?none.
%% This should always be handled right away since ?none is not a valid set.
%% However, ?any is considered a valid set.
@@ -4906,6 +5573,17 @@ family(L) ->
sofs:to_external(F).
%%=============================================================================
+%%
+%% Interface functions for abstract data types defined in this module
+%%
+%%=============================================================================
+
+-spec var_table__new() -> var_table().
+
+var_table__new() ->
+ maps:new().
+
+%%=============================================================================
%% Consistency-testing function(s) below
%%=============================================================================
diff --git a/lib/hipe/doc/Makefile b/lib/hipe/doc/Makefile
index 4ea0137202..1015ca78eb 100644
--- a/lib/hipe/doc/Makefile
+++ b/lib/hipe/doc/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2012. All Rights Reserved.
+# Copyright Ericsson AB 2006-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
diff --git a/lib/hipe/doc/src/Makefile b/lib/hipe/doc/src/Makefile
index fbfd4ca327..a5edb80381 100644
--- a/lib/hipe/doc/src/Makefile
+++ b/lib/hipe/doc/src/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2012. All Rights Reserved.
+# Copyright Ericsson AB 2006-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
diff --git a/lib/hipe/doc/src/book.xml b/lib/hipe/doc/src/book.xml
index 438be134a2..7c594f12ad 100644
--- a/lib/hipe/doc/src/book.xml
+++ b/lib/hipe/doc/src/book.xml
@@ -4,20 +4,21 @@
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>2006</year><year>2013</year>
+ <year>2006</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
</legalnotice>
diff --git a/lib/hipe/doc/src/hipe_app.xml b/lib/hipe/doc/src/hipe_app.xml
index 2ddce664cc..e489d155c3 100644
--- a/lib/hipe/doc/src/hipe_app.xml
+++ b/lib/hipe/doc/src/hipe_app.xml
@@ -4,20 +4,21 @@
<appref>
<header>
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
</legalnotice>
@@ -36,15 +37,14 @@
<description>
<p>
The normal way to native-compile an Erlang module using HiPE is to include the atom native
- in the Erlang compiler options, as in:
- <code>
- 1> <input>c(my_module, [native]).</input></code>
- Options to the HiPE compiler are then passed as follows:
- <code>
- 1> <input>c(my_module, [native,{hipe,Options}]).</input></code>
- For on-line help in the Erlang shell, call <c>hipe:help()</c>.
- Details on HiPE compiler options are given by <c>hipe:help_options()</c>.
- </p>
+ in the Erlang compiler options, as in:</p>
+ <pre>
+ 1> <input>c(my_module, [native]).</input></pre>
+ <p>Options to the HiPE compiler are then passed as follows:</p>
+ <pre>
+ 1> <input>c(my_module, [native,{hipe,Options}]).</input></pre>
+ <p>For on-line help in the Erlang shell, call <c>hipe:help()</c>.
+ Details on HiPE compiler options are given by <c>hipe:help_options()</c>.</p>
</description>
<section>
<title>SEE ALSO</title>
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index 8d3358533b..e2a1524be6 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -4,20 +4,21 @@
<chapter>
<header>
<copyright>
- <year>2006</year><year>2013</year>
+ <year>2006</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
</legalnotice>
@@ -30,6 +31,247 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.15.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ HiPE compiler crashed, during compilation, in some cases
+ that involved inlining of float operations on complicated
+ control flow graphs.</p>
+ <p>
+ Own Id: OTP-13407 Aux Id: PR-984 </p>
+ </item>
+ <item>
+ <p>
+ Various fixes and improvements to the HiPE LLVM backend.
+ <list> <item>Add support for LLVM 3.7 and 3.8 in the
+ HiPE/LLVM x86_64 backend</item> <item>Reinstate support
+ for the LLVM backend on x86 (works OK for LLVM 3.5 to 3.7
+ -- LLVM 3.8 has a bug that prevents it from generating
+ correct native code on x86)</item> </list></p>
+ <p>
+ Own Id: OTP-13626</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Elimination of <c>maps:is_key/2</c> calls to HiPE</p>
+ <p>
+ Own Id: OTP-13625 Aux Id: PR-1069 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.15</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix pretty printing of Core Maps</p>
+ <p>
+ Literal maps could cause Dialyzer to crash when pretty
+ printing the results.</p>
+ <p>
+ Own Id: OTP-13238</p>
+ </item>
+ <item>
+ <p>
+ Dialyzer warnings removed.</p>
+ <p>
+ Own Id: OTP-13379</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Fix HiPE ErLLVM code generation for pattern matching with
+ UTF binaries.</p>
+ <p>
+ Own Id: OTP-13269</p>
+ </item>
+ <item>
+ <p>
+ Fix various binary construction inconsistencies for hipe
+ compiled code. <list> <item>Passing bad field sizes to
+ binary constructions would throw <c>badarith</c> rather
+ than <c>badarg</c>. Worse, in guards, when the unit size
+ of the field was 1, the exception would leak rather than
+ failing the function clause match.</item> <item>Passing
+ bignums as field sizes to binary constructions would
+ always fail (and always with <c>badarg</c>).</item>
+ <item>A bug in bs_init_bits that cased binary
+ constructions to fail with system_limit if they were at
+ least 1/8th of the actual limit.</item> <item>Compiler
+ crashes when matches against an integer literal whose
+ size fits an unsigned word, but not a signed word or
+ matches against an integer literal that whose size is
+ larger than the largest allowed bignum.</item> <item>Very
+ large binary constructions that should fail with
+ system_limit could instead fail with <c>badarg</c> or
+ even succeed with a faulty result.</item> <item>Add
+ missing check for unit size match when inserting a
+ binary. For example, a faulty expression like
+ <c>&lt;&lt;&lt;&lt;1:7&gt;&gt;/binary&gt;&gt;</c> would
+ succeed.</item> </list></p>
+ <p>
+ Own Id: OTP-13272</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.14</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix hipe bug causing segfaults when native code
+ constructs binaries starting with a zero-length integer
+ field.</p>
+ <p>
+ Own Id: OTP-13048</p>
+ </item>
+ <item>
+ <p>
+ Reintroduce the <c>erlang:make_fun/3</c> BIF in
+ erl_bif_types.</p>
+ <p>
+ Own Id: OTP-13068</p>
+ </item>
+ <item>
+ <p>
+ In certain cases of matching with very big binaries, the
+ HiPE compiler generated code that would fail the match,
+ even in cases that the matching was successful. The
+ problem was more quite noticeable on 32-bit platforms.</p>
+ <p>
+ Own Id: OTP-13092</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ mikpe/hipe_x86_signal-musl-support</p>
+ <p>
+ Own Id: OTP-13159</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.13</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix bugs concerning <c>erlang:abs/1</c>. </p>
+ <p>
+ Own Id: OTP-12948</p>
+ </item>
+ <item>
+ <p> Fix a bug concerning <c>lists:keydelete/3</c> with
+ union and opaque types. </p>
+ <p>
+ Own Id: OTP-12949</p>
+ </item>
+ <item>
+ <p>
+ A beam file compiled by hipe for an incompatible runtime
+ system was sometimes not rejected by the loader, which
+ could lead to vm crash. This fix will also allow the same
+ hipe compiler to be used by both normal and debug-built
+ vm.</p>
+ <p>
+ Own Id: OTP-12962</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ New function <c>hipe:erts_checksum/0</c> which returns a
+ value identifying the target runtime system for the
+ compiler. Used by dialyzer for its beam cache directory.</p>
+ <p>
+ Own Id: OTP-12963 Aux Id: OTP-12962, OTP-12964 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.12</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a minor bug in the handling of opaque types. </p>
+ <p>
+ Own Id: OTP-12666</p>
+ </item>
+ <item>
+ <p>
+ Fix hipe bug when matching a "writable" binary. The bug
+ has been seen to sometimes cause a failed binary matching
+ of a correct utf8 character, but other symptoms are also
+ possible.</p>
+ <p>
+ Own Id: OTP-12667</p>
+ </item>
+ <item>
+ <p>
+ Optimizations and code cleanup in hipe code loader.</p>
+ <p>
+ Own Id: OTP-12816</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Improved error handling when memory allocation for HiPE
+ code fails.</p>
+ <p>
+ Own Id: OTP-12448</p>
+ </item>
+ <item>
+ <p>
+ Allow use of complete interface of cerl_pmatch module</p>
+ <p>
+ Own Id: OTP-12794</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.11.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -226,22 +468,28 @@
<p>
EEP43: New data type - Maps</p>
<p>
- With Maps you may for instance: <taglist> <item><c>M0 =
- #{ a =&gt; 1, b =&gt; 2}, % create
- associations</c></item> <item><c>M1 = M0#{ a := 10 }, %
- update values</c></item> <item><c>M2 = M1#{ "hi" =&gt;
- "hello"}, % add new associations</c></item> <item><c>#{
- "hi" := V1, a := V2, b := V3} = M2. % match keys with
- values</c></item> </taglist></p>
+ With Maps you may for instance:</p>
+ <taglist>
+ <tag/> <item><c>M0 = #{ a =&gt; 1, b =&gt; 2}, % create
+ associations</c></item>
+ <tag/><item><c>M1 = M0#{ a := 10 }, % update values</c></item>
+ <tag/><item><c>M2 = M1#{ "hi" =&gt;
+ "hello"}, % add new associations</c></item>
+ <tag/><item><c>#{ "hi" := V1, a := V2, b := V3} = M2.
+ % match keys with values</c></item>
+ </taglist>
<p>
For information on how to use Maps please see Map Expressions in the
<seealso marker="doc/reference_manual:expressions#map_expressions">
Reference Manual</seealso>.</p>
<p>
The current implementation is without the following
- features: <taglist> <item>No variable keys</item>
- <item>No single value access</item> <item>No map
- comprehensions</item> </taglist></p>
+ features:</p>
+ <taglist>
+ <tag/><item>No variable keys</item>
+ <tag/><item>No single value access</item>
+ <tag/><item>No map comprehensions</item>
+ </taglist>
<p>
Note that Maps is <em>experimental</em> during OTP 17.0.</p>
<p>
@@ -509,19 +757,17 @@
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
- <p>
<list> <item><p>No warnings for underspecs with remote
types</p></item> <item><p> Fix crash in Typer</p></item>
<item><p>Fix Dialyzer's warning for its own
code</p></item> <item><p>Fix Dialyzer's warnings in
HiPE</p></item> <item><p>Add file/line info in a
particular Dialyzer crash</p></item> <item><p>Update
- inets test results</p></item> </list></p>
+ inets test results</p></item> </list>
<p>
Own Id: OTP-9758</p>
</item>
<item>
- <p>
<list> <item><p>Correct callback spec in application
module</p></item> <item><p>Refine warning about callback
specs with extra ranges</p></item> <item><p>Cleanup
@@ -532,7 +778,7 @@
analysis</p></item> <item><p>Fix crash in
Dialyzer</p></item> <item><p>Variable substitution was
not generalizing any unknown variables.</p></item>
- </list></p>
+ </list>
<p>
Own Id: OTP-9776</p>
</item>
diff --git a/lib/hipe/doc/src/part_notes.xml b/lib/hipe/doc/src/part_notes.xml
index f912fcfcdb..828c304fb5 100644
--- a/lib/hipe/doc/src/part_notes.xml
+++ b/lib/hipe/doc/src/part_notes.xml
@@ -4,20 +4,21 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2006</year><year>2013</year>
+ <year>2006</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
</legalnotice>
diff --git a/lib/hipe/doc/src/ref_man.xml b/lib/hipe/doc/src/ref_man.xml
index 0e1288b4c4..7938729227 100644
--- a/lib/hipe/doc/src/ref_man.xml
+++ b/lib/hipe/doc/src/ref_man.xml
@@ -4,20 +4,21 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
</legalnotice>
diff --git a/lib/hipe/flow/Makefile b/lib/hipe/flow/Makefile
index 75e156b542..d883eecf36 100644
--- a/lib/hipe/flow/Makefile
+++ b/lib/hipe/flow/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -65,7 +66,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec # +warn_untyped_record
+ERL_COMPILE_FLAGS += -Werror +warn_export_vars +warn_missing_spec +warn_untyped_record
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/flow/cfg.hrl b/lib/hipe/flow/cfg.hrl
index 1f7a162f27..2575b9e38a 100644
--- a/lib/hipe/flow/cfg.hrl
+++ b/lib/hipe/flow/cfg.hrl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -33,11 +34,13 @@
%%
-record(cfg_info, {'fun' :: mfa(),
start_label :: cfg_lbl(),
+ %% TODO: merge is_closure and closure_arity into one field
is_closure :: boolean(),
- closure_arity :: arity(),
+ closure_arity = none :: 'none' | arity(),
is_leaf :: boolean(),
- params, % :: list()
- info = []}). %% this field seems not needed; take out??
+ params :: list(), %% XXX: refine
+ info = [] :: list()}). %% seems not needed; take out??
+-type cfg_info() :: #cfg_info{}.
%%
%% Data is a triple with a dict of constants, a list of labels and an integer
@@ -48,6 +51,6 @@
%% The following is to be used by other modules
%%
-record(cfg, {table = gb_trees:empty() :: gb_trees:tree(),
- info :: #cfg_info{},
+ info :: cfg_info(),
data :: cfg_data()}).
-type cfg() :: #cfg{}.
diff --git a/lib/hipe/flow/cfg.inc b/lib/hipe/flow/cfg.inc
index f0b1a75737..0bad2a8dd7 100644
--- a/lib/hipe/flow/cfg.inc
+++ b/lib/hipe/flow/cfg.inc
@@ -4,18 +4,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/flow/ebb.inc b/lib/hipe/flow/ebb.inc
index 42d7ff3793..529be72dc8 100644
--- a/lib/hipe/flow/ebb.inc
+++ b/lib/hipe/flow/ebb.inc
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/flow/hipe_bb.erl b/lib/hipe/flow/hipe_bb.erl
index 16730f1dce..2da3a6dc99 100644
--- a/lib/hipe/flow/hipe_bb.erl
+++ b/lib/hipe/flow/hipe_bb.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/flow/hipe_bb.hrl b/lib/hipe/flow/hipe_bb.hrl
index f4d426dad1..cd4d788aef 100644
--- a/lib/hipe/flow/hipe_bb.hrl
+++ b/lib/hipe/flow/hipe_bb.hrl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/flow/hipe_dominators.erl b/lib/hipe/flow/hipe_dominators.erl
index 50d45c7c72..72c16b5688 100644
--- a/lib/hipe/flow/hipe_dominators.erl
+++ b/lib/hipe/flow/hipe_dominators.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -58,7 +59,7 @@
-record(domTree, {root :: cfg_lbl(),
size = 0 :: non_neg_integer(),
nodes = gb_trees:empty() :: gb_trees:tree()}).
--type domTree() :: #domTree{}.
+-opaque domTree() :: #domTree{}.
%%>----------------------------------------------------------------------<
%% Procedure : domTree_create/1
diff --git a/lib/hipe/flow/hipe_gen_cfg.erl b/lib/hipe/flow/hipe_gen_cfg.erl
index f9fb1f70c8..a6d053f505 100644
--- a/lib/hipe/flow/hipe_gen_cfg.erl
+++ b/lib/hipe/flow/hipe_gen_cfg.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/flow/liveness.inc b/lib/hipe/flow/liveness.inc
index 6f161fb269..a1caa3e0ad 100644
--- a/lib/hipe/flow/liveness.inc
+++ b/lib/hipe/flow/liveness.inc
@@ -3,18 +3,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/Makefile b/lib/hipe/icode/Makefile
index 87015aa51c..b220bc16a0 100644
--- a/lib/hipe/icode/Makefile
+++ b/lib/hipe/icode/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2013. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -58,7 +59,7 @@ DOC_MODULES = hipe_beam_to_icode \
hipe_icode_pp hipe_icode_primops \
hipe_icode_range \
hipe_icode_split_arith \
- hipe_icode_ssa hipe_icode_ssa_const_prop \
+ hipe_icode_ssa hipe_icode_ssa_const_prop hipe_icode_call_elim \
hipe_icode_ssa_copy_prop hipe_icode_ssa_struct_reuse \
hipe_icode_type $(HIPE_MODULES)
@@ -83,7 +84,7 @@ DOC_FILES= $(DOC_MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_unused_import +warn_exported_vars +warn_missing_spec # +warn_untyped_record
+ERL_COMPILE_FLAGS += -Werror +warn_unused_import +warn_export_vars +warn_missing_spec # +warn_untyped_record
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index 4691662f9f..224aacd8d7 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -880,6 +881,15 @@ trans_fun([{bs_init_bits,{f,Lbl},Size,_Words,_LiveRegs,{field_flags,Flags0},X}|
trans_fun([{bs_add, {f,Lbl}, [Old,New,Unit], Res}|Instructions], Env) ->
Dst = mk_var(Res),
Temp = mk_var(new),
+ {FailLblName, FailCode} =
+ if Lbl =:= 0 ->
+ FailLbl = mk_label(new),
+ {hipe_icode:label_name(FailLbl),
+ [FailLbl,
+ hipe_icode:mk_fail([hipe_icode:mk_const(badarg)], error)]};
+ true ->
+ {map_label(Lbl), []}
+ end,
MultIs =
case {New,Unit} of
{{integer, NewInt}, _} ->
@@ -889,40 +899,26 @@ trans_fun([{bs_add, {f,Lbl}, [Old,New,Unit], Res}|Instructions], Env) ->
[hipe_icode:mk_move(Temp, NewVar)];
_ ->
NewVar = mk_var(New),
- if Lbl =:= 0 ->
- [hipe_icode:mk_primop([Temp], '*',
- [NewVar, hipe_icode:mk_const(Unit)])];
- true ->
- Succ = mk_label(new),
- [hipe_icode:mk_primop([Temp], '*',
- [NewVar, hipe_icode:mk_const(Unit)],
- hipe_icode:label_name(Succ), map_label(Lbl)),
- Succ]
- end
+ Succ = mk_label(new),
+ [hipe_icode:mk_primop([Temp], '*',
+ [NewVar, hipe_icode:mk_const(Unit)],
+ hipe_icode:label_name(Succ), FailLblName),
+ Succ]
end,
Succ2 = mk_label(new),
- {FailLblName, FailCode} =
- if Lbl =:= 0 ->
- FailLbl = mk_label(new),
- {hipe_icode:label_name(FailLbl),
- [FailLbl,
- hipe_icode:mk_fail([hipe_icode:mk_const(badarg)], error)]};
- true ->
- {map_label(Lbl), []}
- end,
IsPos =
[hipe_icode:mk_if('>=', [Temp, hipe_icode:mk_const(0)],
hipe_icode:label_name(Succ2), FailLblName)] ++
- FailCode ++ [Succ2],
- AddI =
+ FailCode ++ [Succ2],
+ AddRhs =
case Old of
- {integer,OldInt} ->
- hipe_icode:mk_primop([Dst], '+', [Temp, hipe_icode:mk_const(OldInt)]);
- _ ->
- OldVar = mk_var(Old),
- hipe_icode:mk_primop([Dst], '+', [Temp, OldVar])
+ {integer,OldInt} -> hipe_icode:mk_const(OldInt);
+ _ -> mk_var(Old)
end,
- MultIs ++ IsPos ++ [AddI|trans_fun(Instructions, Env)];
+ Succ3 = mk_label(new),
+ AddI = hipe_icode:mk_primop([Dst], '+', [Temp, AddRhs],
+ hipe_icode:label_name(Succ3), FailLblName),
+ MultIs ++ IsPos ++ [AddI,Succ3|trans_fun(Instructions, Env)];
%%--------------------------------------------------------------------
%% Bit syntax instructions added in R12B-5 (Fall 2008)
%%--------------------------------------------------------------------
@@ -1305,7 +1301,7 @@ trans_bin([{bs_put_binary,{f,Lbl},Size,Unit,{field_flags,Flags},Source}|
{Name, Args, Env2} =
case Size of
{atom,all} -> %% put all bits
- {{bs_put_binary_all, Flags}, [Src,Base,Offset], Env};
+ {{bs_put_binary_all, Unit, Flags}, [Src,Base,Offset], Env};
{integer,NoBits} when is_integer(NoBits), NoBits >= 0 ->
%% Create a N*Unit bits subbinary
{{bs_put_binary, NoBits*Unit, Flags}, [Src,Base,Offset], Env};
@@ -1584,11 +1580,7 @@ gen_put_map_instrs(exists, Op, TempMapVar, Dst, FailLbl, Pairs, Env) ->
end,
{[IsMapCode, TrueLabel, PutInstructions, ReturnLbl], Env1};
gen_put_map_instrs(new, Op, TempMapVar, Dst, new, Pairs, Env) ->
- TrueLabel = mk_label(new),
FailLbl = mk_label(new),
- IsMapCode = hipe_icode:mk_type([TempMapVar], map,
- hipe_icode:label_name(TrueLabel),
- hipe_icode:label_name(FailLbl)),
DstMapVar = mk_var(Dst),
{ReturnLbl, PutInstructions, Env1}
= case Op of
@@ -1596,10 +1588,10 @@ gen_put_map_instrs(new, Op, TempMapVar, Dst, new, Pairs, Env) ->
trans_put_map_assoc(TempMapVar, DstMapVar, Pairs, Env, []);
exact ->
trans_put_map_exact(TempMapVar, DstMapVar,
- hipe_icode:label_name(FailLbl), Pairs, Env, [])
+ none, Pairs, Env, [])
end,
Fail = hipe_icode:mk_fail([hipe_icode:mk_const(badarg)], error),
- {[IsMapCode, TrueLabel, PutInstructions, FailLbl, Fail, ReturnLbl], Env1}.
+ {[PutInstructions, FailLbl, Fail, ReturnLbl], Env1}.
%%-----------------------------------------------------------------------
%% This function generates the instructions needed to insert several
@@ -1629,6 +1621,13 @@ trans_put_map_exact(MapVar, DestMapVar, _FLbl, [], Env, Acc) ->
ReturnLbl = mk_label(new),
GotoReturn = hipe_icode:mk_goto(hipe_icode:label_name(ReturnLbl)),
{ReturnLbl, lists:reverse([GotoReturn, MoveToReturnVar | Acc]), Env};
+trans_put_map_exact(MapVar, DestMapVar, none, [Key, Value | Rest], Env, Acc) ->
+ {MoveKey, KeyVar, Env1} = mk_move_and_var(Key, Env),
+ {MoveVal, ValVar, Env2} = mk_move_and_var(Value, Env1),
+ BifCallPut = hipe_icode:mk_call([MapVar], maps, update,
+ [KeyVar, ValVar, MapVar], remote),
+ Acc1 = [BifCallPut, MoveVal, MoveKey | Acc],
+ trans_put_map_exact(MapVar, DestMapVar, none, Rest, Env2, Acc1);
trans_put_map_exact(MapVar, DestMapVar, FLbl, [Key, Value | Rest], Env, Acc) ->
SuccLbl = mk_label(new),
{MoveKey, KeyVar, Env1} = mk_move_and_var(Key, Env),
diff --git a/lib/hipe/icode/hipe_icode.erl b/lib/hipe/icode/hipe_icode.erl
index 7b3d087e2d..78508dff22 100644
--- a/lib/hipe/icode/hipe_icode.erl
+++ b/lib/hipe/icode/hipe_icode.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -609,7 +610,9 @@
%% Exported types
%%
--export_type([icode/0]).
+-export_type([icode/0, params/0]).
+
+-type params() :: [icode_var()].
%%---------------------------------------------------------------------
%%
@@ -617,7 +620,7 @@
%%
%%---------------------------------------------------------------------
--spec mk_icode(mfa(), [icode_var()], boolean(), boolean(), [icode_instr()],
+-spec mk_icode(mfa(), params(), boolean(), boolean(), [icode_instr()],
{non_neg_integer(),non_neg_integer()},
{icode_lbl(),icode_lbl()}) -> icode().
mk_icode(Fun, Params, IsClosure, IsLeaf, Code, VarRange, LabelRange) ->
@@ -628,61 +631,61 @@ mk_icode(Fun, Params, IsClosure, IsLeaf, Code, VarRange, LabelRange) ->
var_range=VarRange,
label_range=LabelRange}.
--spec mk_icode(mfa(), [icode_var()], boolean(), boolean(), [icode_instr()],
+-spec mk_icode(mfa(), params(), boolean(), boolean(), [icode_instr()],
hipe_consttab(), {non_neg_integer(),non_neg_integer()},
- {icode_lbl(),icode_lbl()}) -> #icode{}.
+ {icode_lbl(),icode_lbl()}) -> icode().
mk_icode(Fun, Params, IsClosure, IsLeaf, Code, Data, VarRange, LabelRange) ->
#icode{'fun'=Fun, params=Params, code=Code,
data=Data, is_closure=IsClosure, is_leaf=IsLeaf,
var_range=VarRange, label_range=LabelRange}.
--spec icode_fun(#icode{}) -> mfa().
+-spec icode_fun(icode()) -> mfa().
icode_fun(#icode{'fun' = MFA}) -> MFA.
--spec icode_params(#icode{}) -> [icode_var()].
+-spec icode_params(icode()) -> params().
icode_params(#icode{params = Params}) -> Params.
--spec icode_params_update(#icode{}, [icode_var()]) -> #icode{}.
-icode_params_update(Icode, Params) ->
+-spec icode_params_update(icode(), params()) -> icode().
+icode_params_update(Icode, Params) ->
Icode#icode{params = Params}.
--spec icode_is_closure(#icode{}) -> boolean().
+-spec icode_is_closure(icode()) -> boolean().
icode_is_closure(#icode{is_closure = Closure}) -> Closure.
--spec icode_is_leaf(#icode{}) -> boolean().
+-spec icode_is_leaf(icode()) -> boolean().
icode_is_leaf(#icode{is_leaf = Leaf}) -> Leaf.
--spec icode_code(#icode{}) -> icode_instrs().
+-spec icode_code(icode()) -> icode_instrs().
icode_code(#icode{code = Code}) -> Code.
--spec icode_code_update(#icode{}, icode_instrs()) -> #icode{}.
+-spec icode_code_update(icode(), icode_instrs()) -> icode().
icode_code_update(Icode, NewCode) ->
Vmax = highest_var(NewCode),
Lmax = highest_label(NewCode),
Icode#icode{code = NewCode, var_range = {0,Vmax}, label_range = {0,Lmax}}.
--spec icode_data(#icode{}) -> hipe_consttab().
+-spec icode_data(icode()) -> hipe_consttab().
icode_data(#icode{data=Data}) -> Data.
-%% %% -spec icode_data_update(#icode{}, hipe_consttab()) -> #icode{}.
+%% %% -spec icode_data_update(icode(), hipe_consttab()) -> icode().
%% icode_data_update(Icode, NewData) -> Icode#icode{data=NewData}.
--spec icode_var_range(#icode{}) -> {non_neg_integer(), non_neg_integer()}.
+-spec icode_var_range(icode()) -> {non_neg_integer(), non_neg_integer()}.
icode_var_range(#icode{var_range = VarRange}) -> VarRange.
--spec icode_label_range(#icode{}) -> {non_neg_integer(), non_neg_integer()}.
+-spec icode_label_range(icode()) -> {non_neg_integer(), non_neg_integer()}.
icode_label_range(#icode{label_range = LabelRange}) -> LabelRange.
--spec icode_info(#icode{}) -> icode_info().
+-spec icode_info(icode()) -> icode_info().
icode_info(#icode{info = Info}) -> Info.
--spec icode_info_update(#icode{}, icode_info()) -> #icode{}.
+-spec icode_info_update(icode(), icode_info()) -> icode().
icode_info_update(Icode, Info) -> Icode#icode{info = Info}.
--spec icode_closure_arity(#icode{}) -> arity().
+-spec icode_closure_arity(icode()) -> arity().
icode_closure_arity(#icode{closure_arity = Arity}) -> Arity.
--spec icode_closure_arity_update(#icode{}, arity()) -> #icode{}.
+-spec icode_closure_arity_update(icode(), arity()) -> icode().
icode_closure_arity_update(Icode, Arity) -> Icode#icode{closure_arity = Arity}.
@@ -1375,12 +1378,12 @@ remove_constants(L) ->
%% Substitution: replace occurrences of X by Y if {X,Y} is in the
%% Subst_list.
--spec subst([{_,_}], I) -> I when is_subtype(I, icode_instr()).
+-spec subst([{_,_}], I) -> I when I :: icode_instr().
subst(Subst, I) ->
subst_defines(Subst, subst_uses(Subst, I)).
--spec subst_uses([{_,_}], I) -> I when is_subtype(I, icode_instr()).
+-spec subst_uses([{_,_}], I) -> I when I :: icode_instr().
subst_uses(Subst, I) ->
case I of
@@ -1404,7 +1407,7 @@ subst_uses(Subst, I) ->
#icode_label{} -> I
end.
--spec subst_defines([{_,_}], I) -> I when is_subtype(I, icode_instr()).
+-spec subst_defines([{_,_}], I) -> I when I :: icode_instr().
subst_defines(Subst, I) ->
case I of
@@ -1708,7 +1711,7 @@ mk_new_label() ->
%% @doc Removes comments from Icode.
%%
--spec strip_comments(#icode{}) -> #icode{}.
+-spec strip_comments(icode()) -> icode().
strip_comments(ICode) ->
icode_code_update(ICode, no_comments(icode_code(ICode))).
diff --git a/lib/hipe/icode/hipe_icode.hrl b/lib/hipe/icode/hipe_icode.hrl
index 46c04beb40..b2e0d86b28 100644
--- a/lib/hipe/icode/hipe_icode.hrl
+++ b/lib/hipe/icode/hipe_icode.hrl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -168,9 +169,10 @@
%%---------------------------------------------------------------------
-record(icode, {'fun' :: mfa(),
- params :: [icode_var()],
+ params :: hipe_icode:params(),
+ %% TODO: merge is_closure and closure_arity into one field
is_closure :: boolean(),
- closure_arity :: arity(),
+ closure_arity = none :: 'none' | arity(),
is_leaf :: boolean(),
code = [] :: icode_instrs(),
data :: hipe_consttab(),
diff --git a/lib/hipe/icode/hipe_icode_bincomp.erl b/lib/hipe/icode/hipe_icode_bincomp.erl
index 6f694f2bce..5a27519141 100644
--- a/lib/hipe/icode/hipe_icode_bincomp.erl
+++ b/lib/hipe/icode/hipe_icode_bincomp.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/icode/hipe_icode_call_elim.erl b/lib/hipe/icode/hipe_icode_call_elim.erl
new file mode 100644
index 0000000000..6a22133962
--- /dev/null
+++ b/lib/hipe/icode/hipe_icode_call_elim.erl
@@ -0,0 +1,78 @@
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2016. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%----------------------------------------------------------------------
+%% File : hipe_icode_call_elim.erl
+%% Authors : Daniel S. McCain <[email protected]>,
+%% Magnus LÃ¥ng <[email protected]>
+%% Created : 14 Apr 2014 by Magnus LÃ¥ng <[email protected]>
+%% Purpose : Eliminate calls to BIFs that are side-effect free only when
+%% executed on some argument types.
+%%----------------------------------------------------------------------
+-module(hipe_icode_call_elim).
+-export([cfg/1]).
+
+-include("hipe_icode.hrl").
+-include("../flow/cfg.hrl").
+
+-spec cfg(cfg()) -> cfg().
+
+cfg(IcodeSSA) ->
+ lists:foldl(fun (Lbl, CFG1) ->
+ BB1 = hipe_icode_cfg:bb(CFG1, Lbl),
+ Code1 = hipe_bb:code(BB1),
+ Code2 = lists:map(fun elim_insn/1, Code1),
+ BB2 = hipe_bb:code_update(BB1, Code2),
+ hipe_icode_cfg:bb_add(CFG1, Lbl, BB2)
+ end, IcodeSSA, hipe_icode_cfg:labels(IcodeSSA)).
+
+-spec elim_insn(icode_instr()) -> icode_instr().
+elim_insn(Insn=#icode_call{'fun'={_,_,_}=MFA, args=Args, type=remote,
+ dstlist=[Dst=#icode_variable{
+ annotation={type_anno, RetType, _}}]}) ->
+ Opaques = 'universe',
+ case erl_types:t_is_singleton(RetType, Opaques) of
+ true ->
+ ArgTypes = [case Arg of
+ #icode_variable{annotation={type_anno, Type, _}} -> Type;
+ #icode_const{} ->
+ erl_types:t_from_term(hipe_icode:const_value(Arg))
+ end || Arg <- Args],
+ case can_be_eliminated(MFA, ArgTypes) of
+ true ->
+ Const = hipe_icode:mk_const(
+ erl_types:t_singleton_to_term(RetType, Opaques)),
+ #icode_move{dst=Dst, src=Const};
+ false -> Insn
+ end;
+ false -> Insn
+ end;
+elim_insn(Insn) -> Insn.
+
+
+%% A function can be eliminated for some argument types if it has no side
+%% effects when run on arguments of those types.
+
+-spec can_be_eliminated(mfa(), [erl_types:erl_type()]) -> boolean().
+
+can_be_eliminated({maps, is_key, 2}, [_K, M]) ->
+ erl_types:t_is_map(M);
+can_be_eliminated(_, _) ->
+ false.
diff --git a/lib/hipe/icode/hipe_icode_callgraph.erl b/lib/hipe/icode/hipe_icode_callgraph.erl
index ccf97ecc17..12c2cd2b44 100644
--- a/lib/hipe/icode/hipe_icode_callgraph.erl
+++ b/lib/hipe/icode/hipe_icode_callgraph.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_cfg.erl b/lib/hipe/icode/hipe_icode_cfg.erl
index f6c2b0600b..9a602c0283 100644
--- a/lib/hipe/icode/hipe_icode_cfg.erl
+++ b/lib/hipe/icode/hipe_icode_cfg.erl
@@ -3,18 +3,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -54,6 +55,9 @@
-spec postorder(cfg()) -> [icode_lbl()].
-spec reverse_postorder(cfg()) -> [icode_lbl()].
+-spec params(cfg()) -> hipe_icode:params().
+-spec params_update(cfg(), hipe_icode:params()) -> cfg().
+
-spec is_visited(icode_lbl(), gb_sets:set()) -> boolean().
-spec visit(icode_lbl(), gb_sets:set()) -> gb_sets:set().
diff --git a/lib/hipe/icode/hipe_icode_coordinator.erl b/lib/hipe/icode/hipe_icode_coordinator.erl
index c69db9afa9..d2f8748535 100644
--- a/lib/hipe/icode/hipe_icode_coordinator.erl
+++ b/lib/hipe/icode/hipe_icode_coordinator.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_ebb.erl b/lib/hipe/icode/hipe_icode_ebb.erl
index 966c4d7564..2aac9d2f42 100644
--- a/lib/hipe/icode/hipe_icode_ebb.erl
+++ b/lib/hipe/icode/hipe_icode_ebb.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_exceptions.erl b/lib/hipe/icode/hipe_icode_exceptions.erl
index 6191c536ad..f03ce2faaa 100644
--- a/lib/hipe/icode/hipe_icode_exceptions.erl
+++ b/lib/hipe/icode/hipe_icode_exceptions.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -84,7 +85,7 @@
%%----------------------------------------------------------------------------
--spec fix_catches(#cfg{}) -> #cfg{}.
+-spec fix_catches(cfg()) -> cfg().
fix_catches(CFG) ->
{Map, State} = build_mapping(find_catches(init_state(CFG))),
@@ -392,10 +393,10 @@ get_renaming(C, Map) ->
%%---------------------------------------------------------------------
%% State abstraction
--record(state, {cfg :: #cfg{},
+-record(state, {cfg :: cfg(),
changed = false :: boolean(),
- succ :: #cfg{},
- pred :: #cfg{},
+ succ :: cfg(),
+ pred :: cfg(),
start_labels :: [icode_lbl(),...],
visited = hipe_icode_cfg:none_visited() :: gb_sets:set(),
out = gb_trees:empty() :: gb_trees:tree(),
@@ -403,13 +404,8 @@ get_renaming(C, Map) ->
}).
init_state(CFG) ->
- State = #state{cfg = CFG},
- refresh_state_cache(State).
-
-refresh_state_cache(State) ->
- CFG = State#state.cfg,
SLs = [hipe_icode_cfg:start_label(CFG)],
- State#state{succ = CFG, pred = CFG, start_labels = SLs}.
+ #state{cfg = CFG, succ = CFG, pred = CFG, start_labels = SLs}.
get_cfg(State) ->
State#state.cfg.
@@ -465,7 +461,8 @@ get_bb_code(L, State) ->
set_bb_code(L, Code, State) ->
CFG = State#state.cfg,
CFG1 = hipe_icode_cfg:bb_add(CFG, L, hipe_bb:mk_bb(Code)),
- refresh_state_cache(State#state{cfg = CFG1}).
+ SLs = [hipe_icode_cfg:start_label(CFG1)],
+ State#state{cfg = CFG1, succ = CFG1, pred = CFG1, start_labels = SLs}.
get_new_catches_in(L, State) ->
Ps = get_pred(L, State),
diff --git a/lib/hipe/icode/hipe_icode_fp.erl b/lib/hipe/icode/hipe_icode_fp.erl
index 38b3881a77..4a5877074c 100644
--- a/lib/hipe/icode/hipe_icode_fp.erl
+++ b/lib/hipe/icode/hipe_icode_fp.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -33,13 +34,37 @@
-include("hipe_icode.hrl").
-include("../flow/cfg.hrl").
--record(state, {edge_map = gb_trees:empty() :: gb_trees:tree(),
- fp_ebb_map = gb_trees:empty() :: gb_trees:tree(),
- cfg :: #cfg{}}).
+-type mapped_fvar() :: icode_fvar() | {assigned, icode_fvar()} .
+-type incoming_fvars() :: [{icode_lbl(), mapped_fvar()}].
+-type initial_var_map() :: #{icode_var() => incoming_fvars()}.
+-type bb_phi_list() :: [{icode_fvar(), [{icode_lbl(), icode_fvar()}]}].
+-type var_map_phi() :: #{phi => bb_phi_list(),
+ icode_var() => mapped_fvar()}.
+-type var_map() :: #{icode_var() => mapped_fvar()}.
+
+-type edge() :: {icode_lbl(), icode_lbl()}.
+-type edge_map() :: #{edge() => var_map()}.
+
+-type worklist(Item) :: {[Item], [Item], gb_sets:set(Item)}.
+-type worklist() :: worklist(icode_lbl()).
+
+-type fail_lbl() :: [] | icode_lbl().
+-type in_block() :: {true, fail_lbl()} | false.
+-type fp_ebb_map() :: #{{inblock_in | inblock_out, icode_lbl()} | edge()
+ => in_block()}.
+
+-record(state, {edge_map = #{} :: edge_map(),
+ fp_ebb_map = #{} :: fp_ebb_map(),
+ cfg :: cfg()}).
+-type state() :: #state{}.
+
+-type icode_phi() :: #icode_phi{}.
+-type icode_variable() :: #icode_variable{}.
+-type icode_const() :: #icode_const{}.
%%--------------------------------------------------------------------
--spec cfg(#cfg{}) -> #cfg{}.
+-spec cfg(cfg()) -> cfg().
cfg(Cfg) ->
%%hipe_icode_cfg:pp(Cfg),
@@ -58,10 +83,14 @@ cfg(Cfg) ->
%% corresponding fcheckerror.
%%--------------------------------------------------------------------
+-spec annotate_fclearerror(cfg()) -> cfg().
+
annotate_fclearerror(Cfg) ->
Labels = hipe_icode_cfg:reverse_postorder(Cfg),
annotate_fclearerror(Labels, Cfg).
+-spec annotate_fclearerror([icode_lbl()], cfg()) -> cfg().
+
annotate_fclearerror([Label|Left], Cfg) ->
BB = hipe_icode_cfg:bb(Cfg, Label),
Code = hipe_bb:code(BB),
@@ -72,6 +101,9 @@ annotate_fclearerror([Label|Left], Cfg) ->
annotate_fclearerror([], Cfg) ->
Cfg.
+-spec annotate_fclearerror1(icode_instrs(), icode_lbl(), cfg(), icode_instrs())
+ -> icode_instrs().
+
annotate_fclearerror1([I|Left], Label, Cfg, Acc) ->
case I of
#icode_call{} ->
@@ -89,6 +121,9 @@ annotate_fclearerror1([I|Left], Label, Cfg, Acc) ->
annotate_fclearerror1([], _Label, _Cfg, Acc) ->
lists:reverse(Acc).
+-spec lookahead_for_fcheckerror(icode_instrs(), icode_lbl(), cfg()) ->
+ fail_lbl().
+
lookahead_for_fcheckerror([I|Left], Label, Cfg) ->
case I of
#icode_call{} ->
@@ -110,10 +145,14 @@ lookahead_for_fcheckerror([], Label, Cfg) ->
lookahead_for_fcheckerror(Code, Succ, Cfg)
end.
+-spec unannotate_fclearerror(cfg()) -> cfg().
+
unannotate_fclearerror(Cfg) ->
Labels = hipe_icode_cfg:reverse_postorder(Cfg),
unannotate_fclearerror(Labels, Cfg).
+-spec unannotate_fclearerror([icode_lbl()], cfg()) -> cfg().
+
unannotate_fclearerror([Label|Left], Cfg) ->
BB = hipe_icode_cfg:bb(Cfg, Label),
Code = hipe_bb:code(BB),
@@ -124,6 +163,9 @@ unannotate_fclearerror([Label|Left], Cfg) ->
unannotate_fclearerror([], Cfg) ->
Cfg.
+-spec unannotate_fclearerror1(icode_instrs(), icode_instrs()) ->
+ icode_instrs().
+
unannotate_fclearerror1([I|Left], Acc) ->
case I of
#icode_call{} ->
@@ -144,10 +186,14 @@ unannotate_fclearerror1([], Acc) ->
%% Make float EBBs
%%--------------------------------------------------------------------
+-spec place_fp_blocks(state()) -> state().
+
place_fp_blocks(State) ->
WorkList = new_worklist(State),
transform_block(WorkList, State).
+-spec transform_block(worklist(), state()) -> state().
+
transform_block(WorkList, State) ->
case get_work(WorkList) of
none ->
@@ -181,6 +227,10 @@ transform_block(WorkList, State) ->
end
end.
+-spec update_maps(state(), icode_lbl(), ordsets:ordset(icode_lbl()),
+ var_map(), ordsets:ordset(icode_lbl()), var_map())
+ -> fixpoint | {state(), [icode_lbl()]}.
+
update_maps(State, Label, SuccSet, SuccMap, FailSet, FailMap) ->
{NewState, Add1} = update_maps(State, Label, SuccSet, SuccMap, []),
case update_maps(NewState, Label, FailSet, FailMap, Add1) of
@@ -188,6 +238,10 @@ update_maps(State, Label, SuccSet, SuccMap, FailSet, FailMap) ->
{_NewState1, _Add} = Ret -> Ret
end.
+-spec update_maps(state(), icode_lbl(), ordsets:ordset(icode_lbl()),
+ var_map(), [icode_lbl()])
+ -> {state(), [icode_lbl()]}.
+
update_maps(State, From, [To|Left], Map, Acc) ->
case state__map_update(State, From, To, Map) of
fixpoint ->
@@ -198,10 +252,13 @@ update_maps(State, From, [To|Left], Map, Acc) ->
update_maps(State, _From, [], _Map, Acc) ->
{State, Acc}.
+-spec transform_instrs(icode_instrs(), edge_map(), var_map(), icode_instrs())
+ -> {var_map(), icode_instrs()}.
+
transform_instrs([I|Left], PhiMap, Map, Acc) ->
Defines = hipe_icode:defines(I),
- NewMap = delete_all(Defines, Map),
- NewPhiMap = delete_all(Defines, PhiMap),
+ NewMap = maps:without(Defines, Map),
+ NewPhiMap = maps:without(Defines, PhiMap),
case I of
#icode_phi{} ->
Uses = hipe_icode:uses(I),
@@ -213,7 +270,7 @@ transform_instrs([I|Left], PhiMap, Map, Acc) ->
%% All arguments are untagged. Let's untag the destination.
Dst = hipe_icode:phi_dst(I),
NewDst = hipe_icode:mk_new_fvar(),
- NewMap1 = gb_trees:enter(Dst, NewDst, NewMap),
+ NewMap1 = NewMap#{Dst => NewDst},
NewI = subst_phi_uncond(I, NewDst, PhiMap),
transform_instrs(Left, NewPhiMap, NewMap1, [NewI|Acc]);
_ ->
@@ -232,7 +289,7 @@ transform_instrs([I|Left], PhiMap, Map, Acc) ->
[Src] ->
case lookup(Src, Map) of
none ->
- NewMap1 = gb_trees:enter(Src, {assigned, Dst}, NewMap),
+ NewMap1 = NewMap#{Src => {assigned, Dst}},
transform_instrs(Left, NewPhiMap, NewMap1, [I|Acc]);
Dst ->
%% This is the instruction that untagged the variable.
@@ -255,7 +312,7 @@ transform_instrs([I|Left], PhiMap, Map, Acc) ->
unsafe_tag_float ->
[Dst] = hipe_icode:defines(I),
[Src] = hipe_icode:uses(I),
- NewMap1 = gb_trees:enter(Dst, {assigned, Src}, NewMap),
+ NewMap1 = NewMap#{Dst => {assigned, Src}},
transform_instrs(Left, NewPhiMap, NewMap1,[I|Acc]);
_ ->
{NewMap1, NewAcc} = check_for_fop_candidates(I, NewMap, Acc),
@@ -268,6 +325,9 @@ transform_instrs([I|Left], PhiMap, Map, Acc) ->
transform_instrs([], _PhiMap, Map, Acc) ->
{Map, lists:reverse(Acc)}.
+-spec check_for_fop_candidates(icode_instr(), var_map(), icode_instrs())
+ -> {var_map(), icode_instrs()}.
+
check_for_fop_candidates(I, Map, Acc) ->
case is_fop_cand(I) of
false ->
@@ -310,6 +370,8 @@ check_for_fop_candidates(I, Map, Acc) ->
end.
+-spec handle_untagged_arguments(icode_instr(), var_map()) -> icode_instrs().
+
%% If this is an instruction that needs to operate on tagged values,
%% which currently are untagged, we must tag the values and perhaps
%% end the fp ebb.
@@ -321,23 +383,24 @@ handle_untagged_arguments(I, Map) ->
Tag ->
TagIntrs =
[hipe_icode:mk_primop([Dst], unsafe_tag_float,
- [gb_trees:get(Dst, Map)]) || Dst <- Tag],
+ [maps:get(Dst, Map)]) || Dst <- Tag],
[I|TagIntrs]
end.
+-spec do_prelude(var_map_phi()) -> {[icode_phi()], var_map()}.
+
%% Add phi nodes for untagged fp values.
-do_prelude(Map) ->
- case gb_trees:lookup(phi, Map) of
- none ->
- {[], Map};
- {value, List} ->
- %%io:format("Adding phi: ~w\n", [List]),
- Fun = fun ({FVar, Bindings}, Acc) ->
- [hipe_icode:mk_phi(FVar, Bindings)|Acc]
- end,
- {lists:foldl(Fun, [], List), gb_trees:delete(phi, Map)}
- end.
+do_prelude(Map = #{phi := List}) ->
+ %%io:format("Adding phi: ~w\n", [List]),
+ Fun = fun ({FVar, Bindings}, Acc) ->
+ [hipe_icode:mk_phi(FVar, Bindings)|Acc]
+ end,
+ {lists:foldl(Fun, [], List), maps:remove(phi, Map)};
+do_prelude(Map) -> {[], Map}.
+
+-spec split_code([I]) -> {[I], I} when
+ I :: icode_instr().
split_code(Code) ->
split_code(Code, []).
@@ -348,6 +411,8 @@ split_code([I|Left], Acc) ->
split_code(Left, [I|Acc]).
+-spec finalize(state()) -> state().
+
%% When all code is mapped to fp instructions we must make sure that
%% the fp ebb information going into each block is the same as the
%% information coming out of each predecessor. Otherwise, we must add
@@ -359,17 +424,25 @@ finalize(State) ->
Edges = needs_fcheckerror(NewState),
finalize(Edges, NewState).
+-spec finalize([edge()], state()) -> state().
+
finalize([{From, To}|Left], State) ->
NewState = add_fp_ebb_fixup(From, To, State),
finalize(Left, NewState);
finalize([], State) ->
State.
+-spec needs_fcheckerror(state()) -> [{none | icode_lbl(), icode_lbl()}].
+
needs_fcheckerror(State) ->
Cfg = state__cfg(State),
Labels = hipe_icode_cfg:labels(Cfg),
needs_fcheckerror(Labels, State, []).
+-spec needs_fcheckerror([icode_lbl()], state(),
+ [{none | icode_lbl(), icode_lbl()}])
+ -> [{none | icode_lbl(), icode_lbl()}].
+
needs_fcheckerror([Label|Left], State, Acc) ->
case state__get_in_block_in(State, Label) of
{true, _} ->
@@ -394,6 +467,8 @@ needs_fcheckerror([Label|Left], State, Acc) ->
needs_fcheckerror([], _State, Acc) ->
Acc.
+-spec add_fp_ebb_fixup(none | icode_lbl(), icode_lbl(), state()) -> state().
+
add_fp_ebb_fixup('none', To, State) ->
%% Add the fcheckerror to the start of the block.
BB = state__bb(State, To),
@@ -415,9 +490,15 @@ add_fp_ebb_fixup(From, To, State) ->
NewToBB = hipe_bb:code_update(ToBB, NewToCode),
state__bb_add(NewState1, To, NewToBB).
+-spec redirect_phis(icode_instrs(), icode_lbl(), icode_lbl())
+ -> icode_instrs().
+
redirect_phis(Code, OldFrom, NewFrom) ->
redirect_phis(Code, OldFrom, NewFrom, []).
+-spec redirect_phis(icode_instrs(), icode_lbl(), icode_lbl(), icode_instrs())
+ -> icode_instrs().
+
redirect_phis([I|Is] = Code, OldFrom, NewFrom, Acc) ->
case I of
#icode_phi{} ->
@@ -429,13 +510,20 @@ redirect_phis([I|Is] = Code, OldFrom, NewFrom, Acc) ->
redirect_phis([], _OldFrom, _NewFrom, Acc) ->
lists:reverse(Acc).
+-spec subst_phi(icode_phi(), icode_variable(), edge_map())
+ -> icode_phi().
+
subst_phi(I, Dst, Map) ->
ArgList = subst_phi_uses0(hipe_icode:phi_arglist(I), Map, []),
hipe_icode:mk_phi(Dst, ArgList).
+-spec subst_phi_uses0([{icode_lbl(), icode_variable()}], edge_map(),
+ [{icode_lbl(), icode_variable()}])
+ -> [{icode_lbl(), icode_variable()}].
+
subst_phi_uses0([{Pred, Var}|Left], Map, Acc) ->
- case gb_trees:lookup(Var, Map) of
- {value, List} ->
+ case Map of
+ #{Var := List} ->
case lists:keyfind(Pred, 1, List) of
{Pred, {assigned, _NewVar}} ->
%% The variable is untagged, but it has been assigned. Keep it!
@@ -447,20 +535,27 @@ subst_phi_uses0([{Pred, Var}|Left], Map, Acc) ->
%% The variable is not untagged.
subst_phi_uses0(Left, Map, [{Pred, Var} | Acc])
end;
- none ->
+ #{} ->
%% The variable is not untagged.
subst_phi_uses0(Left, Map, [{Pred, Var} | Acc])
end;
subst_phi_uses0([], _Map, Acc) ->
Acc.
+-spec subst_phi_uncond(icode_phi(), icode_variable(), edge_map())
+ -> icode_phi().
+
subst_phi_uncond(I, Dst, Map) ->
ArgList = subst_phi_uses_uncond0(hipe_icode:phi_arglist(I), Map, []),
hipe_icode:mk_phi(Dst, ArgList).
+-spec subst_phi_uses_uncond0([{icode_lbl(), icode_variable()}], edge_map(),
+ [{icode_lbl(), icode_variable()}])
+ -> [{icode_lbl(), icode_variable()}].
+
subst_phi_uses_uncond0([{Pred, Var}|Left], Map, Acc) ->
- case gb_trees:lookup(Var, Map) of
- {value, List} ->
+ case Map of
+ #{Var := List} ->
case lists:keyfind(Pred, 1, List) of
{Pred, {assigned, NewVar}} ->
%% The variable is untagged!
@@ -472,13 +567,15 @@ subst_phi_uses_uncond0([{Pred, Var}|Left], Map, Acc) ->
%% The variable is not untagged.
subst_phi_uses_uncond0(Left, Map, [{Pred, Var} | Acc])
end;
- none ->
+ #{} ->
%% The variable is not untagged.
subst_phi_uses_uncond0(Left, Map, [{Pred, Var} | Acc])
end;
subst_phi_uses_uncond0([], _Map, Acc) ->
Acc.
+-spec place_error_handling(worklist(), state()) -> state().
+
place_error_handling(WorkList, State) ->
case get_work(WorkList) of
none ->
@@ -501,6 +598,9 @@ place_error_handling(WorkList, State) ->
end
end.
+-spec place_error(icode_instrs(), in_block(), icode_instrs())
+ -> {icode_instrs(), in_block()}.
+
place_error([I|Left], InBlock, Acc) ->
case I of
#icode_call{} ->
@@ -637,12 +737,10 @@ instr_allowed_in_fp_ebb(Instr) ->
%%=============================================================
%% ------------------------------------------------------------
-%% Handling the gb_tree
+%% Handling the variable map
-delete_all([Key|Left], Tree) ->
- delete_all(Left, gb_trees:delete_any(Key, Tree));
-delete_all([], Tree) ->
- Tree.
+-spec lookup_list([icode_var() | icode_const()], var_map())
+ -> [none | icode_fvar()].
lookup_list(List, Info) ->
lookup_list(List, fun lookup/2, Info, []).
@@ -652,33 +750,43 @@ lookup_list([H|T], Fun, Info, Acc) ->
lookup_list([], _, _, Acc) ->
lists:reverse(Acc).
+-spec lookup(icode_var() | icode_const(), var_map()) -> none | icode_fvar().
+
lookup(Key, Tree) ->
case hipe_icode:is_const(Key) of
%% This can be true if the same constant has been
%% untagged more than once
true -> none;
false ->
- case gb_trees:lookup(Key, Tree) of
- none -> none;
- {value, {assigned, Val}} -> Val;
- {value, Val} -> Val
+ case Tree of
+ #{Key := {assigned, Val}} -> Val;
+ #{Key := Val} -> Val;
+ #{} -> none
end
end.
+-spec lookup_list_keep_consts([icode_var() | icode_const()], var_map())
+ -> [none | icode_fvar() | icode_const()].
+
lookup_list_keep_consts(List, Info) ->
lookup_list(List, fun lookup_keep_consts/2, Info, []).
+-spec lookup_keep_consts(icode_var() | icode_const(), var_map())
+ -> none | icode_fvar() | icode_const().
+
lookup_keep_consts(Key, Tree) ->
case hipe_icode:is_const(Key) of
true -> Key;
false ->
- case gb_trees:lookup(Key, Tree) of
- none -> none;
- {value, {assigned, Val}} -> Val;
- {value, Val} -> Val
+ case Tree of
+ #{Key := {assigned, Val}} -> Val;
+ #{Key := Val} -> Val;
+ #{} -> none
end
end.
+-spec get_type(icode_argument()) -> erl_types:erl_type().
+
get_type(Var) ->
case hipe_icode:is_const(Var) of
true -> erl_types:t_from_term(hipe_icode:const_value(Var));
@@ -694,98 +802,108 @@ get_type(Var) ->
%% ------------------------------------------------------------
%% Handling the map from variables to fp-variables
+-spec join_maps([edge()], edge_map()) -> initial_var_map().
+
join_maps(Edges, EdgeMap) ->
- join_maps(Edges, EdgeMap, gb_trees:empty()).
+ join_maps(Edges, EdgeMap, #{}).
join_maps([Edge = {Pred, _}|Left], EdgeMap, Map) ->
- case gb_trees:lookup(Edge, EdgeMap) of
- none ->
+ case EdgeMap of
+ #{Edge := OldMap} ->
+ NewMap = join_maps0(maps:to_list(OldMap), Pred, Map),
+ join_maps(Left, EdgeMap, NewMap);
+ #{} ->
%% All predecessors have not been handled. Use empty map.
- gb_trees:empty();
- {value, OldMap} ->
- NewMap = join_maps0(gb_trees:to_list(OldMap), Pred, Map),
- join_maps(Left, EdgeMap, NewMap)
+ #{}
end;
join_maps([], _, Map) ->
Map.
-join_maps0([{phi, _}|Tail], Pred, Map) ->
- join_maps0(Tail, Pred, Map);
-join_maps0([{Var, FVar}|Tail], Pred, Map) ->
- case gb_trees:lookup(Var, Map) of
- none ->
- join_maps0(Tail, Pred, gb_trees:enter(Var, [{Pred, FVar}], Map));
- {value, List} ->
+-spec join_maps0(list(), icode_lbl(), initial_var_map()) -> initial_var_map().
+
+join_maps0([{Var=#icode_variable{kind=var}, FVar}|Tail], Pred, Map) ->
+ case Map of
+ #{Var := List} ->
case lists:keyfind(Pred, 1, List) of
false ->
- join_maps0(Tail, Pred, gb_trees:update(Var, [{Pred, FVar}|List], Map));
+ join_maps0(Tail, Pred, Map#{Var := [{Pred, FVar}|List]});
{Pred, FVar} ->
%% No problem.
join_maps0(Tail, Pred, Map);
_ ->
exit('New binding to same variable')
- end
+ end;
+ #{} ->
+ join_maps0(Tail, Pred, Map#{Var => [{Pred, FVar}]})
end;
join_maps0([], _, Map) ->
Map.
+-spec filter_map(initial_var_map(), pos_integer()) -> var_map_phi().
+
filter_map(Map, NofPreds) ->
- filter_map(gb_trees:to_list(Map), NofPreds, Map).
+ filter_map(maps:to_list(Map), NofPreds, Map).
+
+-spec filter_map([{icode_var(), incoming_fvars()}], pos_integer(),
+ var_map_phi()) -> var_map_phi().
filter_map([{Var, Bindings}|Left], NofPreds, Map) ->
case length(Bindings) =:= NofPreds of
true ->
+ BindingsAllAssigned = lists:all(fun({_, {assigned, _}}) -> true;
+ ({_, _}) -> false
+ end, Bindings),
case all_args_equal(Bindings) of
true ->
- {_, FVar} = hd(Bindings),
- filter_map(Left, NofPreds, gb_trees:update(Var, FVar, Map));
+ NewBinding =
+ case hd(Bindings) of
+ {Pred, {assigned, FVar0}} when is_integer(Pred) ->
+ case BindingsAllAssigned of
+ true -> {assigned, FVar0};
+ false -> FVar0
+ end;
+ {Pred, FVar0} when is_integer(Pred) -> FVar0
+ end,
+ filter_map(Left, NofPreds, Map#{Var := NewBinding});
false ->
PhiDst = hipe_icode:mk_new_fvar(),
PhiArgs = strip_of_assigned(Bindings),
NewMap =
- case gb_trees:lookup(phi, Map) of
- none ->
- gb_trees:insert(phi, [{PhiDst, PhiArgs}], Map);
- {value, Val} ->
- gb_trees:update(phi, [{PhiDst, PhiArgs}|Val], Map)
+ case Map of
+ #{phi := Val} ->
+ Map#{phi := [{PhiDst, PhiArgs}|Val]};
+ #{} ->
+ Map#{phi => [{PhiDst, PhiArgs}]}
end,
NewBinding =
- case bindings_are_assigned(Bindings) of
+ case BindingsAllAssigned of
true -> {assigned, PhiDst};
false -> PhiDst
end,
- filter_map(Left, NofPreds, gb_trees:update(Var, NewBinding, NewMap))
+ filter_map(Left, NofPreds, NewMap#{Var := NewBinding})
end;
false ->
- filter_map(Left, NofPreds, gb_trees:delete(Var, Map))
+ filter_map(Left, NofPreds, maps:remove(Var, Map))
end;
filter_map([], _NofPreds, Map) ->
Map.
-bindings_are_assigned([{_, {assigned, _}}|Left]) ->
- assert_assigned(Left),
- true;
-bindings_are_assigned(Bindings) ->
- assert_not_assigned(Bindings),
- false.
-
-assert_assigned([{_, {assigned, _}}|Left]) ->
- assert_assigned(Left);
-assert_assigned([]) ->
- ok.
-
-assert_not_assigned([{_, FVar}|Left]) ->
- true = hipe_icode:is_fvar(FVar),
- assert_not_assigned(Left);
-assert_not_assigned([]) ->
- ok.
+-spec all_args_equal(incoming_fvars()) -> boolean().
%% all_args_equal returns true if the mapping for a variable is the
%% same from all predecessors, i.e., we do not need a phi-node.
+%% During the fixpoint loop, a mapping might become assigned, without that
+%% information having propagated into all predecessors. We take care to answer
+%% true even if FVar is only assigned in some predecessors.
+
+all_args_equal([{_, {assigned, FVar}}|Left]) ->
+ all_args_equal(Left, FVar);
all_args_equal([{_, FVar}|Left]) ->
all_args_equal(Left, FVar).
+all_args_equal([{_, {assigned, FVar1}}|Left], FVar1) ->
+ all_args_equal(Left, FVar1);
all_args_equal([{_, FVar1}|Left], FVar1) ->
all_args_equal(Left, FVar1);
all_args_equal([], _) ->
@@ -794,20 +912,24 @@ all_args_equal(_, _) ->
false.
+-spec add_new_bindings_unassigned([icode_var()], var_map()) -> var_map().
+
%% We differentiate between values that have been assigned as
%% tagged variables and those that got a 'virtual' binding.
add_new_bindings_unassigned([Var|Left], Map) ->
FVar = hipe_icode:mk_new_fvar(),
- add_new_bindings_unassigned(Left, gb_trees:insert(Var, FVar, Map));
+ add_new_bindings_unassigned(Left, Map#{Var => FVar});
add_new_bindings_unassigned([], Map) ->
Map.
+-spec add_new_bindings_assigned([icode_var()], var_map()) -> var_map().
+
add_new_bindings_assigned([Var|Left], Map) ->
case lookup(Var, Map) of
none ->
FVar = hipe_icode:mk_new_fvar(),
- NewMap = gb_trees:insert(Var, {assigned, FVar}, Map),
+ NewMap = Map#{Var => {assigned, FVar}},
add_new_bindings_assigned(Left, NewMap);
_ ->
add_new_bindings_assigned(Left, Map)
@@ -815,6 +937,8 @@ add_new_bindings_assigned([Var|Left], Map) ->
add_new_bindings_assigned([], Map) ->
Map.
+-spec strip_of_assigned(incoming_fvars()) -> [{icode_lbl(), icode_fvar()}].
+
strip_of_assigned(List) ->
strip_of_assigned(List, []).
@@ -829,6 +953,8 @@ strip_of_assigned([], Acc) ->
%% Help functions for the transformation from ordinary instruction to
%% fp-instruction
+-spec is_fop_cand(icode_instr()) -> boolean().
+
is_fop_cand(I) ->
case hipe_icode:call_fun(I) of
'/' -> true;
@@ -839,6 +965,8 @@ is_fop_cand(I) ->
end
end.
+-spec any_is_float([icode_argument()]) -> boolean().
+
any_is_float(Vars) ->
lists:any(fun (V) -> erl_types:t_is_float(get_type(V)) end, Vars).
@@ -865,25 +993,32 @@ fun_to_fop(Fun) ->
end.
+-spec must_be_tagged(icode_var(), var_map()) -> boolean().
+
%% If there is a tagged version of this variable available we don't
%% have to tag the untagged version.
must_be_tagged(Var, Map) ->
- case gb_trees:lookup(Var, Map) of
- none -> false;
- {value, {assigned, _}} -> false;
- {value, Val} -> hipe_icode:is_fvar(Val)
+ case Map of
+ #{Var := {assigned, _}} -> false;
+ #{Var := Val} -> hipe_icode:is_fvar(Val);
+ #{} -> false
end.
+-spec get_conv_instrs([icode_argument()], var_map()) -> icode_instrs().
+
%% Converting to floating point variables
get_conv_instrs(Vars, Map) ->
get_conv_instrs(Vars, Map, []).
+-spec get_conv_instrs([icode_argument()], var_map(), icode_instrs())
+ -> icode_instrs().
+
get_conv_instrs([Var|Left], Map, Acc) ->
- {_, Dst} = gb_trees:get(Var, Map),
- NewI =
+ #{Var := {_, Dst}} = Map,
+ NewI =
case erl_types:t_is_float(get_type(Var)) of
true ->
[hipe_icode:mk_primop([Dst], unsafe_untag_float, [Var])];
@@ -895,6 +1030,8 @@ get_conv_instrs([], _, Acc) ->
Acc.
+-spec conv_consts([icode_const()], icode_instr()) -> icode_instr().
+
conv_consts(ConstArgs, I) ->
conv_consts(ConstArgs, I, []).
@@ -933,63 +1070,79 @@ state__bb_add(S = #state{cfg = Cfg}, Label, BB) ->
NewCfg = hipe_icode_cfg:bb_add(Cfg, Label, BB),
S#state{cfg = NewCfg}.
+-spec state__map(state(), icode_lbl()) -> initial_var_map().
+
state__map(S = #state{edge_map = EM}, To) ->
join_maps([{From, To} || From <- state__pred(S, To)], EM).
+-spec state__map_update(state(), icode_lbl(), icode_lbl(), var_map()) ->
+ fixpoint | state().
+
state__map_update(S = #state{edge_map = EM}, From, To, Map) ->
FromTo = {From, To},
MapChanged =
- case gb_trees:lookup(FromTo, EM) of
- {value, Map1} -> not match(Map1, Map);
- none -> true
+ case EM of
+ #{FromTo := Map1} -> not match(Map1, Map);
+ #{} -> true
end,
case MapChanged of
true ->
- NewEM = gb_trees:enter(FromTo, Map, EM),
+ NewEM = EM#{FromTo => Map},
S#state{edge_map = NewEM};
false ->
fixpoint
end.
+-spec state__join_in_block(state(), icode_lbl())
+ -> fixpoint | {state(), in_block()}.
+
state__join_in_block(S = #state{fp_ebb_map = Map}, Label) ->
Pred = state__pred(S, Label),
Edges = [{X, Label} || X <- Pred],
- NewInBlock = join_in_block([gb_trees:lookup(X, Map) || X <- Edges]),
+ NewInBlock = join_in_block([maps:find(X, Map) || X <- Edges]),
InBlockLabel = {inblock_in, Label},
- case gb_trees:lookup(InBlockLabel, Map) of
- none ->
- NewMap = gb_trees:insert(InBlockLabel, NewInBlock, Map),
- {S#state{fp_ebb_map = NewMap}, NewInBlock};
- {value, NewInBlock} ->
+ case Map of
+ #{InBlockLabel := NewInBlock} ->
fixpoint;
- _Other ->
- NewMap = gb_trees:update(InBlockLabel, NewInBlock, Map),
+ _ ->
+ NewMap = Map#{InBlockLabel => NewInBlock},
{S#state{fp_ebb_map = NewMap}, NewInBlock}
end.
+-spec state__in_block_out_update(state(), icode_lbl(), in_block())
+ -> state().
+
state__in_block_out_update(S = #state{fp_ebb_map = Map}, Label, NewInBlock) ->
Succ = state__succ(S, Label),
Edges = [{Label, X} || X <- Succ],
NewMap = update_edges(Edges, NewInBlock, Map),
- NewMap1 = gb_trees:enter({inblock_out, Label}, NewInBlock, NewMap),
+ NewMap1 = NewMap#{{inblock_out, Label} => NewInBlock},
S#state{fp_ebb_map = NewMap1}.
+-spec update_edges([edge()], in_block(), fp_ebb_map()) -> fp_ebb_map().
+
update_edges([Edge|Left], NewInBlock, Map) ->
- NewMap = gb_trees:enter(Edge, NewInBlock, Map),
+ NewMap = Map#{Edge => NewInBlock},
update_edges(Left, NewInBlock, NewMap);
update_edges([], _NewInBlock, NewMap) ->
NewMap.
+-spec join_in_block([error | {ok, in_block()}]) -> in_block().
+
join_in_block([]) ->
false;
-join_in_block([none|_]) ->
+join_in_block([error|_]) ->
false;
-join_in_block([{value, InBlock}|Left]) ->
+join_in_block([{ok, InBlock}|Left]) ->
join_in_block(Left, InBlock).
-join_in_block([none|_], _Current) ->
+-spec join_in_block([error | {ok, in_block()}], Current)
+ -> false | Current when
+ Current :: in_block().
+
+join_in_block([error|_], _Current) ->
false;
-join_in_block([{value, InBlock}|Left], Current) ->
+join_in_block([{ok, InBlock}|Left], Current) ->
if Current =:= InBlock -> join_in_block(Left, Current);
Current =:= false -> false;
InBlock =:= false -> false;
@@ -997,19 +1150,25 @@ join_in_block([{value, InBlock}|Left], Current) ->
end;
join_in_block([], Current) ->
Current.
-
+
+
+-spec state__get_in_block_in(state(), icode_lbl()) -> in_block().
state__get_in_block_in(#state{fp_ebb_map = Map}, Label) ->
- gb_trees:get({inblock_in, Label}, Map).
+ maps:get({inblock_in, Label}, Map).
state__get_in_block_out(#state{fp_ebb_map = Map}, Label) ->
- gb_trees:get({inblock_out, Label}, Map).
+ maps:get({inblock_out, Label}, Map).
+-spec new_worklist(state()) -> worklist().
+
new_worklist(#state{cfg = Cfg}) ->
Start = hipe_icode_cfg:start_label(Cfg),
{[Start], [], gb_sets:insert(Start, gb_sets:empty())}.
+-spec get_work(worklist()) -> none | {icode_lbl(), worklist()}.
+
get_work({[Label|Left], List, Set}) ->
{Label, {Left, List, gb_sets:delete(Label, Set)}};
get_work({[], [], _Set}) ->
@@ -1017,6 +1176,8 @@ get_work({[], [], _Set}) ->
get_work({[], List, Set}) ->
get_work({lists:reverse(List), [], Set}).
+-spec add_work(worklist(), [icode_lbl()]) -> worklist().
+
add_work({List1, List2, Set} = Work, [Label|Left]) ->
case gb_sets:is_member(Label, Set) of
true ->
@@ -1029,15 +1190,7 @@ add_work({List1, List2, Set} = Work, [Label|Left]) ->
add_work(WorkList, []) ->
WorkList.
-match(Tree1, Tree2) ->
- match_1(gb_trees:to_list(Tree1), Tree2) andalso
- match_1(gb_trees:to_list(Tree2), Tree1).
+-spec match(var_map(), var_map()) -> boolean().
-match_1([{Key, Val}|Left], Tree2) ->
- case gb_trees:lookup(Key, Tree2) of
- {value, Val} ->
- match_1(Left, Tree2);
- _ -> false
- end;
-match_1([], _) ->
- true.
+match(Tree1, Tree2) when is_map(Tree1), is_map(Tree2) ->
+ Tree1 =:= Tree2.
diff --git a/lib/hipe/icode/hipe_icode_heap_test.erl b/lib/hipe/icode/hipe_icode_heap_test.erl
index 92d5f023fa..ec754d5ee9 100644
--- a/lib/hipe/icode/hipe_icode_heap_test.erl
+++ b/lib/hipe/icode/hipe_icode_heap_test.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_inline_bifs.erl b/lib/hipe/icode/hipe_icode_inline_bifs.erl
index 6ef15b9a18..79f67c2db6 100644
--- a/lib/hipe/icode/hipe_icode_inline_bifs.erl
+++ b/lib/hipe/icode/hipe_icode_inline_bifs.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_instruction_counter.erl b/lib/hipe/icode/hipe_icode_instruction_counter.erl
index f44adfe149..afa70e495b 100644
--- a/lib/hipe/icode/hipe_icode_instruction_counter.erl
+++ b/lib/hipe/icode/hipe_icode_instruction_counter.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_liveness.erl b/lib/hipe/icode/hipe_icode_liveness.erl
index 5816e59032..317d2e54c2 100644
--- a/lib/hipe/icode/hipe_icode_liveness.erl
+++ b/lib/hipe/icode/hipe_icode_liveness.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_mulret.erl b/lib/hipe/icode/hipe_icode_mulret.erl
index 99522f6430..d927a46222 100644
--- a/lib/hipe/icode/hipe_icode_mulret.erl
+++ b/lib/hipe/icode/hipe_icode_mulret.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_pp.erl b/lib/hipe/icode/hipe_icode_pp.erl
index de29b6f779..a736b54c38 100644
--- a/lib/hipe/icode/hipe_icode_pp.erl
+++ b/lib/hipe/icode/hipe_icode_pp.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_primops.erl b/lib/hipe/icode/hipe_icode_primops.erl
index b0113fc556..cee37b6a57 100644
--- a/lib/hipe/icode/hipe_icode_primops.erl
+++ b/lib/hipe/icode/hipe_icode_primops.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -115,7 +116,7 @@ is_safe({hipe_bs_primop, {bs_init, _, _}}) -> false;
is_safe({hipe_bs_primop, {bs_init_bits, _}}) -> false;
is_safe({hipe_bs_primop, {bs_init_bits, _, _}}) -> false;
is_safe({hipe_bs_primop, {bs_put_binary, _, _}}) -> false;
-is_safe({hipe_bs_primop, {bs_put_binary_all, _}}) -> false;
+is_safe({hipe_bs_primop, {bs_put_binary_all, _, _}}) -> false;
is_safe({hipe_bs_primop, {bs_put_float, _, _, _}}) -> false;
is_safe({hipe_bs_primop, {bs_put_integer, _, _, _}}) -> false;
is_safe({hipe_bs_primop, {bs_put_string, _, _}}) -> false;
@@ -218,7 +219,7 @@ fails({hipe_bs_primop, {bs_init, _, _}}) -> true;
fails({hipe_bs_primop, {bs_init_bits, _}}) -> true;
fails({hipe_bs_primop, {bs_init_bits, _, _}}) -> true;
fails({hipe_bs_primop, {bs_put_binary, _, _}}) -> true;
-fails({hipe_bs_primop, {bs_put_binary_all, _}}) -> true;
+fails({hipe_bs_primop, {bs_put_binary_all, _, _}}) -> true;
fails({hipe_bs_primop, {bs_put_float, _, _, _}}) -> true;
fails({hipe_bs_primop, {bs_put_integer, _, _, _}}) -> true;
fails({hipe_bs_primop, {bs_put_string, _, _}}) -> true;
@@ -264,8 +265,8 @@ pp(Dev, Op) ->
io:format(Dev, "gc_test<~w>", [N]);
{hipe_bs_primop, BsOp} ->
case BsOp of
- {bs_put_binary_all, Flags} ->
- io:format(Dev, "bs_put_binary_all<~w>", [Flags]);
+ {bs_put_binary_all, Unit, Flags} ->
+ io:format(Dev, "bs_put_binary_all<~w, ~w>", [Unit,Flags]);
{bs_put_binary, Size} ->
io:format(Dev, "bs_put_binary<~w>", [Size]);
{bs_put_binary, Flags, Size} ->
@@ -503,14 +504,16 @@ type(Primop, Args) ->
NewBinType = match_bin(erl_types:t_bitstr(0, Size), BinType),
NewMatchState =
erl_types:t_matchstate_update_present(NewBinType, MatchState),
- if Signed =:= 0 ->
- erl_types:t_product([erl_types:t_from_range(0, 1 bsl Size - 1),
- NewMatchState]);
- Signed =:= 4 ->
- erl_types:t_product([erl_types:t_from_range(- (1 bsl (Size-1)),
- (1 bsl (Size-1)) - 1),
- NewMatchState])
- end;
+ Range =
+ case Signed of
+ 0 ->
+ UpperBound = inf_add(safe_bsl_1(Size), -1),
+ erl_types:t_from_range(0, UpperBound);
+ 4 ->
+ Bound = safe_bsl_1(Size - 1),
+ erl_types:t_from_range(inf_inv(Bound), inf_add(Bound, -1))
+ end,
+ erl_types:t_product([Range, NewMatchState]);
[_Arg] ->
NewBinType = match_bin(erl_types:t_bitstr(Size, 0), BinType),
NewMatchState =
@@ -627,8 +630,9 @@ type(Primop, Args) ->
[_SrcType, _BitsType, _Base, Type] ->
erl_types:t_bitstr_concat(Type, erl_types:t_bitstr(Size, 0))
end;
- {hipe_bs_primop, {bs_put_binary_all, _Flags}} ->
- [SrcType, _Base, Type] = Args,
+ {hipe_bs_primop, {bs_put_binary_all, Unit, _Flags}} ->
+ [SrcType0, _Base, Type] = Args,
+ SrcType = erl_types:t_inf(erl_types:t_bitstr(Unit, 0), SrcType0),
erl_types:t_bitstr_concat(SrcType,Type);
{hipe_bs_primop, {bs_put_string, _, Size}} ->
[_Base, Type] = Args,
@@ -964,3 +968,20 @@ check_fun_args(_, _) ->
match_bin(Pattern, Match) ->
erl_types:t_bitstr_match(Pattern, Match).
+
+-spec safe_bsl_1(non_neg_integer()) -> non_neg_integer() | 'pos_inf'.
+
+safe_bsl_1(Shift) when Shift =< 128 -> 1 bsl Shift;
+safe_bsl_1(_Shift) -> pos_inf.
+
+%%
+%% The following two functions are stripped-down versions of more
+%% general functions that exist in hipe_icode_range.erl
+%%
+
+inf_inv(pos_inf) -> neg_inf;
+inf_inv(Number) when is_integer(Number) -> -Number.
+
+inf_add(pos_inf, _Number) -> pos_inf;
+inf_add(Number1, Number2) when is_integer(Number1), is_integer(Number2) ->
+ Number1 + Number2.
diff --git a/lib/hipe/icode/hipe_icode_primops.hrl b/lib/hipe/icode/hipe_icode_primops.hrl
index 8a65c5ece0..a0aee165ba 100644
--- a/lib/hipe/icode/hipe_icode_primops.hrl
+++ b/lib/hipe/icode/hipe_icode_primops.hrl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_range.erl b/lib/hipe/icode/hipe_icode_range.erl
index fbc58f3568..12ed796690 100644
--- a/lib/hipe/icode/hipe_icode_range.erl
+++ b/lib/hipe/icode/hipe_icode_range.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -88,6 +89,7 @@
ret_type :: range(),
lookup_fun :: call_fun(),
result_action :: final_fun()}).
+-type state() :: #state{}.
-define(WIDEN, 1).
@@ -171,7 +173,7 @@ analyse(Cfg, Data) ->
catch throw:no_input -> ok
end.
--spec safe_analyse(cfg(), data()) -> #state{}.
+-spec safe_analyse(cfg(), data()) -> state().
safe_analyse(CFG, Data={MFA,_,_,_}) ->
State = state__init(CFG, Data),
@@ -180,14 +182,14 @@ safe_analyse(CFG, Data={MFA,_,_,_}) ->
(state__result_action(NewState))(MFA, [state__ret_type(NewState)]),
NewState.
--spec rewrite_blocks(#state{}) -> #state{}.
+-spec rewrite_blocks(state()) -> state().
rewrite_blocks(State) ->
CFG = state__cfg(State),
Start = hipe_icode_cfg:start_label(CFG),
rewrite_blocks([Start], State, [Start]).
--spec rewrite_blocks([label()], #state{}, [label()]) -> #state{}.
+-spec rewrite_blocks([label()], state(), [label()]) -> state().
rewrite_blocks([Next|Rest], State, Visited) ->
Info = state__info_in(State, Next),
@@ -200,7 +202,7 @@ rewrite_blocks([Next|Rest], State, Visited) ->
rewrite_blocks([], State, _) ->
State.
--spec analyse_blocks(#state{}, work_list()) -> #state{}.
+-spec analyse_blocks(state(), work_list()) -> state().
analyse_blocks(State, Work) ->
case get_work(Work) of
@@ -217,7 +219,7 @@ analyse_blocks(State, Work) ->
analyse_blocks(NewState, NewWork2)
end.
--spec analyse_block(label(), info(), #state{}, boolean()) -> {#state{}, [label()]}.
+-spec analyse_block(label(), info(), state(), boolean()) -> {state(), [label()]}.
analyse_block(Label, Info, State, Rewrite) ->
BB = state__bb(State, Label),
@@ -611,36 +613,32 @@ analyse_if(If, Info, Rewrite) ->
{#icode_goto{} | #icode_if{}, [{label(), info()}]}.
analyse_sane_if(If, Info, [Arg1, Arg2], [Range1, Range2], Rewrite) ->
- case normalize_name(hipe_icode:if_op(If)) of
- '>' ->
- {TrueRange2, TrueRange1, FalseRange2, FalseRange1} =
- range_inequality_propagation(Range2, Range1);
- '<' ->
- {TrueRange1, TrueRange2, FalseRange1, FalseRange2} =
- range_inequality_propagation(Range1, Range2);
- '>=' ->
- {FalseRange1, FalseRange2, TrueRange1, TrueRange2} =
+ {TrueRange1, TrueRange2, FalseRange1, FalseRange2} =
+ case normalize_name(hipe_icode:if_op(If)) of
+ '>' ->
+ {TR2, TR1, FR2, FR1} = range_inequality_propagation(Range2, Range1),
+ {TR1, TR2, FR1, FR2};
+ '<' ->
range_inequality_propagation(Range1, Range2);
- '=<' ->
- {FalseRange2, FalseRange1, TrueRange2, TrueRange1} =
- range_inequality_propagation(Range2, Range1);
- '=:=' ->
- {TrueRange1, TrueRange2, FalseRange1, FalseRange2} =
- range_equality_propagation(Range1, Range2);
- '=/=' ->
- {FalseRange1, FalseRange2, TrueRange1, TrueRange2} =
- range_equality_propagation(Range1, Range2);
- '==' ->
- {TempTrueRange1, TempTrueRange2, FalseRange1, FalseRange2} =
- range_equality_propagation(Range1, Range2),
- TrueRange1 = set_other(TempTrueRange1, other(Range1)),
- TrueRange2 = set_other(TempTrueRange2, other(Range2));
- '/=' ->
- {TempFalseRange1, TempFalseRange2, TrueRange1, TrueRange2} =
- range_equality_propagation(Range1, Range2),
- FalseRange1 = set_other(TempFalseRange1, other(Range1)),
- FalseRange2 = set_other(TempFalseRange2, other(Range2))
- end,
+ '>=' ->
+ {FR1, FR2, TR1, TR2} = range_inequality_propagation(Range1, Range2),
+ {TR1, TR2, FR1, FR2};
+ '=<' ->
+ {FR2, FR1, TR2, TR1} = range_inequality_propagation(Range2, Range1),
+ {TR1, TR2, FR1, FR2};
+ '=:=' ->
+ {TR1, TR2, FR1, FR2} = range_equality_propagation(Range1, Range2),
+ {TR1, TR2, FR1, FR2};
+ '=/=' ->
+ {FR1, FR2, TR1, TR2} = range_equality_propagation(Range1, Range2),
+ {TR1, TR2, FR1, FR2};
+ '==' ->
+ {TR1, TR2, FR1, FR2} = range_equality_propagation(Range1, Range2),
+ {set_other(TR1,other(Range1)), set_other(TR2,other(Range2)), FR1, FR2};
+ '/=' ->
+ {FR1, FR2, TR1, TR2} = range_equality_propagation(Range1, Range2),
+ {TR1, TR2, set_other(FR1,other(Range1)), set_other(FR2,other(Range2))}
+ end,
%% io:format("TR1 = ~w\nTR2 = ~w\n", [TrueRange1, TrueRange2]),
True =
case lists:all(fun range__is_none/1, [TrueRange1, TrueRange2]) of
@@ -693,26 +691,24 @@ normalize_name(Name) ->
-spec range_equality_propagation(range(), range()) ->
{range(), range(), range(), range()}.
-range_equality_propagation(Range_1, Range_2) ->
- True_range = inf(Range_1, Range_2),
- case {range(Range_1), range(Range_2)} of
- {{N,N}, {N,N}} ->
- False_range_1 = none_range(),
- False_range_2 = none_range();
- {{N1,N1}, {N2,N2}} ->
- False_range_1 = Range_1,
- False_range_2 = Range_2;
- {{N,N}, _} ->
- False_range_1 = Range_1,
- {_,False_range_2} = compare_with_integer(N, Range_2);
- {_, {N,N}} ->
- False_range_2 = Range_2,
- {_,False_range_1} = compare_with_integer(N, Range_1);
- {_, _} ->
- False_range_1 = Range_1,
- False_range_2 = Range_2
- end,
- {True_range, True_range, False_range_1, False_range_2}.
+range_equality_propagation(Range1, Range2) ->
+ TrueRange = inf(Range1, Range2),
+ {FalseRange1, FalseRange2} =
+ case {range(Range1), range(Range2)} of
+ {{N,N}, {N,N}} ->
+ {none_range(), none_range()};
+ {{N1,N1}, {N2,N2}} ->
+ {Range1, Range2};
+ {{N,N}, _} ->
+ {_,FR2} = compare_with_integer(N, Range2),
+ {Range1, FR2};
+ {_, {N,N}} ->
+ {_,FR1} = compare_with_integer(N, Range1),
+ {FR1, Range2};
+ {_, _} ->
+ {Range1, Range2}
+ end,
+ {TrueRange, TrueRange, FalseRange1, FalseRange2}.
-spec range_inequality_propagation(range(), range()) ->
{range(), range(), range(), range()}.
@@ -778,18 +774,17 @@ analyse_type(Type, Info, Rewrite) ->
TypeTest = hipe_icode:type_test(Type),
[Arg|_] = hipe_icode:type_args(Type),
OldVarRange = get_range_from_arg(Arg),
- case TypeTest of
- {integer, N} ->
- {TrueRange,FalseRange} = compare_with_integer(N,OldVarRange);
- integer ->
- TrueRange = inf(any_range(), OldVarRange),
- FalseRange = inf(none_range(), OldVarRange);
- number ->
- TrueRange = FalseRange = OldVarRange;
- _ ->
- TrueRange = inf(none_range(), OldVarRange),
- FalseRange = OldVarRange
- end,
+ {TrueRange, FalseRange} =
+ case TypeTest of
+ {integer, N} ->
+ compare_with_integer(N, OldVarRange);
+ integer ->
+ {inf(any_range(), OldVarRange), inf(none_range(), OldVarRange)};
+ number ->
+ {OldVarRange, OldVarRange};
+ _ ->
+ {inf(none_range(), OldVarRange), OldVarRange}
+ end,
TrueLabel = hipe_icode:type_true_label(Type),
FalseLabel = hipe_icode:type_false_label(Type),
TrueInfo = enter_define({Arg, TrueRange}, Info),
@@ -1200,14 +1195,12 @@ basic_type(#unsafe_update_element{}) -> not_analysed.
analyse_bs_get_integer(Size, Flags, true) ->
Signed = Flags band 4,
- if Signed =:= 0 ->
- Max = 1 bsl Size - 1,
- Min = 0;
- true ->
- Max = 1 bsl (Size-1) - 1,
- Min = -(1 bsl (Size-1))
- end,
- {Min, Max};
+ case Signed =:= 0 of
+ true ->
+ {0, inf_add(inf_bsl(1, Size), -1)}; % return {Min, Max}
+ false ->
+ {inf_inv(inf_bsl(1, Size-1)), inf_add(inf_bsl(1, Size-1), -1)}
+ end;
analyse_bs_get_integer(Size, Flags, false) when is_integer(Size),
is_integer(Flags) ->
any_r().
@@ -1652,7 +1645,7 @@ inf_bsl(Number1, Number2) when is_integer(Number1), is_integer(Number2) ->
%% State
--spec state__init(cfg(), data()) -> #state{}.
+-spec state__init(cfg(), data()) -> state().
state__init(Cfg, {MFA, ArgsFun, CallFun, FinalFun}) ->
Start = hipe_icode_cfg:start_label(Cfg),
@@ -1675,19 +1668,19 @@ state__init(Cfg, {MFA, ArgsFun, CallFun, FinalFun}) ->
lookup_fun=CallFun, result_action=FinalFun}
end.
--spec state__cfg(#state{}) -> cfg().
+-spec state__cfg(state()) -> cfg().
state__cfg(#state{cfg=Cfg}) ->
Cfg.
--spec state__bb(#state{}, label()) -> bb().
+-spec state__bb(state(), label()) -> bb().
state__bb(#state{cfg=Cfg}, Label) ->
BB = hipe_icode_cfg:bb(Cfg, Label),
true = hipe_bb:is_bb(BB), % Just an assert
BB.
--spec state__bb_add(#state{}, label(), bb()) -> #state{}.
+-spec state__bb_add(state(), label(), bb()) -> state().
state__bb_add(S=#state{cfg=Cfg}, Label, BB) ->
NewCfg = hipe_icode_cfg:bb_add(Cfg, Label, BB),
@@ -1773,14 +1766,12 @@ join_info_in([Var|Left], Info1, Info2, Acc, Changed) ->
NewTree = gb_trees:insert(Var, Val, Acc),
join_info_in(Left, Info1, Info2, NewTree, Changed);
{{value, Val1}, {value, Val2}} ->
- NewVal =
+ {NewChanged, NewVal} =
case sup(Val1, Val2) of
Val1 ->
- NewChanged = Changed,
- Val1;
+ {Changed, Val1};
Val ->
- NewChanged = true,
- Val
+ {true, Val}
end,
NewTree = gb_trees:insert(Var, NewVal, Acc),
join_info_in(Left, Info1, Info2, NewTree, NewChanged)
diff --git a/lib/hipe/icode/hipe_icode_split_arith.erl b/lib/hipe/icode/hipe_icode_split_arith.erl
index d59f9247fa..e00a13f82e 100644
--- a/lib/hipe/icode/hipe_icode_split_arith.erl
+++ b/lib/hipe/icode/hipe_icode_split_arith.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_ssa.erl b/lib/hipe/icode/hipe_icode_ssa.erl
index 2c4b6d9409..b222fbc7d2 100644
--- a/lib/hipe/icode/hipe_icode_ssa.erl
+++ b/lib/hipe/icode/hipe_icode_ssa.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_ssa_const_prop.erl b/lib/hipe/icode/hipe_icode_ssa_const_prop.erl
index f1640b1cee..4ab4d7e95d 100644
--- a/lib/hipe/icode/hipe_icode_ssa_const_prop.erl
+++ b/lib/hipe/icode/hipe_icode_ssa_const_prop.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_ssa_copy_prop.erl b/lib/hipe/icode/hipe_icode_ssa_copy_prop.erl
index 1899c09715..5e5bd2a178 100644
--- a/lib/hipe/icode/hipe_icode_ssa_copy_prop.erl
+++ b/lib/hipe/icode/hipe_icode_ssa_copy_prop.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl
index 772e30eada..7613024787 100644
--- a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl
+++ b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -313,7 +314,7 @@ node_create(Label, Pred, Succ) ->
%% tree - the tree of nodes, with labels as keys and node records as values
-record(nodes, {
- domtree :: hipe_dominators:domTree(),
+ domtree = none :: 'none' | hipe_dominators:domTree(),
labels = none :: 'none' | [icode_lbl()],
postorder = none :: 'none' | [icode_lbl()],
start_label = none :: 'none' | icode_lbl(),
@@ -389,7 +390,7 @@ update_del_red_test_set(Update) ->
%%-----------------------------------------------------------------------------
%% Main function called from the hipe_main module
--spec struct_reuse(#cfg{}) -> #cfg{}.
+-spec struct_reuse(cfg()) -> cfg().
struct_reuse(CFG) ->
%% debug_init_case_count(?SR_INSTR_TYPE),
diff --git a/lib/hipe/icode/hipe_icode_type.erl b/lib/hipe/icode/hipe_icode_type.erl
index ebeb5e2c10..794c27ebcc 100644
--- a/lib/hipe/icode/hipe_icode_type.erl
+++ b/lib/hipe/icode/hipe_icode_type.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -104,6 +105,7 @@
ret_type = [t_none()] :: [erl_types:erl_type()],
lookupfun :: call_fun(),
resultaction :: final_fun()}).
+-type state() :: #state{}.
%%-----------------------------------------------------------------------
%% The main exported function
@@ -192,7 +194,7 @@ analyse(Cfg, Data) ->
catch throw:no_input -> ok % No need to do anything since we have no input
end.
--spec safe_analyse(cfg(), data()) -> #state{}.
+-spec safe_analyse(cfg(), data()) -> state().
safe_analyse(Cfg, {MFA,_,_,_}=Data) ->
State = new_state(Cfg, Data),
@@ -362,6 +364,7 @@ call_always_fails(#icode_call{} = I, Info) ->
%% These can actually be calls too.
{erlang, halt, 0} -> false;
{erlang, halt, 1} -> false;
+ {erlang, halt, 2} -> false;
{erlang, exit, 1} -> false;
{erlang, error, 1} -> false;
{erlang, error, 2} -> false;
@@ -459,24 +462,24 @@ integer_range_inequality_propagation(Op, A1, A2, TrueLab, FalseLab, Info) ->
NonIntArg1 = t_subtract(Arg1, t_integer()),
NonIntArg2 = t_subtract(Arg2, t_integer()),
?ineq_debug("nonintargs", [NonIntArg1,NonIntArg2]),
- case t_is_none(IntArg1) or t_is_none(IntArg2) of
+ case t_is_none(IntArg1) orelse t_is_none(IntArg2) of
true ->
?ineq_debug("one is none", [IntArg1,IntArg2]),
[{TrueLab, Info}, {FalseLab, Info}];
false ->
- case Op of
- '>=' ->
- {FalseArg1, FalseArg2, TrueArg1, TrueArg2} =
- integer_range_less_then_propagator(IntArg1, IntArg2);
- '>' ->
- {TrueArg2, TrueArg1, FalseArg2, FalseArg1} =
- integer_range_less_then_propagator(IntArg2, IntArg1);
- '<' ->
- {TrueArg1, TrueArg2, FalseArg1, FalseArg2} =
- integer_range_less_then_propagator(IntArg1, IntArg2);
- '=<' ->
- {FalseArg2, FalseArg1, TrueArg2, TrueArg1} =
- integer_range_less_then_propagator(IntArg2, IntArg1)
+ {TrueArg1, TrueArg2, FalseArg1, FalseArg2} =
+ case Op of
+ '>=' ->
+ {FA1, FA2, TA1, TA2} = int_range_lt_propagator(IntArg1, IntArg2),
+ {TA1, TA2, FA1, FA2};
+ '>' ->
+ {TA2, TA1, FA2, FA1} = int_range_lt_propagator(IntArg2, IntArg1),
+ {TA1, TA2, FA1, FA2};
+ '<' ->
+ int_range_lt_propagator(IntArg1, IntArg2);
+ '=<' ->
+ {FA2, FA1, TA2, TA1} = int_range_lt_propagator(IntArg2, IntArg1),
+ {TA1, TA2, FA1, FA2}
end,
?ineq_debug("int res", [TrueArg1, TrueArg2, FalseArg1, FalseArg2]),
False = {FalseLab, enter(A1, t_sup(FalseArg1, NonIntArg1),
@@ -486,7 +489,7 @@ integer_range_inequality_propagation(Op, A1, A2, TrueLab, FalseLab, Info) ->
[True, False]
end.
-integer_range_less_then_propagator(IntArg1, IntArg2) ->
+int_range_lt_propagator(IntArg1, IntArg2) ->
Min1 = number_min(IntArg1),
Max1 = number_max(IntArg1),
Min2 = number_min(IntArg2),
diff --git a/lib/hipe/icode/hipe_icode_type.hrl b/lib/hipe/icode/hipe_icode_type.hrl
index dd69c1e8b2..466e157646 100644
--- a/lib/hipe/icode/hipe_icode_type.hrl
+++ b/lib/hipe/icode/hipe_icode_type.hrl
@@ -1,18 +1,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/llvm/Makefile b/lib/hipe/llvm/Makefile
index 92f378924a..88016a7d8b 100644
--- a/lib/hipe/llvm/Makefile
+++ b/lib/hipe/llvm/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2014. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -39,20 +40,19 @@ RELSYSDIR = $(RELEASE_PATH)/lib/hipe-$(VSN)
# Target Specs
# ----------------------------------------------------
ifdef HIPE_ENABLED
-HIPE_MODULES = hipe_rtl_to_llvm \
+HIPE_MODULES = elf_format \
hipe_llvm \
- elf_format \
+ hipe_llvm_liveness \
hipe_llvm_main \
hipe_llvm_merge \
- hipe_llvm_liveness
+ hipe_rtl_to_llvm
else
HIPE_MODULES =
endif
MODULES = $(HIPE_MODULES)
-HRL_FILES= elf_format.hrl elf32_format.hrl elf64_format.hrl \
- hipe_llvm_arch.hrl
+HRL_FILES= elf_format.hrl elf32_format.hrl elf64_format.hrl hipe_llvm_arch.hrl
ERL_FILES= $(MODULES:%=%.erl)
TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
@@ -70,7 +70,7 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
include ../native.mk
-ERL_COMPILE_FLAGS += +inline #+warn_missing_spec
+ERL_COMPILE_FLAGS += -Werror +inline +warn_export_vars #+warn_missing_spec
# if in 32 bit backend define BIT32 symbol
ARCH = $(shell echo $(TARGET) | sed 's/^\(x86_64\)-.*/64bit/')
@@ -107,3 +107,11 @@ release_spec: opt
$(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
release_docs_spec:
+
+$(EBIN)/elf_format.beam: elf_format.hrl elf32_format.hrl elf64_format.hrl
+$(EBIN)/hipe_llvm_main.beam: ../../kernel/src/hipe_ext_format.hrl \
+ hipe_llvm_arch.hrl elf_format.hrl elf32_format.hrl elf64_format.hrl
+$(EBIN)/hipe_llvm_merge.beam: ../../kernel/src/hipe_ext_format.hrl \
+ hipe_llvm_arch.hrl ../rtl/hipe_literals.hrl ../main/hipe.hrl
+$(EBIN)/hipe_rtl_to_llvm.beam: ../rtl/hipe_rtl.hrl ../rtl/hipe_literals.hrl \
+ hipe_llvm_arch.hrl
diff --git a/lib/hipe/llvm/elf_format.erl b/lib/hipe/llvm/elf_format.erl
index 260da9b5e6..8cf6ea6250 100644
--- a/lib/hipe/llvm/elf_format.erl
+++ b/lib/hipe/llvm/elf_format.erl
@@ -13,21 +13,20 @@
-module(elf_format).
--export([get_tab_entries/1,
- %% Relocations
- get_rodata_relocs/1,
- get_text_relocs/1,
+-export([%% Relocations
extract_rela/2,
- get_rela_addends/1,
%% Note
extract_note/2,
%% Executable code
extract_text/1,
%% GCC Exception Table
- get_exn_handlers/1,
- %% Misc.
- set_architecture_flag/1,
- is64bit/0
+ get_exn_handlers/1,
+ %% Symbols
+ elf_symbols/1,
+ %% Sections
+ section_contents/2,
+ %% Main interface
+ read/1
]).
-include("elf_format.hrl").
@@ -36,27 +35,57 @@
%% Types
%%------------------------------------------------------------------------------
--type elf() :: binary().
-
--type lp() :: non_neg_integer(). % landing pad
--type num() :: non_neg_integer().
--type index() :: non_neg_integer().
--type offset() :: non_neg_integer().
--type size() :: non_neg_integer().
--type start() :: non_neg_integer().
-
--type info() :: index().
--type nameoff() :: offset().
--type valueoff() :: offset().
-
--type name() :: string().
--type name_size() :: {name(), size()}.
--type name_sizes() :: [name_size()].
+-export_type([elf/0
+ ,addend/0
+ ,bitflags/0
+ ,name/0
+ ,offset/0
+ ,reloc_type/0
+ ,shdr_type/0
+ ,size/0
+ ,sym_bind/0
+ ,sym_type/0
+ ,valueoff/0
+ ]).
+
+-type bitflags() :: non_neg_integer().
+-type index() :: non_neg_integer().
+-type lp() :: non_neg_integer(). % landing pad
+-type num() :: non_neg_integer().
+-type offset() :: non_neg_integer().
+-type size() :: non_neg_integer().
+-type start() :: non_neg_integer().
+
+-type addend() :: integer() | undefined.
+-type name() :: string().
+-type shdr_type() :: 'null' | 'progbits' | 'symtab' | 'strtab' | 'rela'
+ | 'hash' | 'dynamic' | 'note' | 'nobits' | 'rel' | 'shlib'
+ | 'dynsym' | {os, ?SHT_LOOS..?SHT_HIOS}
+ | {proc, ?SHT_LOPROC..?SHT_HIPROC}.
+-type sym_bind() :: 'local' | 'global' | 'weak' | {os, ?STB_LOOS..?STB_HIOS}
+ | {proc, ?STB_LOPROC..?STB_HIPROC}.
+-type sym_type() :: 'notype' | 'object' | 'func' | 'section' | 'file'
+ | {os, ?STT_LOOS..?STT_HIOS}
+ | {proc, ?STT_LOPROC..?STT_HIPROC}.
+-type valueoff() :: offset().
+
+-ifdef(BIT32). % 386
+-type reloc_type() :: '32' | 'pc32'.
+-else. % X86_64
+-type reloc_type() :: '64' | 'pc32' | '32'.
+-endif.
%%------------------------------------------------------------------------------
%% Abstract Data Types and Accessors for ELF Structures.
%%------------------------------------------------------------------------------
+-record(elf, {file :: binary()
+ ,sections :: [elf_shdr()]
+ ,sec_nam :: #{string() => elf_shdr()}
+ ,symbols :: undefined | [elf_sym()]
+ }).
+-opaque elf() :: #elf{}.
+
%% File header
-record(elf_ehdr, {ident, % ELF identification
type, % Object file type
@@ -85,42 +114,6 @@
}).
%% -type elf_ehdr_ident() :: #elf_ehdr_ident{}.
-%% Section header entries
--record(elf_shdr, {name, % Section name
- type, % Section type
- flags, % Section attributes
- addr, % Virtual address in memory
- offset :: offset(), % Offset in file
- size :: size(), % Size of section
- link, % Link to other section
- info, % Miscellaneous information
- addralign, % Address align boundary
- entsize % Size of entries, if section has table
- }).
-%% -type elf_shdr() :: #elf_shdr{}.
-
-%% Symbol table entries
--record(elf_sym, {name :: nameoff(), % Symbol name
- info, % Type and Binding attributes
- other, % Reserved
- shndx, % Section table index
- value :: valueoff(), % Symbol value
- size :: size() % Size of object
- }).
--type elf_sym() :: #elf_sym{}.
-
-%% Relocations
--record(elf_rel, {r_offset :: offset(), % Address of reference
- r_info :: info() % Symbol index and type of relocation
- }).
--type elf_rel() :: #elf_rel{}.
-
--record(elf_rela, {r_offset :: offset(), % Address of reference
- r_info :: info(), % Symbol index and type of relocation
- r_addend :: offset() % Constant part of expression
- }).
--type elf_rela() :: #elf_rela{}.
-
%% %% Program header table
%% -record(elf_phdr, {type, % Type of segment
%% flags, % Segment attributes
@@ -199,44 +192,19 @@ mk_shdr(Name, Type, Flags, Addr, Offset, Size, Link, Info, AddrAlign, EntSize) -
%%%-------------------------
%%% Symbol Table Entries
%%%-------------------------
-mk_sym(Name, Info, Other, Shndx, Value, Size) ->
- #elf_sym{name = Name, info = Info, other = Other,
- shndx = Shndx, value = Value, size = Size}.
-
--spec sym_name(elf_sym()) -> nameoff().
-sym_name(#elf_sym{name = Name}) -> Name.
+mk_sym(Name, Bind, Type, Section, Value, Size) ->
+ #elf_sym{name = Name, bind = Bind, type = Type,
+ section = Section, value = Value, size = Size}.
+%% -spec sym_name(elf_sym()) -> string().
+%% sym_name(#elf_sym{name = Name}) -> Name.
+%%
%% -spec sym_value(elf_sym()) -> valueoff().
%% sym_value(#elf_sym{value = Value}) -> Value.
%%
%% -spec sym_size(elf_sym()) -> size().
%% sym_size(#elf_sym{size = Size}) -> Size.
-%%%-------------------------
-%%% Relocations
-%%%-------------------------
--spec mk_rel(offset(), info()) -> elf_rel().
-mk_rel(Offset, Info) ->
- #elf_rel{r_offset = Offset, r_info = Info}.
-
-%% The following two functions capitalize on the fact that the two kinds of
-%% relocation records (for 32- and 64-bit architectures have similar structure.
-
--spec r_offset(elf_rel() | elf_rela()) -> offset().
-r_offset(#elf_rel{r_offset = Offset}) -> Offset;
-r_offset(#elf_rela{r_offset = Offset}) -> Offset.
-
--spec r_info(elf_rel() | elf_rela()) -> info().
-r_info(#elf_rel{r_info = Info}) -> Info;
-r_info(#elf_rela{r_info = Info}) -> Info.
-
--spec mk_rela(offset(), info(), offset()) -> elf_rela().
-mk_rela(Offset, Info, Addend) ->
- #elf_rela{r_offset = Offset, r_info = Info, r_addend = Addend}.
-
--spec rela_addend(elf_rela()) -> offset().
-rela_addend(#elf_rela{r_addend = Addend}) -> Addend.
-
%% %%%-------------------------
%% %%% GCC exception table
%% %%%-------------------------
@@ -263,15 +231,30 @@ mk_gccexntab_callsite(Start, Size, LP, Action) ->
%% gccexntab_callsite_lp(#elf_gccexntab_callsite{lp = LP}) -> LP.
%%------------------------------------------------------------------------------
+%% Main interface function
+%%------------------------------------------------------------------------------
+
+%% @doc Parses an ELF file.
+-spec read(binary()) -> elf().
+read(ElfBin) ->
+ Header = extract_header(ElfBin),
+ [_UndefinedSec|Sections] = extract_shdrtab(ElfBin, Header),
+ SecNam = maps:from_list(
+ [{Name, Sec} || Sec = #elf_shdr{name=Name} <- Sections]),
+ Elf0 = #elf{file=ElfBin, sections=Sections, sec_nam=SecNam},
+ [_UndefinedSym|Symbols] = extract_symtab(Elf0, extract_strtab(Elf0)),
+ Elf0#elf{symbols=Symbols}.
+
+%%------------------------------------------------------------------------------
%% Functions to manipulate the ELF File Header
%%------------------------------------------------------------------------------
%% @doc Extracts the File Header from an ELF formatted object file. Also sets
%% the ELF class variable in the process dictionary (used by many functions
%% in this and hipe_llvm_main modules).
--spec extract_header(elf()) -> elf_ehdr().
-extract_header(Elf) ->
- Ehdr_bin = get_binary_segment(Elf, 0, ?ELF_EHDR_SIZE),
+-spec extract_header(binary()) -> elf_ehdr().
+extract_header(ElfBin) ->
+ Ehdr_bin = get_binary_segment(ElfBin, 0, ?ELF_EHDR_SIZE),
<< %% Structural pattern matching on fields.
Ident_bin:?E_IDENT_SIZE/binary,
Type:?bits(?E_TYPE_SIZE)/integer-little,
@@ -300,19 +283,28 @@ extract_header(Elf) ->
%% Functions to manipulate Section Header Entries
%%------------------------------------------------------------------------------
+-type shdrtab() :: [elf_shdr()].
+
%% @doc Extracts the Section Header Table from an ELF formated Object File.
-extract_shdrtab(Elf) ->
- %% Extract File Header to get info about Section Header Offset (in bytes),
- %% Entry Size (in bytes) and Number of entries
- #elf_ehdr{shoff = ShOff, shentsize = ShEntsize, shnum = ShNum} =
- extract_header(Elf),
+-spec extract_shdrtab(binary(), elf_ehdr()) -> shdrtab().
+extract_shdrtab(ElfBin, #elf_ehdr{shoff=ShOff, shentsize=?ELF_SHDRENTRY_SIZE,
+ shnum=ShNum, shstrndx=ShStrNdx}) ->
%% Get actual Section header table (binary)
- ShdrBin = get_binary_segment(Elf, ShOff, ShNum * ShEntsize),
- get_shdrtab_entries(ShdrBin, []).
-
-get_shdrtab_entries(<<>>, Acc) ->
- lists:reverse(Acc);
-get_shdrtab_entries(ShdrBin, Acc) ->
+ ShdrBin = get_binary_segment(ElfBin, ShOff, ShNum * ?ELF_SHDRENTRY_SIZE),
+ %% We need to lookup the offset and size of the section header string table
+ %% before we can fully parse the section table. We compute its offset and
+ %% extract the fields we need here.
+ ShStrEntryOffset = ShStrNdx * ?ELF_SHDRENTRY_SIZE,
+ <<_:ShStrEntryOffset/binary, _:?SH_NAME_SIZE/binary,
+ _:?SH_TYPE_SIZE/binary, _:?SH_FLAGS_SIZE/binary, _:?SH_ADDR_SIZE/binary,
+ ShStrOffset:?bits(?SH_OFFSET_SIZE)/little,
+ ShStrSize:?bits(?SH_SIZE_SIZE)/little,
+ _/binary>> = ShdrBin,
+ ShStrTab = parse_strtab(get_binary_segment(ElfBin, ShStrOffset, ShStrSize)),
+ get_shdrtab_entries(ShdrBin, ShStrTab).
+
+get_shdrtab_entries(<<>>, _ShStrTab) -> [];
+get_shdrtab_entries(ShdrTab, ShStrTab) ->
<<%% Structural pattern matching on fields.
Name:?bits(?SH_NAME_SIZE)/integer-little,
Type:?bits(?SH_TYPE_SIZE)/integer-little,
@@ -324,205 +316,166 @@ get_shdrtab_entries(ShdrBin, Acc) ->
Info:?bits(?SH_INFO_SIZE)/integer-little,
Addralign:?bits(?SH_ADDRALIGN_SIZE)/integer-little,
Entsize:?bits(?SH_ENTSIZE_SIZE)/integer-little,
- MoreShdrE/binary
- >> = ShdrBin,
- ShdrE = mk_shdr(Name, Type, Flags, Addr, Offset,
- Size, Link, Info, Addralign, Entsize),
- get_shdrtab_entries(MoreShdrE, [ShdrE | Acc]).
-
-%% @doc Extracts a specific Entry of a Section Header Table. This function
-%% takes as argument the Section Header Table (`SHdrTab') and the entry's
-%% serial number (`EntryNum') and returns the entry (`shdr').
-get_shdrtab_entry(SHdrTab, EntryNum) ->
- lists:nth(EntryNum + 1, SHdrTab).
-
-%%------------------------------------------------------------------------------
-%% Functions to manipulate Section Header String Table
-%%------------------------------------------------------------------------------
-
-%% @doc Extracts the Section Header String Table. This section is not a known
-%% ELF Object File section. It is just a "hidden" table storing the
-%% names of all sections that exist in current object file.
--spec extract_shstrtab(elf()) -> [name()].
-extract_shstrtab(Elf) ->
- %% Extract Section Name String Table Index
- #elf_ehdr{shstrndx = ShStrNdx} = extract_header(Elf),
- ShHdrTab = extract_shdrtab(Elf),
- %% Extract Section header entry and get actual Section-header String Table
- #elf_shdr{offset = ShStrOffset, size = ShStrSize} =
- get_shdrtab_entry(ShHdrTab, ShStrNdx),
- case get_binary_segment(Elf, ShStrOffset, ShStrSize) of
- <<>> -> %% Segment empty
- [];
- ShStrTab -> %% Convert to string table
- [Name || {Name, _Size} <- get_names(ShStrTab)]
- end.
-
-%%------------------------------------------------------------------------------
-
--spec get_tab_entries(elf()) -> [{name(), valueoff(), size()}].
-get_tab_entries(Elf) ->
- SymTab = extract_symtab(Elf),
- Ts = [{Name, Value, Size div ?ELF_XWORD_SIZE}
- || #elf_sym{name = Name, value = Value, size = Size} <- SymTab,
- Name =/= 0],
- {NameIndices, ValueOffs, Sizes} = lists:unzip3(Ts),
- %% Find the names of the symbols.
- %% Get string table entries ([{Name, Offset in strtab section}]). Keep only
- %% relevant entries:
- StrTab = extract_strtab(Elf),
- Relevant = [get_strtab_entry(StrTab, Off) || Off <- NameIndices],
- %% Zip back to {Name, ValueOff, Size}
- lists:zip3(Relevant, ValueOffs, Sizes).
+ Rest/binary
+ >> = ShdrTab,
+ Entry = mk_shdr(get_strtab_entry(Name, ShStrTab), decode_shdr_type(Type),
+ Flags, Addr, Offset, Size, Link, Info, Addralign, Entsize),
+ [Entry | get_shdrtab_entries(Rest, ShStrTab)].
+
+decode_shdr_type(?SHT_NULL) -> 'null';
+decode_shdr_type(?SHT_PROGBITS) -> 'progbits';
+decode_shdr_type(?SHT_SYMTAB) -> 'symtab';
+decode_shdr_type(?SHT_STRTAB) -> 'strtab';
+decode_shdr_type(?SHT_RELA) -> 'rela';
+decode_shdr_type(?SHT_HASH) -> 'hash'; %unused
+decode_shdr_type(?SHT_DYNAMIC) -> 'dynamic'; %unused
+decode_shdr_type(?SHT_NOTE) -> 'note'; %unused
+decode_shdr_type(?SHT_NOBITS) -> 'nobits';
+decode_shdr_type(?SHT_REL) -> 'rel';
+decode_shdr_type(?SHT_SHLIB) -> 'shlib'; %unused
+decode_shdr_type(?SHT_DYNSYM) -> 'dynsym'; %unused
+decode_shdr_type(OS) when ?SHT_LOOS =< OS, OS =< ?SHT_HIOS -> {os, OS};
+decode_shdr_type(Proc) when ?SHT_LOPROC =< Proc, Proc =< ?SHT_HIPROC ->
+ {proc, Proc}.
+
+-spec elf_section(non_neg_integer(), elf()) -> undefined | abs | elf_shdr().
+elf_section(0, #elf{}) -> undefined;
+elf_section(?SHN_ABS, #elf{}) -> abs;
+elf_section(Index, #elf{sections=SecIdx}) ->
+ lists:nth(Index, SecIdx).
+
+%% Reads the contents of a section from an object
+-spec section_contents(elf_shdr(), elf()) -> binary().
+section_contents(#elf_shdr{offset=Offset, size=Size}, #elf{file=ElfBin}) ->
+ get_binary_segment(ElfBin, Offset, Size).
%%------------------------------------------------------------------------------
%% Functions to manipulate Symbol Table
%%------------------------------------------------------------------------------
%% @doc Function that extracts Symbol Table from an ELF Object file.
-extract_symtab(Elf) ->
- Symtab_bin = extract_segment_by_name(Elf, ?SYMTAB),
- get_symtab_entries(Symtab_bin, []).
-
-get_symtab_entries(<<>>, Acc) ->
- lists:reverse(Acc);
-get_symtab_entries(Symtab_bin, Acc) ->
- <<SymE_bin:?ELF_SYM_SIZE/binary, MoreSymE/binary>> = Symtab_bin,
- case is64bit() of
- true ->
- <<%% Structural pattern matching on fields.
- Name:?bits(?ST_NAME_SIZE)/integer-little,
- Info:?bits(?ST_INFO_SIZE)/integer-little,
- Other:?bits(?ST_OTHER_SIZE)/integer-little,
- Shndx:?bits(?ST_SHNDX_SIZE)/integer-little,
- Value:?bits(?ST_VALUE_SIZE)/integer-little,
- Size:?bits(?ST_SIZE_SIZE)/integer-little
- >> = SymE_bin;
- false ->
- << %% Same fields in different order:
- Name:?bits(?ST_NAME_SIZE)/integer-little,
- Value:?bits(?ST_VALUE_SIZE)/integer-little,
- Size:?bits(?ST_SIZE_SIZE)/integer-little,
- Info:?bits(?ST_INFO_SIZE)/integer-little,
- Other:?bits(?ST_OTHER_SIZE)/integer-little,
- Shndx:?bits(?ST_SHNDX_SIZE)/integer-little
- >> = SymE_bin
- end,
- SymE = mk_sym(Name, Info, Other, Shndx, Value, Size),
- get_symtab_entries(MoreSymE, [SymE | Acc]).
-
-%% @doc Extracts a specific entry from the Symbol Table (as binary).
-%% This function takes as arguments the Symbol Table (`SymTab')
-%% and the entry's serial number and returns that entry (`sym').
-get_symtab_entry(SymTab, EntryNum) ->
- lists:nth(EntryNum + 1, SymTab).
+extract_symtab(Elf, StrTab) ->
+ Symtab = extract_segment_by_name(Elf, ?SYMTAB),
+ [parse_sym(Sym, Elf, StrTab) || <<Sym:?ELF_SYM_SIZE/binary>> <= Symtab].
+
+-ifdef(BIT32).
+parse_sym(<<%% Structural pattern matching on fields.
+ Name:?bits(?ST_NAME_SIZE)/integer-little,
+ Value:?bits(?ST_VALUE_SIZE)/integer-little,
+ Size:?bits(?ST_SIZE_SIZE)/integer-little,
+ Info:?bits(?ST_INFO_SIZE)/integer-little,
+ _Other:?bits(?ST_OTHER_SIZE)/integer-little,
+ Shndx:?bits(?ST_SHNDX_SIZE)/integer-little>>,
+ Elf, StrTab) ->
+ mk_sym(get_strtab_entry(Name, StrTab), decode_symbol_bind(?ELF_ST_BIND(Info)),
+ decode_symbol_type(?ELF_ST_TYPE(Info)), elf_section(Shndx, Elf), Value,
+ Size).
+-else.
+parse_sym(<<%% Same fields in different order:
+ Name:?bits(?ST_NAME_SIZE)/integer-little,
+ Info:?bits(?ST_INFO_SIZE)/integer-little,
+ _Other:?bits(?ST_OTHER_SIZE)/integer-little,
+ Shndx:?bits(?ST_SHNDX_SIZE)/integer-little,
+ Value:?bits(?ST_VALUE_SIZE)/integer-little,
+ Size:?bits(?ST_SIZE_SIZE)/integer-little>>,
+ Elf, StrTab) ->
+ mk_sym(get_strtab_entry(Name, StrTab), decode_symbol_bind(?ELF_ST_BIND(Info)),
+ decode_symbol_type(?ELF_ST_TYPE(Info)), elf_section(Shndx, Elf), Value,
+ Size).
+-endif.
+
+decode_symbol_bind(?STB_LOCAL) -> 'local';
+decode_symbol_bind(?STB_GLOBAL) -> 'global';
+decode_symbol_bind(?STB_WEAK) -> 'weak'; %unused
+decode_symbol_bind(OS) when ?STB_LOOS =< OS, OS =< ?STB_HIOS -> {os, OS};
+decode_symbol_bind(Proc) when ?STB_LOPROC =< Proc, Proc =< ?STB_HIPROC ->
+ {proc, Proc}.
+
+decode_symbol_type(?STT_NOTYPE) -> 'notype';
+decode_symbol_type(?STT_OBJECT) -> 'object';
+decode_symbol_type(?STT_FUNC) -> 'func';
+decode_symbol_type(?STT_SECTION) -> 'section';
+decode_symbol_type(?STT_FILE) -> 'file';
+decode_symbol_type(OS) when ?STT_LOOS =< OS, OS =< ?STT_HIOS -> {os, OS};
+decode_symbol_type(Proc) when ?STT_LOPROC =< Proc, Proc =< ?STT_HIPROC ->
+ {proc, Proc}.
+
+%% @doc Extracts a specific entry from the Symbol Table.
+-spec elf_symbol(0, elf()) -> undefined;
+ (pos_integer(), elf()) -> elf_sym().
+elf_symbol(0, #elf{}) -> undefined;
+elf_symbol(Index, #elf{symbols=Symbols}) -> lists:nth(Index, Symbols).
+
+-spec elf_symbols(elf()) -> [elf_sym()].
+elf_symbols(#elf{symbols=Symbols}) -> Symbols.
%%------------------------------------------------------------------------------
%% Functions to manipulate String Table
%%------------------------------------------------------------------------------
+%% ADT: get_strtab_entry/1 must be used to consume this type.
+-type strtab() :: binary().
+
%% @doc Extracts String Table from an ELF formated Object File.
--spec extract_strtab(elf()) -> [{string(), offset()}].
+-spec extract_strtab(elf()) -> strtab().
extract_strtab(Elf) ->
- Strtab_bin = extract_segment_by_name(Elf, ?STRTAB),
- NamesSizes = get_names(Strtab_bin),
- make_offsets(NamesSizes).
-
-%% @doc Returns the name of the symbol at the given offset. The string table
-%% contains entries of the form {Name, Offset}. If no such offset exists
-%% returns the empty string (`""').
-%% XXX: There might be a bug here because of the "compact" saving the ELF
-%% format uses: e.g. only stores ".rela.text" for ".rela.text" and ".text".
-get_strtab_entry(Strtab, Offset) ->
- case lists:keyfind(Offset, 2, Strtab) of
- {Name, Offset} -> Name;
- false -> ""
- end.
+ parse_strtab(extract_segment_by_name(Elf, ?STRTAB)).
+
+-spec parse_strtab(binary()) -> strtab().
+parse_strtab(StrTabSectionBin) -> StrTabSectionBin.
+
+%% @doc Returns the name of the symbol at the given offset.
+-spec get_strtab_entry(non_neg_integer(), strtab()) -> string().
+get_strtab_entry(Offset, StrTab) ->
+ <<_:Offset/binary, StrBin/binary>> = StrTab,
+ bin_get_string(StrBin).
+
+%% @doc Extracts a null-terminated string from a binary.
+-spec bin_get_string(binary()) -> string().
+%% FIXME: No regard for encoding (just happens to work for ASCII and Latin-1)
+bin_get_string(<<0, _/binary>>) -> [];
+bin_get_string(<<Char, Rest/binary>>) -> [Char|bin_get_string(Rest)].
%%------------------------------------------------------------------------------
%% Functions to manipulate Relocations
%%------------------------------------------------------------------------------
-%% @doc This function gets as argument an ELF binary file and returns a list
-%% with all .rela.rodata labels (i.e. constants and literals in code)
-%% or an empty list if no ".rela.rodata" section exists in code.
--spec get_rodata_relocs(elf()) -> [offset()].
-get_rodata_relocs(Elf) ->
- case is64bit() of
- true ->
- %% Only care about the addends (== offsets):
- get_rela_addends(extract_rela(Elf, ?RODATA));
- false ->
- %% Find offsets hardcoded in ".rodata" entry
- %%XXX: Treat all 0s as padding and skip them!
- [SkipPadding || SkipPadding <- extract_rodata(Elf), SkipPadding =/= 0]
- end.
-
--spec get_rela_addends([elf_rela()]) -> [offset()].
-get_rela_addends(RelaEntries) ->
- [rela_addend(E) || E <- RelaEntries].
-
-%% @doc Extract a list of the form `[{SymbolName, Offset}]' with all relocatable
-%% symbols and their offsets in the code from the ".text" section.
--spec get_text_relocs(elf()) -> [{name(), offset()}].
-get_text_relocs(Elf) ->
- %% Only care about the symbol table index and the offset:
- NameOffsetTemp = [{?ELF_R_SYM(r_info(E)), r_offset(E)}
- || E <- extract_rela(Elf, ?TEXT)],
- {NameIndices, ActualOffsets} = lists:unzip(NameOffsetTemp),
- %% Find the names of the symbols:
- %%
- %% Get those symbol table entries that are related to Text relocs:
- Symtab = extract_symtab(Elf),
- SymtabEs = [get_symtab_entry(Symtab, Index) || Index <- NameIndices],
- %XXX: not zero-indexed!
- %% Symbol table entries contain the offset of the name of the symbol in
- %% String Table:
- SymtabEs2 = [sym_name(E) || E <- SymtabEs], %XXX: Do we need to sort SymtabE?
- %% Get string table entries ([{Name, Offset in strtab section}]). Keep only
- %% relevant entries:
- Strtab = extract_strtab(Elf),
- Relevant = [get_strtab_entry(Strtab, Off) || Off <- SymtabEs2],
- %% Zip back with actual offsets:
- lists:zip(Relevant, ActualOffsets).
-
%% @doc Extract the Relocations segment for section `Name' (that is passed
%% as second argument) from an ELF formated Object file binary.
--spec extract_rela(elf(), name()) -> [elf_rel() | elf_rela()].
+-spec extract_rela(elf(), name()) -> [elf_rel()].
+
+-ifdef(BIT32).
extract_rela(Elf, Name) ->
- SegName =
- case is64bit() of
- true -> ?RELA(Name); % ELF-64 uses ".rela"
- false -> ?REL(Name) % ...while ELF-32 uses ".rel"
- end,
- Rela_bin = extract_segment_by_name(Elf, SegName),
- get_rela_entries(Rela_bin, []).
-
-get_rela_entries(<<>>, Acc) ->
- lists:reverse(Acc);
-get_rela_entries(Bin, Acc) ->
- E = case is64bit() of
- true ->
- <<%% Structural pattern matching on fields of a Rela Entry.
- Offset:?bits(?R_OFFSET_SIZE)/integer-little,
- Info:?bits(?R_INFO_SIZE)/integer-little,
- Addend:?bits(?R_ADDEND_SIZE)/integer-little,
- Rest/binary
- >> = Bin,
- mk_rela(Offset, Info, Addend);
- false ->
- <<%% Structural pattern matching on fields of a Rel Entry.
- Offset:?bits(?R_OFFSET_SIZE)/integer-little,
- Info:?bits(?R_INFO_SIZE)/integer-little,
- Rest/binary
- >> = Bin,
- mk_rel(Offset, Info)
- end,
- get_rela_entries(Rest, [E | Acc]).
-
-%% %% @doc Extract the `EntryNum' (serial number) Relocation Entry.
-%% get_rela_entry(Rela, EntryNum) ->
-%% lists:nth(EntryNum + 1, Rela).
+ SecData = extract_segment_by_name(Elf, Name),
+ [#elf_rel{offset=Offset, symbol=elf_symbol(?ELF_R_SYM(Info), Elf),
+ type=decode_reloc_type(?ELF_R_TYPE(Info)),
+ addend=read_implicit_addend(Offset, SecData)}
+ || <<Offset:?bits(?R_OFFSET_SIZE)/little,
+ Info:?bits(?R_INFO_SIZE)/little % 386 uses ".rel"
+ >> <= extract_segment_by_name(Elf, ?REL(Name))].
+
+%% The only types HiPE knows how to patch
+decode_reloc_type(1) -> '32';
+decode_reloc_type(2) -> 'pc32'.
+
+read_implicit_addend(Offset, Section) ->
+ %% All x86 relocation types uses 'word32' relocation fields; i.e. 32-bit LE.
+ <<_:Offset/binary, Addend:32/signed-little, _/binary>> = Section,
+ Addend.
+
+-else. %% BIT32
+extract_rela(Elf, Name) ->
+ [#elf_rel{offset=Offset, symbol=elf_symbol(?ELF_R_SYM(Info), Elf),
+ type=decode_reloc_type(?ELF_R_TYPE(Info)), addend=Addend}
+ || <<Offset:?bits(?R_OFFSET_SIZE)/little,
+ Info:?bits(?R_INFO_SIZE)/little,
+ Addend:?bits(?R_ADDEND_SIZE)/signed-little % X86_64 uses ".rela"
+ >> <= extract_segment_by_name(Elf, ?RELA(Name))].
+
+decode_reloc_type(1) -> '64';
+decode_reloc_type(2) -> 'pc32';
+decode_reloc_type(10) -> '32'.
+-endif. %% BIT32
%%------------------------------------------------------------------------------
%% Functions to manipulate Executable Code segment
@@ -615,19 +568,6 @@ get_gccexntab_callsites(CSTab, Acc) ->
get_gccexntab_callsites(More, [GccCS | Acc]).
%%------------------------------------------------------------------------------
-%% Functions to manipulate Read-only Data (.rodata)
-%%------------------------------------------------------------------------------
-extract_rodata(Elf) ->
- Rodata_bin = extract_segment_by_name(Elf, ?RODATA),
- get_rodata_entries(Rodata_bin, []).
-
-get_rodata_entries(<<>>, Acc) ->
- lists:reverse(Acc);
-get_rodata_entries(Rodata_bin, Acc) ->
- <<Num:?bits(?ELF_ADDR_SIZE)/integer-little, More/binary>> = Rodata_bin,
- get_rodata_entries(More, [Num | Acc]).
-
-%%------------------------------------------------------------------------------
%% Helper functions
%%------------------------------------------------------------------------------
@@ -647,107 +587,15 @@ get_binary_segment(Bin, Offset, Size) ->
%% There are handy macros defined in elf_format.hrl for all Standard
%% Section Names.
-spec extract_segment_by_name(elf(), string()) -> binary().
-extract_segment_by_name(Elf, SectionName) ->
- %% Extract Section Header Table and Section Header String Table from binary
- SHdrTable = extract_shdrtab(Elf),
- Names = extract_shstrtab(Elf),
- %% Zip to a list of (Name,ShdrE)
- [_Zero | ShdrEs] = lists:keysort(2, SHdrTable), % Skip first entry (zeros).
- L = lists:zip(Names, ShdrEs),
+extract_segment_by_name(#elf{file=ElfBin, sec_nam=SecNam}, SectionName) ->
%% Find Section Header Table entry by name
- case lists:keyfind(SectionName, 1, L) of
- {SectionName, ShdrE} -> %% Note: Same name.
- #elf_shdr{offset = Offset, size = Size} = ShdrE,
- get_binary_segment(Elf, Offset, Size);
- false -> %% Not found.
+ case SecNam of
+ #{SectionName := #elf_shdr{offset=Offset, size=Size}} ->
+ get_binary_segment(ElfBin, Offset, Size);
+ #{} -> %% Not found.
<<>>
end.
-%% @doc Extracts a list of strings with (zero-separated) names from a binary.
-%% Returns tuples of `{Name, Size}'.
-%% XXX: Skip trailing 0.
--spec get_names(<<_:8,_:_*8>>) -> name_sizes().
-get_names(<<0, Bin/binary>>) ->
- NamesSizes = get_names(Bin, []),
- fix_names(NamesSizes, []).
-
-get_names(<<>>, Acc) ->
- lists:reverse(Acc);
-get_names(Bin, Acc) ->
- {Name, MoreNames} = bin_get_string(Bin),
- get_names(MoreNames, [{Name, length(Name)} | Acc]).
-
-%% @doc Fix names:
-%% e.g. If ".rela.text" exists, ".text" does not. Same goes for
-%% ".rel.text". In that way, the Section Header String Table is more
-%% compact. Add ".text" just *before* the corresponding rela-field,
-%% etc.
--spec fix_names(name_sizes(), name_sizes()) -> name_sizes().
-fix_names([], Acc) ->
- lists:reverse(Acc);
-fix_names([{Name, Size}=T | Names], Acc) ->
- case is64bit() of
- true ->
- case string:str(Name, ".rela") =:= 1 of
- true -> %% Name starts with ".rela":
- Section = string:substr(Name, 6),
- fix_names(Names, [{Section, Size - 5}
- | [T | Acc]]); % XXX: Is order ok? (".text"
- % always before ".rela.text")
- false -> %% Name does not start with ".rela":
- fix_names(Names, [T | Acc])
- end;
- false ->
- case string:str(Name, ".rel") =:= 1 of
- true -> %% Name starts with ".rel":
- Section = string:substr(Name, 5),
- fix_names(Names, [{Section, Size - 4}
- | [T | Acc]]); % XXX: Is order ok? (".text"
- % always before ".rela.text")
- false -> %% Name does not start with ".rel":
- fix_names(Names, [T | Acc])
- end
- end.
-
-
-%% @doc A function that byte-reverses a binary. This might be needed because of
-%% little (fucking!) endianess.
--spec bin_reverse(binary()) -> binary().
-bin_reverse(Bin) when is_binary(Bin) ->
- bin_reverse(Bin, <<>>).
-
--spec bin_reverse(binary(), binary()) -> binary().
-bin_reverse(<<>>, Acc) ->
- Acc;
-bin_reverse(<<Head, More/binary>>, Acc) ->
- bin_reverse(More, <<Head, Acc/binary>>).
-
-%% @doc A function that extracts a null-terminated string from a binary. It
-%% returns the found string along with the rest of the binary.
--spec bin_get_string(binary()) -> {string(), binary()}.
-bin_get_string(Bin) ->
- bin_get_string(Bin, <<>>).
-
-bin_get_string(<<>>, BinAcc) ->
- Bin = bin_reverse(BinAcc), % little endian!
- {binary_to_list(Bin), <<>>};
-bin_get_string(<<0, MoreBin/binary>>, BinAcc) ->
- Bin = bin_reverse(BinAcc), % little endian!
- {binary_to_list(Bin), MoreBin};
-bin_get_string(<<Letter, Tail/binary>>, BinAcc) ->
- bin_get_string(Tail, <<Letter, BinAcc/binary>>).
-
-%% @doc
-make_offsets(NamesSizes) ->
- {Names, Sizes} = lists:unzip(NamesSizes),
- Offsets = make_offsets_from_sizes(Sizes, 1, []),
- lists:zip(Names, Offsets).
-
-make_offsets_from_sizes([], _, Acc) ->
- lists:reverse(Acc);
-make_offsets_from_sizes([Size | Sizes], Cur, Acc) ->
- make_offsets_from_sizes(Sizes, Size+Cur+1, [Cur | Acc]). % For the "."!
-
%% @doc Little-Endian Base 128 (LEB128) Decoder
%% This function extracts the <b>first</b> LEB128-encoded integer in a
%% binary and returns that integer along with the remaining binary. This is
@@ -770,21 +618,3 @@ leb128_decode(LebNum, NoOfBits, Acc) ->
<<Num:Size/integer>> = <<NextBundle:7/bits, Acc/bits>>,
{Num, MoreLebNums}
end.
-
-%% @doc Extract ELF Class from ELF header and export symbol to process
-%% dictionary.
--spec set_architecture_flag(elf()) -> 'ok'.
-set_architecture_flag(Elf) ->
- %% Extract information about ELF Class from ELF Header
- <<16#7f, $E, $L, $F, EI_Class, _MoreHeader/binary>>
- = get_binary_segment(Elf, 0, ?ELF_EHDR_SIZE),
- put(elf_class, EI_Class),
- ok.
-
-%% @doc Read from object file header if the file class is ELF32 or ELF64.
--spec is64bit() -> boolean().
-is64bit() ->
- case get(elf_class) of
- ?ELFCLASS64 -> true;
- ?ELFCLASS32 -> false
- end.
diff --git a/lib/hipe/llvm/elf_format.hrl b/lib/hipe/llvm/elf_format.hrl
index 7a3cdfead6..57a36f0c3e 100644
--- a/lib/hipe/llvm/elf_format.hrl
+++ b/lib/hipe/llvm/elf_format.hrl
@@ -486,3 +486,43 @@
%% Misc.
%%------------------------------------------------------------------------------
-define(bits(Bytes), ((Bytes) bsl 3)).
+
+%%------------------------------------------------------------------------------
+%% Exported record and type declarations for 'elf_format' module
+%%------------------------------------------------------------------------------
+
+%% Section header entries
+-record(elf_shdr,
+ {name :: elf_format:name() % Section name
+ ,type :: elf_format:shdr_type() % Section type
+ ,flags :: elf_format:bitflags() % Section attributes
+ ,addr :: elf_format:offset() % Virtual address in memory
+ ,offset :: elf_format:offset() % Offset in file
+ ,size :: elf_format:size() % Size of section
+ ,link :: non_neg_integer() % Link to other section
+ ,info :: non_neg_integer() % Miscellaneous information
+ ,addralign :: elf_format:size() % Address align boundary
+ ,entsize :: elf_format:size() % Size of entries, if section has
+ % table
+ }).
+-type elf_shdr() :: #elf_shdr{}.
+
+%% Symbol table entries
+-record(elf_sym,
+ {name :: elf_format:name() % Symbol name
+ ,bind :: elf_format:sym_bind() % Symbol binding
+ ,type :: elf_format:sym_type() % Symbol type
+ ,value :: elf_format:valueoff() % Symbol value
+ ,size :: elf_format:size() % Size of object
+ ,section :: undefined | abs | elf_shdr()
+ }).
+-type elf_sym() :: #elf_sym{}.
+
+%% Relocations
+-record(elf_rel,
+ {offset :: elf_format:offset()
+ ,type :: elf_format:reloc_type()
+ ,addend :: elf_format:addend()
+ ,symbol :: elf_sym()
+ }).
+-type elf_rel() :: #elf_rel{}.
diff --git a/lib/hipe/llvm/hipe_llvm.erl b/lib/hipe/llvm/hipe_llvm.erl
index 5e33731a2b..b22f8fb320 100644
--- a/lib/hipe/llvm/hipe_llvm.erl
+++ b/lib/hipe/llvm/hipe_llvm.erl
@@ -199,10 +199,9 @@
adj_stack_register/1,
adj_stack_type/1,
- mk_branch_meta/3,
- branch_meta_id/1,
- branch_meta_true_weight/1,
- branch_meta_false_weight/1
+ mk_meta/2,
+ meta_id/1,
+ meta_operands/1
]).
-export([
@@ -234,7 +233,7 @@
function_arg_type_list/1
]).
--export([pp_ins_list/2, pp_ins/2]).
+-export([pp_ins_list/3, pp_ins/3]).
%%-----------------------------------------------------------------------------
@@ -343,8 +342,9 @@
-record(llvm_adj_stack, {offset, 'register', type}).
-type llvm_adj_stack() :: #llvm_adj_stack{}.
--record(llvm_branch_meta, {id, true_weight, false_weight}).
--type llvm_branch_meta() :: #llvm_branch_meta{}.
+-record(llvm_meta, {id :: string(),
+ operands :: [string() | integer() | llvm_meta()]}).
+-type llvm_meta() :: #llvm_meta{}.
%% A type for any LLVM instruction
-type llvm_instr() :: llvm_ret() | llvm_br() | llvm_br_cond()
@@ -357,7 +357,7 @@
| llvm_call() | llvm_fun_def() | llvm_fun_decl()
| llvm_landingpad() | llvm_comment() | llvm_label()
| llvm_const_decl() | llvm_asm() | llvm_adj_stack()
- | llvm_branch_meta().
+ | llvm_meta().
%% Types
-record(llvm_void, {}).
@@ -701,7 +701,7 @@ is_label(#llvm_comment{}) -> false;
is_label(#llvm_const_decl{}) -> false;
is_label(#llvm_asm{}) -> false;
is_label(#llvm_adj_stack{}) -> false;
-is_label(#llvm_branch_meta{}) -> false.
+is_label(#llvm_meta{}) -> false.
%% const_decl
mk_const_decl(Dst, Decl_type, Type, Value) ->
@@ -722,14 +722,11 @@ adj_stack_offset(#llvm_adj_stack{offset=Offset}) -> Offset.
adj_stack_register(#llvm_adj_stack{'register'=Register}) -> Register.
adj_stack_type(#llvm_adj_stack{type=Type}) -> Type.
-%% branch meta-data
-mk_branch_meta(Id, True_weight, False_weight) ->
- #llvm_branch_meta{id=Id, true_weight=True_weight, false_weight=False_weight}.
-branch_meta_id(#llvm_branch_meta{id=Id}) -> Id.
-branch_meta_true_weight(#llvm_branch_meta{true_weight=True_weight}) ->
- True_weight.
-branch_meta_false_weight(#llvm_branch_meta{false_weight=False_weight}) ->
- False_weight.
+%% meta-data
+mk_meta(Id, Operands) ->
+ #llvm_meta{id=Id, operands=Operands}.
+meta_id(#llvm_meta{id=Id}) -> Id.
+meta_operands(#llvm_meta{operands=Operands}) -> Operands.
%% types
mk_void() -> #llvm_void{}.
@@ -765,13 +762,17 @@ function_arg_type_list(#llvm_fun{arg_type_list=Arg_type_list}) ->
%% Pretty-printer Functions
%%----------------------------------------------------------------------------
-%% @doc Pretty-print a list of LLVM instructions to a Device.
-pp_ins_list(_Dev, []) -> ok;
-pp_ins_list(Dev, [I|Is]) ->
- pp_ins(Dev, I),
- pp_ins_list(Dev, Is).
+-type llvm_version() :: {Major :: integer(), Minor :: integer()}.
-pp_ins(Dev, I) ->
+%% @doc Pretty-print a list of LLVM instructions to a Device, using syntax
+%% compatible with LLVM v. Major.Minor
+-spec pp_ins_list(file:io_device(), llvm_version(), [llvm_instr()]) -> ok.
+pp_ins_list(_Dev, _Ver, []) -> ok;
+pp_ins_list(Dev, Ver={_,_}, [I|Is]) ->
+ pp_ins(Dev, Ver, I),
+ pp_ins_list(Dev, Ver, Is).
+
+pp_ins(Dev, Ver, I) ->
case indent(I) of
true -> write(Dev, " ");
false -> ok
@@ -861,7 +862,7 @@ pp_ins(Dev, I) ->
true -> write(Dev, "volatile ");
false -> ok
end,
- pp_type(Dev, load_p_type(I)),
+ pp_dereference_type(Dev, Ver, load_p_type(I)),
write(Dev, [" ", load_pointer(I), " "]),
case load_alignment(I) of
[] -> ok;
@@ -897,7 +898,7 @@ pp_ins(Dev, I) ->
true -> write(Dev, "inbounds ");
false -> ok
end,
- pp_type(Dev, getelementptr_p_type(I)),
+ pp_dereference_type(Dev, Ver, getelementptr_p_type(I)),
write(Dev, [" ", getelementptr_value(I)]),
pp_typed_idxs(Dev, getelementptr_typed_idxs(I)),
write(Dev, "\n");
@@ -958,12 +959,16 @@ pp_ins(Dev, I) ->
pp_args(Dev, fun_def_arglist(I)),
write(Dev, ") "),
pp_options(Dev, fun_def_fn_attrs(I)),
+ case Ver >= {3,7} of false -> ok; true ->
+ write(Dev, "personality i32 (i32, i64, i8*,i8*)* "
+ "@__gcc_personality_v0 ")
+ end,
case fun_def_align(I) of
[] -> ok;
N -> write(Dev, ["align ", N])
end,
write(Dev, "{\n"),
- pp_ins_list(Dev, fun_def_body(I)),
+ pp_ins_list(Dev, Ver, fun_def_body(I)),
write(Dev, "}\n");
#llvm_fun_decl{} ->
write(Dev, "declare "),
@@ -992,8 +997,12 @@ pp_ins(Dev, I) ->
pp_type(Dev, const_decl_type(I)),
write(Dev, [" ", const_decl_value(I), "\n"]);
#llvm_landingpad{} ->
- write(Dev, "landingpad { i8*, i32 } personality i32 (i32, i64, i8*,i8*)*
- @__gcc_personality_v0 cleanup\n");
+ write(Dev, "landingpad { i8*, i32 } "),
+ case Ver < {3,7} of false -> ok; true ->
+ write(Dev, "personality i32 (i32, i64, i8*,i8*)* "
+ "@__gcc_personality_v0 ")
+ end,
+ write(Dev, "cleanup\n");
#llvm_asm{} ->
write(Dev, [asm_instruction(I), "\n"]);
#llvm_adj_stack{} ->
@@ -1001,14 +1010,37 @@ pp_ins(Dev, I) ->
adj_stack_register(I), "\", \"r\"("]),
pp_type(Dev, adj_stack_type(I)),
write(Dev, [" ", adj_stack_offset(I),")\n"]);
- #llvm_branch_meta{} ->
- write(Dev, ["!", branch_meta_id(I), " = metadata !{metadata !\"branch_weights\",
- i32 ", branch_meta_true_weight(I), ", i32 ",
- branch_meta_false_weight(I), "}\n"]);
+ #llvm_meta{} ->
+ write(Dev, ["!", meta_id(I), " = "]),
+ Named = case string:to_integer(meta_id(I)) of
+ {_, ""} -> false;
+ _ -> true
+ end,
+ case Ver < {3,6} andalso not Named of
+ true -> write(Dev, "metadata !{metadata ");
+ false -> write(Dev, "!{ ")
+ end,
+ write(Dev, string:join([if is_list(Op) -> ["!\"", Op, "\""];
+ is_integer(Op) -> ["i32 ", integer_to_list(Op)];
+ is_record(Op, llvm_meta) ->
+ ["!", meta_id(Op)]
+ end || Op <- meta_operands(I)], ", ")),
+ write(Dev, " }\n");
Other ->
exit({?MODULE, pp_ins, {"Unknown LLVM instruction", Other}})
end.
+%% @doc Print the type of a dereference in an LLVM instruction using syntax
+%% parsable by the specified LLVM version.
+pp_dereference_type(Dev, Ver, Type) ->
+ case Ver >= {3,7} of
+ false -> ok;
+ true ->
+ pp_type(Dev, pointer_type(Type)),
+ write(Dev, ", ")
+ end,
+ pp_type(Dev, Type).
+
%% @doc Pretty-print a list of types
pp_type_list(_Dev, []) -> ok;
pp_type_list(Dev, [T]) ->
@@ -1114,7 +1146,7 @@ indent(I) ->
#llvm_fun_def{} -> false;
#llvm_fun_decl{} -> false;
#llvm_const_decl{} -> false;
- #llvm_branch_meta{} -> false;
+ #llvm_meta{} -> false;
_ -> true
end.
diff --git a/lib/hipe/llvm/hipe_llvm_main.erl b/lib/hipe/llvm/hipe_llvm_main.erl
index 0e50c9539b..476d6fb49c 100644
--- a/lib/hipe/llvm/hipe_llvm_main.erl
+++ b/lib/hipe/llvm/hipe_llvm_main.erl
@@ -13,7 +13,7 @@
%% chain is invoked in order to produce an object file.
rtl_to_native(MFA, RTL, Roots, Options) ->
%% Compile to LLVM and get Instruction List (along with infos)
- {LLVMCode, RelocsDict, ConstTab} =
+ {LLVMCode, RelocsDict0, ConstTab0} =
hipe_rtl_to_llvm:translate(RTL, Roots),
%% Fix function name to an acceptable LLVM identifier (needed for closures)
{_Module, Fun, Arity} = hipe_rtl_to_llvm:fix_mfa_name(MFA),
@@ -24,34 +24,33 @@ rtl_to_native(MFA, RTL, Roots, Options) ->
%% Extract information from object file
%%
ObjBin = open_object_file(ObjectFile),
- %% Read and set the ELF class
- elf_format:set_architecture_flag(ObjBin),
+ Obj = elf_format:read(ObjBin),
%% Get labels info (for switches and jump tables)
- Labels = elf_format:get_rodata_relocs(ObjBin),
- {Switches, Closures} = get_tables(ObjBin),
+ Labels = elf_format:extract_rela(Obj, ?RODATA),
+ Tables = get_tables(Obj),
%% Associate Labels with Switches and Closures with stack args
- {SwitchInfos, ExposedClosures} =
- correlate_labels(Switches ++ Closures, Labels),
+ {SwitchInfos, ExposedClosures} = correlate_labels(Tables, Labels),
%% SwitchInfos: [{"table_50", [Labels]}]
%% ExposedClosures: [{"table_closures", [Labels]}]
-
+
%% Labelmap contains the offsets of the labels in the code that are
%% used for switch's jump tables
- LabelMap = create_labelmap(MFA, SwitchInfos, RelocsDict),
+ LabelMap = create_labelmap(MFA, SwitchInfos, RelocsDict0),
+ {RelocsDict, ConstTab} = extract_constants(RelocsDict0, ConstTab0, Obj),
%% Get relocation info
- TextRelocs = elf_format:get_text_relocs(ObjBin),
+ TextRelocs = elf_format:extract_rela(Obj, ?TEXT),
%% AccRefs contains the offsets of all references to relocatable symbols in
%% the code:
AccRefs = fix_relocations(TextRelocs, RelocsDict, MFA),
%% Get stack descriptors
- SDescs = get_sdescs(ObjBin),
+ SDescs = get_sdescs(Obj),
%% FixedSDescs are the stack descriptors after correcting calls that have
%% arguments in the stack
FixedSDescs =
fix_stack_descriptors(RelocsDict, AccRefs, SDescs, ExposedClosures),
Refs = AccRefs ++ FixedSDescs,
%% Get binary code from object file
- BinCode = elf_format:extract_text(ObjBin),
+ BinCode = elf_format:extract_text(Obj),
%% Remove temp files (if needed)
ok = remove_temp_folder(Dir, Options),
%% Return the code together with information that will be used in the
@@ -78,7 +77,8 @@ compile_with_llvm(FunName, Arity, LLVMCode, Options, UseBuffer) ->
false -> []
end,
{ok, File_llvm} = file:open(Dir ++ Filename ++ ".ll", OpenOpts),
- hipe_llvm:pp_ins_list(File_llvm, LLVMCode),
+ Ver = hipe:get_llvm_version(), %% Should probably cache this
+ hipe_llvm:pp_ins_list(File_llvm, Ver, LLVMCode),
%% delayed_write can cause file:close not to do a close, hence the two calls
ok = file:close(File_llvm),
__ = file:close(File_llvm),
@@ -158,12 +158,10 @@ trans_optlev_flag(Tool, Options) ->
%%------------------------------------------------------------------------------
%% @doc Get switch table and closure table.
+-spec get_tables(elf_format:elf()) -> [elf_sym()].
get_tables(Elf) ->
- %% Search Symbol Table for an entry with name prefixed with "table_":
- Triples = elf_format:get_tab_entries(Elf),
- Switches = [T || T={"table_" ++ _, _, _} <- Triples],
- Closures = [T || T={"table_closures" ++ _, _, _} <- Switches],
- {Switches, Closures}.
+ %% Search Symbol Table for entries where name is prefixed with "table_":
+ [S || S=#elf_sym{name="table_" ++ _} <- elf_format:elf_symbols(Elf)].
%% @doc This function associates symbols who point to some table of labels with
%% the corresponding offsets of the labels in the code. These tables can
@@ -171,14 +169,12 @@ get_tables(Elf) ->
%% of blocks that contain closure calls with more than ?NR_ARG_REGS.
correlate_labels([], _L) -> {[], []};
correlate_labels(Tables, Labels) ->
- %% Sort "Tables" based on "ValueOffsets"
- OffsetSortedTb = lists:ukeysort(2, Tables),
- %% Unzip offset-sorted list of "Switches"
- {Names, _Offsets, TablesSizeList} = lists:unzip3(OffsetSortedTb),
- %% Associate switch names with labels
- L = split_list(Labels, TablesSizeList),
- %% Zip back! (to [{SwitchName, Values}])
- NamesValues = lists:zip(Names, L),
+ %% Assumes that the relocations are sorted
+ RelocTree = gb_trees:from_orddict(
+ [{Rel#elf_rel.offset, Rel#elf_rel.addend} || Rel <- Labels]),
+ %% Lookup all relocations pertaining to each symbol
+ NamesValues = [{Name, lookup_range(Value, Value+Size, RelocTree)}
+ || #elf_sym{name=Name, value=Value, size=Size} <- Tables],
case lists:keytake("table_closures", 1, NamesValues) of
false -> %% No closures in the code, no closure table
{NamesValues, []};
@@ -186,6 +182,17 @@ correlate_labels(Tables, Labels) ->
{SwitchesNV, ClosureTableNV}
end.
+%% Fetches all values with a key in [Low, Hi)
+-spec lookup_range(_::K, _::K, gb_trees:tree(K,V)) -> [_::V].
+lookup_range(Low, Hi, Tree) ->
+ lookup_range_1(Hi, gb_trees:iterator_from(Low, Tree)).
+
+lookup_range_1(Hi, Iter0) ->
+ case gb_trees:next(Iter0) of
+ {Key, Value, Iter} when Key < Hi -> [Value | lookup_range_1(Hi, Iter)];
+ _ -> []
+ end.
+
%% @doc Create a gb_tree which contains information about the labels that used
%% for switch's jump tables. The keys of the gb_tree are of the form
%% {MFA, Label} and the values are the actual Offsets.
@@ -213,40 +220,80 @@ insert_to_labelmap([{Key, Value}|Rest], LabelMap) ->
insert_to_labelmap(Rest, LabelMap)
end.
+%% Find any LLVM-generated constants and add them to the constant table
+extract_constants(RelocsDict0, ConstTab0, Obj) ->
+ TextRelocs = elf_format:extract_rela(Obj, ?TEXT),
+ AnonConstSections =
+ lists:usort([{Sec, Offset}
+ || #elf_rel{symbol=#elf_sym{type=section, section=Sec},
+ addend=Offset} <- TextRelocs]),
+ lists:foldl(
+ fun({#elf_shdr{name=Name, type=progbits, addralign=Align, entsize=EntSize,
+ size=Size} = Section, Offset}, {RelocsDict1, ConstTab1})
+ when EntSize > 0, 0 =:= Size rem EntSize, 0 =:= Offset rem EntSize ->
+ SectionBin = elf_format:section_contents(Section, Obj),
+ Constant = binary:part(SectionBin, Offset, EntSize),
+ {ConstTab, ConstLbl} =
+ hipe_consttab:insert_binary_const(ConstTab1, Align, Constant),
+ {dict:store({anon, Name, Offset}, {constant, ConstLbl}, RelocsDict1),
+ ConstTab}
+ end, {RelocsDict0, ConstTab0}, AnonConstSections).
+
%% @doc Correlate object file relocation symbols with info from translation to
%% llvm code.
fix_relocations(Relocs, RelocsDict, MFA) ->
- fix_relocs(Relocs, RelocsDict, MFA, []).
-
-fix_relocs([], _, _, RelocAcc) -> RelocAcc;
-fix_relocs([{Name, Offset}|Rs], RelocsDict, {ModName,_,_}=MFA, RelocAcc) ->
+ lists:map(fun(Reloc) -> fix_reloc(Reloc, RelocsDict, MFA) end, Relocs).
+
+%% Relocation types and expected addends for x86 and amd64
+-define(PCREL_T, 'pc32').
+-define(PCREL_A, -4). %% Hard-coded in hipe_x86.c and hipe_amd64.c
+-ifdef(BIT32).
+-define(ABS_T, '32').
+-define(ABS_A, _). %% We support any addend
+-else.
+-define(ABS_T, '64').
+-define(ABS_A, 0).
+-endif.
+
+fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=undefined, type=notype},
+ offset=Offset, type=?PCREL_T, addend=?PCREL_A},
+ RelocsDict, {ModName,_,_}) when Name =/= "" ->
case dict:fetch(Name, RelocsDict) of
- {atom, AtomName} ->
- fix_relocs(Rs, RelocsDict, MFA,
- [{?LOAD_ATOM, Offset, AtomName}|RelocAcc]);
- {constant, Label} ->
- fix_relocs(Rs, RelocsDict, MFA,
- [{?LOAD_ADDRESS, Offset, {constant, Label}}|RelocAcc]);
- {switch, _, JTabLab} -> %% Treat switch exactly as constant
- fix_relocs(Rs, RelocsDict, MFA,
- [{?LOAD_ADDRESS, Offset, {constant, JTabLab}}|RelocAcc]);
- {closure, _}=Closure ->
- fix_relocs(Rs, RelocsDict, MFA,
- [{?LOAD_ADDRESS, Offset, Closure}|RelocAcc]);
- {call, {bif, BifName, _}} ->
- fix_relocs(Rs, RelocsDict, MFA,
- [{?CALL_LOCAL, Offset, BifName}|RelocAcc]);
+ {call, {bif, BifName, _}} -> {?CALL_LOCAL, Offset, BifName};
%% MFA calls to functions in the same module are of type 3, while all
%% other MFA calls are of type 2.
- {call, {ModName,_F,_A}=CallMFA} ->
- fix_relocs(Rs, RelocsDict, MFA,
- [{?CALL_LOCAL, Offset, CallMFA}|RelocAcc]);
- {call, CallMFA} ->
- fix_relocs(Rs, RelocsDict, MFA,
- [{?CALL_REMOTE, Offset, CallMFA}|RelocAcc]);
- Other ->
- exit({?MODULE, fix_relocs,
- {"Relocation not in relocation dictionary", Other}})
+ %% XXX: Does this code break hot code loading (by transforming external
+ %% calls into local calls?)
+ {call, {ModName,_F,_A}=CallMFA} -> {?CALL_LOCAL, Offset, CallMFA};
+ {call, CallMFA} -> {?CALL_REMOTE, Offset, CallMFA}
+ end;
+fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=undefined, type=notype},
+ offset=Offset, type=?ABS_T, addend=?ABS_A},
+ RelocsDict, _) when Name =/= "" ->
+ case dict:fetch(Name, RelocsDict) of
+ {atom, AtomName} -> {?LOAD_ATOM, Offset, AtomName};
+ {constant, Label} -> {?LOAD_ADDRESS, Offset, {constant, Label}};
+ {closure, _}=Closure -> {?LOAD_ADDRESS, Offset, Closure}
+ end;
+fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=#elf_shdr{name=?TEXT},
+ type=func},
+ offset=Offset, type=?PCREL_T, addend=?PCREL_A},
+ RelocsDict, MFA) when Name =/= "" ->
+ case dict:fetch(Name, RelocsDict) of
+ {call, MFA} -> {?CALL_LOCAL, Offset, MFA}
+ end;
+fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=#elf_shdr{name=?RODATA},
+ type=object},
+ offset=Offset, type=?ABS_T, addend=?ABS_A},
+ RelocsDict, _) when Name =/= "" ->
+ case dict:fetch(Name, RelocsDict) of
+ {switch, _, JTabLab} -> %% Treat switch exactly as constant
+ {?LOAD_ADDRESS, Offset, {constant, JTabLab}}
+ end;
+fix_reloc(#elf_rel{symbol=#elf_sym{type=section, section=#elf_shdr{name=Name}},
+ offset=Offset, type=?ABS_T, addend=Addend}, RelocsDict, _) ->
+ case dict:fetch({anon, Name, Addend}, RelocsDict) of
+ {constant, Label} -> {?LOAD_ADDRESS, Offset, {constant, Label}}
end.
%%------------------------------------------------------------------------------
@@ -271,20 +318,14 @@ get_sdescs(Elf) ->
T = SPCount * ?SP_ADDR_SIZE,
%% Pattern match fields of ".note.gc":
<<SPCount:(?bits(?SP_COUNT_SIZE))/integer-little, % Sanity check!
- SPAddrs:T/binary, % NOTE: In 64bit they are relocs!
+ _SPAddrs:T/binary, % NOTE: In 64bit they are relocs!
StkFrameSize:(?bits(?SP_STKFRAME_SIZE))/integer-little,
StkArity:(?bits(?SP_STKARITY_SIZE))/integer-little,
_LiveRootCount:(?bits(?SP_LIVEROOTCNT_SIZE))/integer-little, % Skip
Roots/binary>> = NoteGC_bin,
LiveRoots = get_liveroots(Roots, []),
- %% Extract information about the safe point addresses:
- SPOffs =
- case elf_format:is64bit() of
- true -> %% Find offsets in ".rela.note.gc":
- elf_format:get_rela_addends(RelaNoteGC);
- false -> %% Find offsets in SPAddrs (in ".note.gc"):
- get_spoffs(SPAddrs, [])
- end,
+ %% Extract the safe point offsets:
+ SPOffs = [A || #elf_rel{addend=A} <- RelaNoteGC],
%% Extract Exception Handler labels:
ExnHandlers = elf_format:get_exn_handlers(Elf),
%% Combine ExnHandlers and Safe point addresses (return addresses):
@@ -300,13 +341,6 @@ get_liveroots(<<Root:?bits(?LR_STKINDEX_SIZE)/integer-little,
MoreRoots/binary>>, Acc) ->
get_liveroots(MoreRoots, [Root | Acc]).
-%% @doc Extracts a bunch of integers (safepoint offsets) from a binary. Returns
-%% a tuple as need for stack descriptors.
-get_spoffs(<<>>, Acc) ->
- lists:reverse(Acc);
-get_spoffs(<<SPOff:?bits(?SP_ADDR_SIZE)/integer-little, More/binary>>, Acc) ->
- get_spoffs(More, [SPOff | Acc]).
-
combine_ras_and_exns(_, [], Acc) ->
lists:reverse(Acc);
combine_ras_and_exns(ExnHandlers, [RA | MoreRAs], Acc) ->
@@ -465,7 +499,7 @@ remove_temp_folder(Dir, Options) ->
end.
unique_id(FunName, Arity) ->
- integer_to_list(erlang:phash2({FunName, Arity, now()})).
+ integer_to_list(erlang:phash2({FunName, Arity, erlang:unique_integer()})).
unique_folder(FunName, Arity, Options) ->
DirName = "llvm_" ++ unique_id(FunName, Arity) ++ "/",
@@ -489,18 +523,3 @@ unique_folder(FunName, Arity, Options) ->
dir_exists(Filename) ->
{Flag, Info} = file:read_file_info(Filename),
(Flag =:= ok) andalso (element(3, Info) =:= directory).
-
-%% @doc Function that takes as arguments a list of integers and a list with
-%% numbers indicating how many items should each tuple have and splits
-%% the original list to a list of lists of integers (with the specified
-%% number of elements), i.e. [ [...], [...] ].
--spec split_list([integer()], [integer()]) -> [ [integer()] ].
-split_list(List, ElemsPerTuple) ->
- split_list(List, ElemsPerTuple, []).
-
--spec split_list([integer()], [integer()], [ [integer()] ]) -> [ [integer()] ].
-split_list([], [], Acc) ->
- lists:reverse(Acc);
-split_list(List, [NumOfElems | MoreNums], Acc) ->
- {L1, L2} = lists:split(NumOfElems, List),
- split_list(L2, MoreNums, [ L1 | Acc]).
diff --git a/lib/hipe/llvm/hipe_llvm_merge.erl b/lib/hipe/llvm/hipe_llvm_merge.erl
index 3ababfc21a..6e891ac3b0 100644
--- a/lib/hipe/llvm/hipe_llvm_merge.erl
+++ b/lib/hipe/llvm/hipe_llvm_merge.erl
@@ -27,7 +27,7 @@ finalize(CompiledCode, Closures, Exports) ->
DataRelocs = hipe_pack_constants:mk_data_relocs(RefsFromConsts, LabelMap),
SSE = hipe_pack_constants:slim_sorted_exportmap(ExportMap, Closures, Exports),
SlimRefs = hipe_pack_constants:slim_refs(AccRefs),
- term_to_binary([{?VERSION_STRING(),?HIPE_SYSTEM_CRC},
+ term_to_binary([{?VERSION_STRING(),?HIPE_ERTS_CHECKSUM},
ConstAlign, ConstSize,
SC, % ConstMap
DataRelocs, % LabelMap
diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl
index d7d8d1b049..66b2e10fb8 100644
--- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl
+++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl
@@ -13,6 +13,8 @@
-define(WORD_WIDTH, (?bytes_to_bits(hipe_rtl_arch:word_size()))).
-define(BRANCH_META_TAKEN, "0").
-define(BRANCH_META_NOT_TAKEN, "1").
+-define(FIRST_FREE_META_NO, 2).
+-define(HIPE_LITERALS_META, "hipe.literals").
%%------------------------------------------------------------------------------
%% @doc Main function for translating an RTL function to LLVM Assembly. Takes as
@@ -51,8 +53,9 @@ translate(RTL, Roots) ->
translate_instr_list(Code1, [], Relocs, Data),
%% Create LLVM code to declare relocation symbols as external symbols along
%% with local variables in order to use them as just any other variable
- {FinalRelocs, ExternalDecl, LocalVars} =
+ {FinalRelocs, ExternalDecl0, LocalVars} =
handle_relocations(Relocs1, Data, Fun),
+ ExternalDecl = add_literals_metadata(ExternalDecl0),
%% Pass on LLVM code in order to create Fail blocks and a landingpad
%% instruction to each one
LLVM_Code2 = add_landingpads(LLVM_Code1, FailLabels),
@@ -266,17 +269,18 @@ trans_alub_overflow(I, Sign, Relocs) ->
T2 = mk_temp(),
%% T1{1}: Boolean variable indicating overflow
I6 = hipe_llvm:mk_extractvalue(T2, ReturnType, T1, "1", []),
- case hipe_rtl:alub_cond(I) of
- Op when Op =:= overflow orelse Op =:= ltu ->
- True_label = mk_jump_label(hipe_rtl:alub_true_label(I)),
- False_label = mk_jump_label(hipe_rtl:alub_false_label(I)),
- MetaData = branch_metadata(hipe_rtl:alub_pred(I));
- not_overflow ->
- True_label = mk_jump_label(hipe_rtl:alub_false_label(I)),
- False_label = mk_jump_label(hipe_rtl:alub_true_label(I)),
- MetaData = branch_metadata(1 - hipe_rtl:alub_pred(I))
- end,
- I7 = hipe_llvm:mk_br_cond(T2, True_label, False_label, MetaData),
+ {TrueLabel, FalseLabel, MetaData} =
+ case hipe_rtl:alub_cond(I) of
+ Op when Op =:= overflow orelse Op =:= ltu ->
+ {mk_jump_label(hipe_rtl:alub_true_label(I)),
+ mk_jump_label(hipe_rtl:alub_false_label(I)),
+ branch_metadata(hipe_rtl:alub_pred(I))};
+ not_overflow ->
+ {mk_jump_label(hipe_rtl:alub_false_label(I)),
+ mk_jump_label(hipe_rtl:alub_true_label(I)),
+ branch_metadata(1 - hipe_rtl:alub_pred(I))}
+ end,
+ I7 = hipe_llvm:mk_br_cond(T2, TrueLabel, FalseLabel, MetaData),
{[I7, I6, I5, I4, I3, I2, I1], NewRelocs}.
trans_alub_op(I, Sign) ->
@@ -1457,8 +1461,8 @@ handle_relocations(Relocs, Data, Fun) ->
Relocs4 = dict:store("hipe_bifs.llvm_fix_pinned_regs.0",
{call, {hipe_bifs, llvm_fix_pinned_regs, 0}}, Relocs3),
BranchMetaData = [
- hipe_llvm:mk_branch_meta(?BRANCH_META_TAKEN, "99", "1")
- , hipe_llvm:mk_branch_meta(?BRANCH_META_NOT_TAKEN, "1", "99")
+ hipe_llvm:mk_meta(?BRANCH_META_TAKEN, ["branch_weights", 99, 1])
+ , hipe_llvm:mk_meta(?BRANCH_META_NOT_TAKEN, ["branch_weights", 1, 99])
],
ExternalDeclarations = AtomDecl ++ ClosureDecl ++ ConstDecl ++ FunDecl ++
ClosureLabelDecl ++ SwitchDecl ++ BranchMetaData,
@@ -1611,3 +1615,16 @@ load_constant(Label) ->
const_to_dict(Elem, Dict) ->
Name = "DL" ++ integer_to_list(Elem),
dict:store(Name, {'constant', Elem}, Dict).
+
+%% @doc Export the hipe literals that LLVM needs to generate the prologue as
+%% metadata.
+add_literals_metadata(ExternalDecls) ->
+ Pairs = [hipe_llvm:mk_meta(integer_to_list(?FIRST_FREE_META_NO),
+ ["P_NSP_LIMIT", ?P_NSP_LIMIT])
+ ,hipe_llvm:mk_meta(integer_to_list(?FIRST_FREE_META_NO + 1),
+ ["X86_LEAF_WORDS", ?X86_LEAF_WORDS])
+ ,hipe_llvm:mk_meta(integer_to_list(?FIRST_FREE_META_NO + 2),
+ ["AMD64_LEAF_WORDS", ?AMD64_LEAF_WORDS])
+ ],
+ [hipe_llvm:mk_meta(?HIPE_LITERALS_META, Pairs) |
+ Pairs ++ ExternalDecls].
diff --git a/lib/hipe/main/Makefile b/lib/hipe/main/Makefile
index 66e4c3e39a..8ef31dbb46 100644
--- a/lib/hipe/main/Makefile
+++ b/lib/hipe/main/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -69,7 +70,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
include ../native.mk
-ERL_COMPILE_FLAGS += +nowarn_shadow_vars +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += -Werror +nowarn_shadow_vars +warn_export_vars +warn_missing_spec +warn_untyped_record
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/main/hipe.app.src b/lib/hipe/main/hipe.app.src
index e81212d4dc..f8487151d7 100644
--- a/lib/hipe/main/hipe.app.src
+++ b/lib/hipe/main/hipe.app.src
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2015. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -87,6 +88,7 @@
hipe_icode2rtl,
hipe_icode_bincomp,
hipe_icode_callgraph,
+ hipe_icode_call_elim,
hipe_icode_cfg,
hipe_icode_coordinator,
hipe_icode_ebb,
@@ -223,5 +225,5 @@
{registered,[]},
{applications, [kernel,stdlib]},
{env, []},
- {runtime_dependencies, ["syntax_tools-1.6.14","stdlib-2.0","kernel-3.0",
- "erts-6.0","compiler-5.0"]}]}.
+ {runtime_dependencies, ["syntax_tools-1.6.14","stdlib-2.5","kernel-3.0",
+ "erts-7.1","compiler-5.0"]}]}.
diff --git a/lib/hipe/main/hipe.appup.src b/lib/hipe/main/hipe.appup.src
index 02679fab21..b297ba10db 100644
--- a/lib/hipe/main/hipe.appup.src
+++ b/lib/hipe/main/hipe.appup.src
@@ -1,18 +1,19 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
{"%VSN%", [], []}.
diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl
index 539ce883c0..6c525dd143 100644
--- a/lib/hipe/main/hipe.erl
+++ b/lib/hipe/main/hipe.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -199,15 +200,17 @@
compile/4,
compile_core/4,
file/1,
- file/2,
- llvm_support_available/0,
+ file/2,
+ get_llvm_version/0,
+ llvm_support_available/0,
load/1,
help/0,
help_hiper/0,
help_options/0,
help_option/1,
help_debug_options/0,
- version/0]).
+ version/0,
+ erts_checksum/0]).
-ifndef(DEBUG).
-define(DEBUG,true).
@@ -215,6 +218,7 @@
-include("hipe.hrl").
-include("../../compiler/src/beam_disasm.hrl").
+-include("../rtl/hipe_literals.hrl").
%%-------------------------------------------------------------------
%% Basic type declaration for exported functions of the 'hipe' module
@@ -445,16 +449,16 @@ compile(Name, File, Opts0) when is_atom(Name) ->
true ->
case filename:find_src(filename:rootname(File, ".beam")) of
{error, _} ->
- ?error_msg("Cannot find source code for ~p.",[File]),
+ ?error_msg("Cannot find source code for ~p.", [File]),
?EXIT({cant_find_source_code});
{Source, CompOpts} ->
CoreOpts = [X || X = {core_transform, _} <- Opts],
- %%io:format("Using: ~w\n", [CoreOpts]),
+ %% io:format("Using: ~w\n", [CoreOpts]),
case compile:file(Source, CoreOpts ++ [to_core, binary|CompOpts]) of
{ok, _, Core} ->
compile_core(Name, Core, File, Opts);
Error ->
- ?error_msg("Error compiling ~p:\n~p.",[File, Error]),
+ ?error_msg("Error compiling ~p:\n~p.", [File, Error]),
?EXIT({cant_compile_source_code})
end
end;
@@ -466,7 +470,7 @@ compile(Name, File, Opts0) when is_atom(Name) ->
{ok, _, Core} ->
compile_core(Name, Core, File, Opts);
Error ->
- ?error_msg("Error compiling ~p:\n~p\n",[Source, Error]),
+ ?error_msg("Error compiling ~p:\n~p\n", [Source, Error]),
?EXIT({cant_compile_source_code, Error})
end;
Other when Other =:= false; Other =:= undefined ->
@@ -569,8 +573,7 @@ file(File, Options) when is_atom(File) ->
disasm(File) ->
case beam_disasm:file(File) of
#beam_file{labeled_exports = LabeledExports,
- compile_info = CompInfo,
- code = BeamCode} ->
+ compile_info = CompInfo, code = BeamCode} ->
CompOpts = proplists:get_value(options, CompInfo, []),
HCompOpts = case lists:keyfind(hipe, 1, CompOpts) of
{hipe, L} when is_list(L) -> L;
@@ -593,16 +596,16 @@ fix_beam_exports([], Exports) ->
Exports.
get_beam_icode(Mod, {BeamCode, Exports}, File, Options) ->
- ?option_time({ok, Icode} =
- (catch {ok, hipe_beam_to_icode:module(BeamCode, Options)}),
- "BEAM-to-Icode", Options),
+ {ok, Icode} =
+ ?option_time((catch {ok, hipe_beam_to_icode:module(BeamCode, Options)}),
+ "BEAM-to-Icode", Options),
BeamBin = get_beam_code(File),
{{Mod, Exports, Icode}, BeamBin}.
get_core_icode(Mod, Core, File, Options) ->
- ?option_time({ok, Icode} =
- (catch {ok, cerl_to_icode:module(Core, Options)}),
- "BEAM-to-Icode", Options),
+ {ok, Icode} =
+ ?option_time((catch {ok, cerl_to_icode:module(Core, Options)}),
+ "BEAM-to-Icode", Options),
NeedBeamCode = not proplists:get_bool(load, Options),
BeamBin =
case NeedBeamCode of
@@ -615,7 +618,7 @@ get_core_icode(Mod, Core, File, Options) ->
get_beam_code(Bin) when is_binary(Bin) -> Bin;
get_beam_code(FileName) ->
case erl_prim_loader:get_file(FileName) of
- {ok,Bin,_} ->
+ {ok, Bin, _} ->
Bin;
error ->
?EXIT(no_beam_file)
@@ -649,8 +652,9 @@ run_compiler_1(DisasmFun, IcodeFun, Options) ->
%% The full option expansion is not done
%% until the DisasmFun returns.
{Code, CompOpts} = DisasmFun(Options),
- Opts0 = expand_options(Options ++ CompOpts),
- Opts =
+ Opts0 = expand_options(Options ++ CompOpts,
+ get(hipe_target_arch)),
+ Opts =
case proplists:get_bool(to_llvm, Opts0) andalso
not llvm_support_available() of
true ->
@@ -760,7 +764,8 @@ finalize(OrigList, Mod, Exports, WholeModule, Opts) ->
finalize_fun(MfaIcodeList, Exports, Opts) ->
case proplists:get_value(concurrent_comp, Opts) of
FalseVal when (FalseVal =:= undefined) orelse (FalseVal =:= false) ->
- [finalize_fun_sequential(MFAIcode, Opts, #comp_servers{})
+ NoServers = #comp_servers{pp_server = none, range = none, type = none},
+ [finalize_fun_sequential(MFAIcode, Opts, NoServers)
|| {_MFA, _Icode} = MFAIcode <- MfaIcodeList];
TrueVal when (TrueVal =:= true) orelse (TrueVal =:= debug) ->
finalize_fun_concurrent(MfaIcodeList, Exports, Opts)
@@ -895,8 +900,7 @@ do_load(Mod, Bin, BeamBinOrPath) when is_binary(BeamBinOrPath);
code:load_native_sticky(Mod, Bin, Beam);
false ->
%% Normal loading of a whole module
- Architecture = erlang:system_info(hipe_architecture),
- ChunkName = hipe_unified_loader:chunk_name(Architecture),
+ ChunkName = hipe_unified_loader:chunk_name(HostArch),
{ok, _, Chunks0} = beam_lib:all_chunks(BeamBinOrPath),
Chunks = [{ChunkName, Bin}|lists:keydelete(ChunkName, 1, Chunks0)],
{ok, BeamPlusNative} = beam_lib:build_module(Chunks),
@@ -933,9 +937,9 @@ assemble(CompiledCode, Closures, Exports, Options) ->
%% but can be overridden by passing an option {target, Target}.
set_architecture(Options) ->
- put(hipe_host_arch, erlang:system_info(hipe_architecture)),
- put(hipe_target_arch,
- proplists:get_value(target, Options, get(hipe_host_arch))),
+ HostArch = erlang:system_info(hipe_architecture),
+ put(hipe_host_arch, HostArch),
+ put(hipe_target_arch, proplists:get_value(target, Options, HostArch)),
ok.
%% This sets up some globally accessed stuff that are needed by the
@@ -943,7 +947,7 @@ set_architecture(Options) ->
%% Therefore, this expands the current set of options for local use.
pre_init(Opts) ->
- Options = expand_options(Opts),
+ Options = expand_options(Opts, get(hipe_target_arch)),
%% Initialise some counters used for measurements and benchmarking. If
%% the option 'measure_regalloc' is given the compilation will return
%% a keylist with the counter values.
@@ -1031,6 +1035,12 @@ post(Res, Icode, Options) ->
version() ->
?VERSION_STRING().
+%% @doc Returns checksum identifying the target runtime system.
+-spec erts_checksum() -> integer().
+
+erts_checksum() ->
+ ?HIPE_ERTS_CHECKSUM.
+
%% --------------------------------------------------------------------
%% D O C U M E N T A T I O N - H E L P
%% --------------------------------------------------------------------
@@ -1061,6 +1071,8 @@ help() ->
" Prints a description of debug options.\n" ++
" version() ->\n" ++
" Returns the HiPE version as a string'.\n" ++
+ " erts_checksum() ->\n" ++
+ " Returns a checksum identifying the target runtime system.\n" ++
"\n" ++
" For HiPE developers only:\n" ++
" Use `help_hiper()' for information about HiPE's low-level interface\n",
@@ -1105,10 +1117,10 @@ help_hiper() ->
-spec help_options() -> 'ok'.
help_options() ->
- set_architecture([]), %% needed for target-specific option expansion
- O1 = expand_options([o1]),
- O2 = expand_options([o2]),
- O3 = expand_options([o3]),
+ HostArch = erlang:system_info(hipe_architecture),
+ O1 = expand_options([o1], HostArch),
+ O2 = expand_options([o2], HostArch),
+ O3 = expand_options([o3], HostArch),
io:format("HiPE Compiler Options\n" ++
" Boolean-valued options generally have corresponding " ++
"aliases `no_...',\n" ++
@@ -1134,7 +1146,7 @@ help_options() ->
[ordsets:from_list([verbose, debug, time, load, pp_beam,
pp_icode, pp_rtl, pp_native, pp_asm,
timeout]),
- expand_options([pp_all]),
+ expand_options([pp_all], HostArch),
O1 -- [o1],
(O2 -- O1) -- [o2],
(O3 -- O2) -- [o3]]),
@@ -1153,6 +1165,9 @@ option_text(caller_save_spill_restore) ->
"Activates caller save register spills and restores";
option_text(debug) ->
"Outputs internal debugging information during compilation";
+option_text(icode_call_elim) ->
+ "Performs call elimination of BIFs that are side-effect free\n" ++
+ "only on some argument types";
option_text(icode_range) ->
"Performs integer range analysis on the Icode level";
option_text(icode_ssa_check) ->
@@ -1232,8 +1247,8 @@ option_text(Opt) when is_atom(Opt) ->
-spec help_option(comp_option()) -> 'ok'.
help_option(Opt) ->
- set_architecture([]), %% needed for target-specific option expansion
- case expand_options([Opt]) of
+ HostArch = erlang:system_info(hipe_architecture),
+ case expand_options([Opt], HostArch) of
[Opt] ->
Name = if is_atom(Opt) -> Opt;
tuple_size(Opt) =:= 2 -> element(1, Opt)
@@ -1306,6 +1321,7 @@ opt_keys() ->
get_called_modules,
split_arith,
split_arith_unsafe,
+ icode_call_elim,
icode_inline_bifs,
icode_ssa_check,
icode_ssa_copy_prop,
@@ -1364,11 +1380,11 @@ opt_keys() ->
%% verbose_spills,
x87].
-%% Definitions:
+%% Definitions:
-o1_opts() ->
+o1_opts(TargetArch) ->
Common = [inline_fp, pmatch, peephole],
- case get(hipe_target_arch) of
+ case TargetArch of
ultrasparc ->
Common;
powerpc ->
@@ -1385,48 +1401,22 @@ o1_opts() ->
?EXIT({executing_on_an_unsupported_architecture,Arch})
end.
-o2_opts() ->
+o2_opts(TargetArch) ->
Common = [icode_ssa_const_prop, icode_ssa_copy_prop, % icode_ssa_struct_reuse,
- icode_type, icode_inline_bifs, rtl_lcm,
+ icode_type, icode_inline_bifs, icode_call_elim, rtl_lcm,
rtl_ssa, rtl_ssa_const_prop,
- spillmin_color, use_indexing, remove_comments,
- concurrent_comp, binary_opt | o1_opts()],
- case get(hipe_target_arch) of
- ultrasparc ->
- Common;
- powerpc ->
- Common;
- ppc64 ->
- Common;
- arm ->
- Common;
- x86 ->
- Common;
- % [rtl_ssapre | Common];
- amd64 ->
- [icode_range | Common]; % range analysis is effective on 64 bits
- Arch ->
- ?EXIT({executing_on_an_unsupported_architecture,Arch})
- end.
-
-o3_opts() ->
- Common = [icode_range, {regalloc,coalescing} | o2_opts()],
- case get(hipe_target_arch) of
- ultrasparc ->
- Common;
- powerpc ->
- Common;
- ppc64 ->
- Common;
- arm ->
- Common;
- x86 ->
- Common;
- amd64 ->
- Common;
- Arch ->
- ?EXIT({executing_on_an_unsupported_architecture,Arch})
- end.
+ spillmin_color, use_indexing, remove_comments,
+ concurrent_comp, binary_opt | o1_opts(TargetArch)],
+ case TargetArch of
+ T when T =:= amd64 orelse T =:= ppc64 -> % 64-bit targets
+ [icode_range | Common];
+ _ -> % T \in [arm, powerpc, ultrasparc, x86]
+ Common % [rtl_ssapre | Common];
+ end.
+
+o3_opts(TargetArch) ->
+ %% no point checking for target architecture since this is checked in 'o1'
+ [icode_range, {regalloc,coalescing} | o2_opts(TargetArch)].
%% Note that in general, the normal form for options should be positive.
%% This is a good programming convention, so that tests in the code say
@@ -1443,6 +1433,7 @@ opt_negations() ->
{no_icode_inline_bifs, icode_inline_bifs},
{no_icode_range, icode_range},
{no_icode_split_arith, icode_split_arith},
+ {no_icode_call_elim, icode_call_elim},
{no_icode_ssa_check, icode_ssa_check},
{no_icode_ssa_copy_prop, icode_ssa_copy_prop},
{no_icode_ssa_const_prop, icode_ssa_const_prop},
@@ -1489,22 +1480,29 @@ opt_aliases() ->
opt_basic_expansions() ->
[{pp_all, [pp_beam, pp_icode, pp_rtl, pp_native]}].
-opt_expansions() ->
- [{o1, o1_opts()},
- {o2, o2_opts()},
- {o3, o3_opts()},
- {to_llvm, llvm_opts(o3)},
- {{to_llvm, o0}, llvm_opts(o0)},
- {{to_llvm, o1}, llvm_opts(o1)},
- {{to_llvm, o2}, llvm_opts(o2)},
- {{to_llvm, o3}, llvm_opts(o3)},
+opt_expansions(TargetArch) ->
+ [{o1, o1_opts(TargetArch)},
+ {o2, o2_opts(TargetArch)},
+ {o3, o3_opts(TargetArch)},
+ {to_llvm, llvm_opts(o3, TargetArch)},
+ {{to_llvm, o0}, llvm_opts(o0, TargetArch)},
+ {{to_llvm, o1}, llvm_opts(o1, TargetArch)},
+ {{to_llvm, o2}, llvm_opts(o2, TargetArch)},
+ {{to_llvm, o3}, llvm_opts(o3, TargetArch)},
{x87, [x87, inline_fp]},
- {inline_fp, case get(hipe_target_arch) of %% XXX: Temporary until x86
- x86 -> [x87, inline_fp]; %% has sse2
+ {inline_fp, case TargetArch of %% XXX: Temporary until x86 has sse2
+ x86 -> [x87, inline_fp];
_ -> [inline_fp] end}].
-llvm_opts(O) ->
- [to_llvm, {llvm_opt, O}, {llvm_llc, O}].
+llvm_opts(O, TargetArch) ->
+ Base = [to_llvm, {llvm_opt, O}, {llvm_llc, O}],
+ case TargetArch of
+ %% A llvm bug present in 3.4 through (at least) 3.8 miscompiles x86
+ %% functions that have floats are spilled to stack by clobbering the process
+ %% pointer (ebp) trying to realign the stack pointer.
+ x86 -> [no_inline_fp | Base];
+ _ -> Base
+ end.
%% This expands "basic" options, which may be tested early and cannot be
%% in conflict with options found in the source code.
@@ -1523,18 +1521,19 @@ expand_kt2(Opts) ->
[{use_callgraph, fixpoint}, core,
{core_transform, cerl_typean}]}]}]).
-%% Note that set_architecture/1 must be called first, and that the given
+%% Note that the given
%% list should contain the total set of options, since things like 'o2'
%% are expanded here. Basic expansions are processed here also, since
%% this function is called from the help functions.
--spec expand_options(comp_options()) -> comp_options().
+-spec expand_options(comp_options(), hipe_architecture()) -> comp_options().
-expand_options(Opts) ->
+expand_options(Opts, TargetArch) ->
proplists:normalize(Opts, [{negations, opt_negations()},
{aliases, opt_aliases()},
{expand, opt_basic_expansions()},
- {expand, opt_expansions()}]).
+ {expand, opt_expansions(TargetArch)},
+ {negations, opt_negations()}]).
-spec check_options(comp_options()) -> 'ok'.
@@ -1552,18 +1551,27 @@ check_options(Opts) ->
-spec llvm_support_available() -> boolean().
llvm_support_available() ->
- get_llvm_version() >= 3.4.
+ get_llvm_version() >= {3,4}.
+
+-type llvm_version() :: {Major :: integer(), Minor :: integer()}.
+-spec get_llvm_version() -> llvm_version() | {0, 0}.
get_llvm_version() ->
OptStr = os:cmd("opt -version"),
SubStr = "LLVM version ", N = length(SubStr),
case string:str(OptStr, SubStr) of
0 -> % No opt available
- 0.0;
+ {0, 0};
S ->
- case string:to_float(string:sub_string(OptStr, S + N)) of
- {error, _} -> 0.0; %XXX: Assumes no revision numbers in versioning
- {Float, _} -> Float
+ case string:tokens(string:sub_string(OptStr, S + N), ".") of
+ [MajorS, MinorS | _] ->
+ case {string:to_integer(MajorS), string:to_integer(MinorS)} of
+ {{Major, ""}, {Minor, _}}
+ when is_integer(Major), is_integer(Minor) ->
+ {Major, Minor};
+ _ -> {0, 0}
+ end;
+ _ -> {0, 0} %XXX: Assumes no revision numbers in versioning
end
end.
diff --git a/lib/hipe/main/hipe.hrl.src b/lib/hipe/main/hipe.hrl.src
index e74f31b19d..53b59f88f0 100644
--- a/lib/hipe/main/hipe.hrl.src
+++ b/lib/hipe/main/hipe.hrl.src
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -151,7 +152,7 @@
STMNT,
?untagged_msg(Msg ++ "~.2f s\n",[hipe_timing:stop_timer(Timer)/1000])).
-else.
--define(TIME_STMNT(STMNT,Msg,Timer),STMNT).
+-define(TIME_STMNT(STMNT,Msg,Timer), STMNT).
-endif.
-define(start_timer(Text), hipe_timing:start(Text, ?MODULE)).
@@ -161,22 +162,24 @@
-define(get_hipe_timer_val(Timer), get(Timer)).
-define(set_hipe_timer_val(Timer, Val), put(Timer, Val)).
-define(option_time(Stmnt, Text, Options),
- if true -> ?when_option(time, Options, ?start_timer(Text)),
- fun(R) ->
- ?when_option(time, Options, ?stop_timer(Text)),
- R
- end(Stmnt)end).
+ begin
+ ?when_option(time, Options, ?start_timer(Text)),
+ fun(R) ->
+ ?when_option(time, Options, ?stop_timer(Text)),
+ R
+ end(Stmnt)
+ end).
--define(option_start_time(Text,Options),
+-define(option_start_time(Text, Options),
?when_option(time, Options, ?start_timer(Text))).
--define(option_stop_time(Text,Options),
+-define(option_stop_time(Text, Options),
?when_option(time, Options, ?stop_timer(Text))).
-define(opt_start_timer(Text),
- hipe_timing:start_optional_timer(Text,?MODULE)).
+ hipe_timing:start_optional_timer(Text, ?MODULE)).
-define(opt_stop_timer(Text),
- hipe_timing:stop_optional_timer(Text,?MODULE)).
+ hipe_timing:stop_optional_timer(Text, ?MODULE)).
%%
%% Turn on instrumentation of the compiler.
@@ -186,15 +189,15 @@
-define(count_pre_ra_instructions(Options, NoInstrs),
?when_option(count_instrs, Options,
put(pre_ra_instrs,
- get(pre_ra_instrs)+ NoInstrs))).
+ get(pre_ra_instrs) + NoInstrs))).
-define(count_post_ra_instructions(Options, NoInstrs),
?when_option(count_instrs, Options,
put(post_ra_instrs,
- get(post_ra_instrs)+ NoInstrs))).
+ get(post_ra_instrs) + NoInstrs))).
-define(start_time_regalloc(Options),
?when_option(timeregalloc, Options,
- put(regalloctime1,erlang:statistics(runtime)))).
+ put(regalloctime1, erlang:statistics(runtime)))).
-define(stop_time_regalloc(Options),
?when_option(timeregalloc, Options,
put(regalloctime,
@@ -214,11 +217,11 @@
-define(count_pre_ra_temps(Options, NoTemps),
?when_option(count_temps, Options,
put(pre_ra_temps,
- get(pre_ra_temps)+ NoTemps))).
+ get(pre_ra_temps) + NoTemps))).
-define(count_post_ra_temps(Options, NoTemps),
?when_option(count_temps, Options,
put(post_ra_temps,
- get(post_ra_temps)+ NoTemps))).
+ get(post_ra_temps) + NoTemps))).
-define(inc_counter(Counter, Val),
case get(Counter) of
@@ -254,7 +257,7 @@
?count_post_ra_instructions(Options, NoInstrs),
?cons_counter(counter_mem_temps, get(counter_mfa_mem_temps)),
?cons_counter(ra_all_iterations_counter, get(ra_iteration_counter)),
- put(ra_iteration_counter,0),
+ put(ra_iteration_counter, 0),
?count_post_ra_temps(Options, NoTemps)
end).
@@ -263,12 +266,12 @@
put(spilledtemps, get(spilledtemps) + NoSpills))).
-define(optional_start_timer(Timer, Options),
- case lists:member(Timer, proplists:get_value(timers,Options++[{timers,[]}])) of
+ case lists:member(Timer, proplists:get_value(timers, Options++[{timers,[]}])) of
true -> ?start_hipe_timer(Timer);
false -> true
end).
-define(optional_stop_timer(Timer, Options),
- case lists:member(Timer, proplists:get_value(timers,Options++[{timers,[]}])) of
+ case lists:member(Timer, proplists:get_value(timers, Options++[{timers,[]}])) of
true -> ?stop_hipe_timer(Timer);
false -> true
end).
@@ -298,7 +301,8 @@
%% Records defined in the hipe module used in other parts of the compiler
%%----------------------------------------------------------------------------
--record(comp_servers, {pp_server :: pid(), range :: pid(), type :: pid()}).
+-type mpid() :: 'none' | pid().
+-record(comp_servers, {pp_server :: mpid(), range :: mpid(), type :: mpid()}).
%%----------------------------------------------------------------------------
%% Basic types of the 'hipe' application used in other parts of the system
@@ -314,4 +318,4 @@
'unknown' | {'reg' | 'fp_reg' | 'spill',
non_neg_integer()}}].
-type hipe_temp_map() :: tuple().
--type hipe_spill_map() :: [{non_neg_integer(), {'spill',non_neg_integer()}}].
+-type hipe_spill_map() :: [{non_neg_integer(), {'spill', non_neg_integer()}}].
diff --git a/lib/hipe/main/hipe_main.erl b/lib/hipe/main/hipe_main.erl
index 89b79998be..4b89feb48a 100644
--- a/lib/hipe/main/hipe_main.erl
+++ b/lib/hipe/main/hipe_main.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -54,7 +55,7 @@
%%=====================================================================
%% @spec compile_icode(MFA::mfa(),
-%% LinearIcode::#icode{},
+%% LinearIcode::icode(),
%% CompilerOptions::comp_options(),
%% CompServers::#comp_servers()) ->
%% {native,Platform,{unprofiled,NativeCode}} | {rtl,RTLCode}
@@ -68,7 +69,7 @@
%% generated). The compiler options must have already been expanded
%% (cf. `<a href="hipe.html">hipe:expand_options</a>'). </p>
--spec compile_icode(mfa(), #icode{}, comp_options(), #comp_servers{}) ->
+-spec compile_icode(mfa(), icode(), comp_options(), #comp_servers{}) ->
comp_icode_ret().
compile_icode(MFA, LinearIcode, Options, Servers) ->
@@ -229,10 +230,12 @@ get_pp_module(icode_liveness) -> hipe_icode_liveness;
get_pp_module(rtl_liveness) -> hipe_rtl_liveness.
perform_io(no_fun, _) -> ok;
-perform_io(Fun,PPServer) when is_pid(PPServer) ->
- PPServer ! {print,Fun};
-perform_io(Fun, undefined) ->
- Fun().
+perform_io(Fun, PPServer) when is_pid(PPServer) ->
+ PPServer ! {print, Fun},
+ ok;
+perform_io(Fun, none) ->
+ Fun(),
+ ok.
%%--------------------------------------------------------------------
@@ -281,8 +284,9 @@ icode_ssa_type(IcodeSSA, MFA, Options, Servers) ->
false -> AnnIcode1
end,
AnnIcode3 = icode_range_analysis(AnnIcode2, MFA, Options, Servers),
- pp(AnnIcode3, MFA, icode, pp_range_icode, Options, Servers),
- hipe_icode_type:unannotate_cfg(AnnIcode3)
+ AnnIcode4 = icode_eliminate_safe_calls(AnnIcode3, Options),
+ pp(AnnIcode4, MFA, icode, pp_range_icode, Options, Servers),
+ hipe_icode_type:unannotate_cfg(AnnIcode4)
end.
icode_ssa_convert(IcodeCfg, Options) ->
@@ -292,7 +296,7 @@ icode_ssa_convert(IcodeCfg, Options) ->
icode_ssa_const_prop(IcodeSSA, Options) ->
case proplists:get_bool(icode_ssa_const_prop, Options) of
true ->
- ?option_time(Tmp=hipe_icode_ssa_const_prop:propagate(IcodeSSA),
+ Tmp = ?option_time(hipe_icode_ssa_const_prop:propagate(IcodeSSA),
"Icode SSA sparse conditional constant propagation", Options),
?option_time(hipe_icode_ssa:remove_dead_code(Tmp),
"Icode SSA dead code elimination pass 1", Options);
@@ -331,6 +335,15 @@ icode_range_analysis(IcodeSSA, MFA, Options, Servers) ->
IcodeSSA
end.
+icode_eliminate_safe_calls(IcodeSSA, Options) ->
+ case proplists:get_bool(icode_call_elim, Options) of
+ true ->
+ ?option_time(hipe_icode_call_elim:cfg(IcodeSSA),
+ "Icode SSA safe call elimination", Options);
+ false ->
+ IcodeSSA
+ end.
+
icode_ssa_dead_code_elimination(IcodeSSA, Options) ->
IcodeSSA1 = ?option_time(hipe_icode_ssa:remove_dead_code(IcodeSSA),
"Icode SSA dead code elimination pass 2",
diff --git a/lib/hipe/misc/Makefile b/lib/hipe/misc/Makefile
index 16166f552c..72cfff21a8 100644
--- a/lib/hipe/misc/Makefile
+++ b/lib/hipe/misc/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -68,7 +69,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += -Werror +warn_export_vars +warn_missing_spec +warn_untyped_record
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/misc/hipe_consttab.erl b/lib/hipe/misc/hipe_consttab.erl
index 2b02f54b5c..226b20fa46 100644
--- a/lib/hipe/misc/hipe_consttab.erl
+++ b/lib/hipe/misc/hipe_consttab.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -86,7 +87,8 @@
% {NewTab, Lbl}
insert_sorted_block/4,
insert_block/3,
- %% insert_global_word/2,
+ insert_binary_const/3,
+ %% insert_global_word/2,
%% insert_global_block/4,
%% update_word/3, % update_word(ConstTab, Value) -> {NewTab, Lbl}
%% update_block/5,
@@ -195,6 +197,16 @@ insert_block({ConstTab, RefToLabels, NextLabel}, ElementType, InitList) ->
{ElementType,InitList}),
{insert_backrefs(NewTa, Id, ReferredLabels), Id}.
+%% @doc Inserts a binary constant literal into the const table.
+-spec insert_binary_const(hipe_consttab(), ct_alignment(), binary()) ->
+ {hipe_consttab(), hipe_constlbl()}.
+insert_binary_const(ConstTab, Alignment, Binary)
+ when (Alignment =:= 4 orelse Alignment =:= 8 orelse Alignment =:= 16
+ orelse Alignment =:= 32), is_binary(Binary),
+ size(Binary) rem Alignment =:= 0 ->
+ insert_const(ConstTab, block, Alignment, false,
+ {byte, binary_to_list(Binary)}).
+
%% @spec (ConstTab::hipe_consttab(), ElementType::element_type(),
%% InitList::block(), SortOrder) -> {hipe_consttab(), hipe_constlbl()}
diff --git a/lib/hipe/misc/hipe_consttab.hrl b/lib/hipe/misc/hipe_consttab.hrl
index aea3c5bc88..550da0455c 100644
--- a/lib/hipe/misc/hipe_consttab.hrl
+++ b/lib/hipe/misc/hipe_consttab.hrl
@@ -2,24 +2,25 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
%%-----------------------------------------------------------------------------
--type ct_alignment() :: 4 | 8.
+-type ct_alignment() :: 4 | 8 | 16 | 32.
-type hipe_constlbl() :: non_neg_integer().
-type hipe_consttab() :: {dict:dict(), [hipe_constlbl()], hipe_constlbl()}.
diff --git a/lib/hipe/misc/hipe_data_pp.erl b/lib/hipe/misc/hipe_data_pp.erl
index 0f206e8ade..6cdc6c5ad2 100644
--- a/lib/hipe/misc/hipe_data_pp.erl
+++ b/lib/hipe/misc/hipe_data_pp.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/misc/hipe_gensym.erl b/lib/hipe/misc/hipe_gensym.erl
index 4d2a237188..da7c4f9a5d 100644
--- a/lib/hipe/misc/hipe_gensym.erl
+++ b/lib/hipe/misc/hipe_gensym.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/misc/hipe_pack_constants.erl b/lib/hipe/misc/hipe_pack_constants.erl
index 300f9ae43a..b54830dd57 100644
--- a/lib/hipe/misc/hipe_pack_constants.erl
+++ b/lib/hipe/misc/hipe_pack_constants.erl
@@ -3,18 +3,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/misc/hipe_sdi.erl b/lib/hipe/misc/hipe_sdi.erl
index 9a2ff78ecf..fbb4b105f6 100644
--- a/lib/hipe/misc/hipe_sdi.erl
+++ b/lib/hipe/misc/hipe_sdi.erl
@@ -3,18 +3,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/misc/hipe_sdi.hrl b/lib/hipe/misc/hipe_sdi.hrl
index f89cae1529..a1e12f9df2 100644
--- a/lib/hipe/misc/hipe_sdi.hrl
+++ b/lib/hipe/misc/hipe_sdi.hrl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/opt/Makefile b/lib/hipe/opt/Makefile
index a21c543574..684d6f45b4 100644
--- a/lib/hipe/opt/Makefile
+++ b/lib/hipe/opt/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -63,7 +64,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec # +warn_untyped_record
+ERL_COMPILE_FLAGS += -Werror +warn_export_vars +warn_missing_spec # +warn_untyped_record
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/opt/hipe_schedule.erl b/lib/hipe/opt/hipe_schedule.erl
index 4f153e17ad..00ad487620 100644
--- a/lib/hipe/opt/hipe_schedule.erl
+++ b/lib/hipe/opt/hipe_schedule.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/opt/hipe_schedule_prio.erl b/lib/hipe/opt/hipe_schedule_prio.erl
index 4d078b007d..3dcc0845e0 100644
--- a/lib/hipe/opt/hipe_schedule_prio.erl
+++ b/lib/hipe/opt/hipe_schedule_prio.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/opt/hipe_spillmin.erl b/lib/hipe/opt/hipe_spillmin.erl
index df885a7dff..4eeb1d71db 100644
--- a/lib/hipe/opt/hipe_spillmin.erl
+++ b/lib/hipe/opt/hipe_spillmin.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/opt/hipe_spillmin_color.erl b/lib/hipe/opt/hipe_spillmin_color.erl
index 11a281100b..7c23de44b4 100644
--- a/lib/hipe/opt/hipe_spillmin_color.erl
+++ b/lib/hipe/opt/hipe_spillmin_color.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/opt/hipe_spillmin_scan.erl b/lib/hipe/opt/hipe_spillmin_scan.erl
index c58906c389..06b68e1934 100644
--- a/lib/hipe/opt/hipe_spillmin_scan.erl
+++ b/lib/hipe/opt/hipe_spillmin_scan.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/opt/hipe_target_machine.erl b/lib/hipe/opt/hipe_target_machine.erl
index be9f095429..f64bb8b518 100644
--- a/lib/hipe/opt/hipe_target_machine.erl
+++ b/lib/hipe/opt/hipe_target_machine.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/opt/hipe_ultra_mod2.erl b/lib/hipe/opt/hipe_ultra_mod2.erl
index b039eaee80..f28c4e6939 100644
--- a/lib/hipe/opt/hipe_ultra_mod2.erl
+++ b/lib/hipe/opt/hipe_ultra_mod2.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/opt/hipe_ultra_prio.erl b/lib/hipe/opt/hipe_ultra_prio.erl
index 9e2c1a0489..423dc0d6bf 100644
--- a/lib/hipe/opt/hipe_ultra_prio.erl
+++ b/lib/hipe/opt/hipe_ultra_prio.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/Makefile b/lib/hipe/ppc/Makefile
index 8bd2a8226c..1901dfa671 100644
--- a/lib/hipe/ppc/Makefile
+++ b/lib/hipe/ppc/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2012. All Rights Reserved.
+# Copyright Ericsson AB 2004-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -75,7 +76,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars
+ERL_COMPILE_FLAGS += -Werror +warn_export_vars
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/ppc/hipe_ppc.erl b/lib/hipe/ppc/hipe_ppc.erl
index 4014fc1561..380e791bc1 100644
--- a/lib/hipe/ppc/hipe_ppc.erl
+++ b/lib/hipe/ppc/hipe_ppc.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -166,8 +167,10 @@ temp_is_precoloured(#ppc_temp{reg=Reg,type=Type}) ->
_ -> hipe_ppc_registers:is_precoloured_gpr(Reg)
end.
-mk_simm16(Value) -> #ppc_simm16{value=Value}.
-mk_uimm16(Value) -> #ppc_uimm16{value=Value}.
+mk_simm16(Value) when Value >= -(1 bsl 15), Value < (1 bsl 15) ->
+ #ppc_simm16{value=Value}.
+mk_uimm16(Value) when Value >= 0, Value < (1 bsl 16) ->
+ #ppc_uimm16{value=Value}.
mk_mfa(M, F, A) -> #ppc_mfa{m=M, f=F, a=A}.
@@ -239,7 +242,11 @@ mk_li(Dst, Value, Tail) -> % Dst can be R0
Value =< 16#7FFFFFFF ->
mk_li32(Dst, R0, Value, Tail);
true ->
- Highest = (Value bsr 48), % Value@highest
+ Highest = case (Value bsr 48) of % Value@highest
+ TopBitSet when TopBitSet >= (1 bsl 15) ->
+ TopBitSet - (1 bsl 16); % encoder needs it to be negative
+ FitsSimm16 -> FitsSimm16
+ end,
Higher = (Value bsr 32) band 16#FFFF, % Value@higher
High = (Value bsr 16) band 16#FFFF, % Value@h
Low = Value band 16#FFFF, % Value@l
diff --git a/lib/hipe/ppc/hipe_ppc.hrl b/lib/hipe/ppc/hipe_ppc.hrl
index 25e7ae0b5f..aa8ff4a3f7 100644
--- a/lib/hipe/ppc/hipe_ppc.hrl
+++ b/lib/hipe/ppc/hipe_ppc.hrl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/ppc/hipe_ppc_assemble.erl b/lib/hipe/ppc/hipe_ppc_assemble.erl
index 3ad91f4051..d89ff6235c 100644
--- a/lib/hipe/ppc/hipe_ppc_assemble.erl
+++ b/lib/hipe/ppc/hipe_ppc_assemble.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -49,7 +50,7 @@ assemble(CompiledCode, Closures, Exports, Options) ->
DataRelocs = hipe_pack_constants:mk_data_relocs(RefsFromConsts, LabelMap),
SSE = hipe_pack_constants:slim_sorted_exportmap(ExportMap,Closures,Exports),
SlimRefs = hipe_pack_constants:slim_refs(AccRefs),
- Bin = term_to_binary([{?VERSION_STRING(),?HIPE_SYSTEM_CRC},
+ Bin = term_to_binary([{?VERSION_STRING(),?HIPE_ERTS_CHECKSUM},
ConstAlign, ConstSize,
SC,
DataRelocs, % nee LM, LabelMap
@@ -174,7 +175,8 @@ do_slwi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 32 ->
{Dst, Src1, {sh,N}, {mb,0}, {me,31-N}}.
do_srwi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 32 ->
- {Dst, Src1, {sh,32-N}, {mb,N}, {me,31}}.
+ %% SH should be 0 (not 32) when N is 0
+ {Dst, Src1, {sh,(32-N) band 31}, {mb,N}, {me,31}}.
do_srawi_src2({uimm,N}) when is_integer(N), 0 =< N, N < 32 -> {sh,N}.
@@ -183,7 +185,8 @@ do_sldi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 64 ->
{Dst, Src1, {sh6,N}, {me6,63-N}}.
do_srdi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 64 ->
- {Dst, Src1, {sh6,64-N}, {mb6,N}}.
+ %% SH should be 0 (not 64) when N is 0
+ {Dst, Src1, {sh6,(64-N) band 63}, {mb6,N}}.
do_sradi_src2({uimm,N}) when is_integer(N), 0 =< N, N < 64 -> {sh6,N}.
@@ -245,6 +248,7 @@ do_load(I) ->
case LdOp of
'ld' -> do_disp_ds(Disp);
'ldu' -> do_disp_ds(Disp);
+ 'lwa' -> do_disp_ds(Disp);
_ -> do_disp(Disp)
end,
NewBase = do_reg(Base),
diff --git a/lib/hipe/ppc/hipe_ppc_cfg.erl b/lib/hipe/ppc/hipe_ppc_cfg.erl
index 13a7754831..34d4bf54c5 100644
--- a/lib/hipe/ppc/hipe_ppc_cfg.erl
+++ b/lib/hipe/ppc/hipe_ppc_cfg.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_defuse.erl b/lib/hipe/ppc/hipe_ppc_defuse.erl
index 03a8f82abf..77b84dc574 100644
--- a/lib/hipe/ppc/hipe_ppc_defuse.erl
+++ b/lib/hipe/ppc/hipe_ppc_defuse.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_encode.erl b/lib/hipe/ppc/hipe_ppc_encode.erl
index 97cb0bf635..793f6ccc02 100644
--- a/lib/hipe/ppc/hipe_ppc_encode.erl
+++ b/lib/hipe/ppc/hipe_ppc_encode.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/ppc/hipe_ppc_finalise.erl b/lib/hipe/ppc/hipe_ppc_finalise.erl
index c4b9526fec..8bb9520f89 100644
--- a/lib/hipe/ppc/hipe_ppc_finalise.erl
+++ b/lib/hipe/ppc/hipe_ppc_finalise.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_frame.erl b/lib/hipe/ppc/hipe_ppc_frame.erl
index 8a4d1906c0..ff0450270f 100644
--- a/lib/hipe/ppc/hipe_ppc_frame.erl
+++ b/lib/hipe/ppc/hipe_ppc_frame.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_liveness_all.erl b/lib/hipe/ppc/hipe_ppc_liveness_all.erl
index c9234e8100..cab7605967 100644
--- a/lib/hipe/ppc/hipe_ppc_liveness_all.erl
+++ b/lib/hipe/ppc/hipe_ppc_liveness_all.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_liveness_fpr.erl b/lib/hipe/ppc/hipe_ppc_liveness_fpr.erl
index ff9db21e2b..1437e27508 100644
--- a/lib/hipe/ppc/hipe_ppc_liveness_fpr.erl
+++ b/lib/hipe/ppc/hipe_ppc_liveness_fpr.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_liveness_gpr.erl b/lib/hipe/ppc/hipe_ppc_liveness_gpr.erl
index a55052b944..074fada918 100644
--- a/lib/hipe/ppc/hipe_ppc_liveness_gpr.erl
+++ b/lib/hipe/ppc/hipe_ppc_liveness_gpr.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_main.erl b/lib/hipe/ppc/hipe_ppc_main.erl
index 1d84f6db11..fd5cc2befb 100644
--- a/lib/hipe/ppc/hipe_ppc_main.erl
+++ b/lib/hipe/ppc/hipe_ppc_main.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_pp.erl b/lib/hipe/ppc/hipe_ppc_pp.erl
index f88e922808..e69e6b64a2 100644
--- a/lib/hipe/ppc/hipe_ppc_pp.erl
+++ b/lib/hipe/ppc/hipe_ppc_pp.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_ra.erl b/lib/hipe/ppc/hipe_ppc_ra.erl
index 3de7f48de1..87c776f5d1 100644
--- a/lib/hipe/ppc/hipe_ppc_ra.erl
+++ b/lib/hipe/ppc/hipe_ppc_ra.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_ra_finalise.erl b/lib/hipe/ppc/hipe_ppc_ra_finalise.erl
index 53f8b739c2..ea163221c2 100644
--- a/lib/hipe/ppc/hipe_ppc_ra_finalise.erl
+++ b/lib/hipe/ppc/hipe_ppc_ra_finalise.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_ra_ls.erl b/lib/hipe/ppc/hipe_ppc_ra_ls.erl
index 0b5d915ee8..6e8304467e 100644
--- a/lib/hipe/ppc/hipe_ppc_ra_ls.erl
+++ b/lib/hipe/ppc/hipe_ppc_ra_ls.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/ppc/hipe_ppc_ra_naive.erl b/lib/hipe/ppc/hipe_ppc_ra_naive.erl
index f0ca41b49e..24995be252 100644
--- a/lib/hipe/ppc/hipe_ppc_ra_naive.erl
+++ b/lib/hipe/ppc/hipe_ppc_ra_naive.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_ra_postconditions.erl b/lib/hipe/ppc/hipe_ppc_ra_postconditions.erl
index 142bce39cc..0b16ec3891 100644
--- a/lib/hipe/ppc/hipe_ppc_ra_postconditions.erl
+++ b/lib/hipe/ppc/hipe_ppc_ra_postconditions.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl b/lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl
index 889c5681ac..821aa66c11 100644
--- a/lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl
+++ b/lib/hipe/ppc/hipe_ppc_ra_postconditions_fp.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_ppc_registers.erl b/lib/hipe/ppc/hipe_ppc_registers.erl
index 74aeab3df4..f4781d5ed7 100644
--- a/lib/hipe/ppc/hipe_ppc_registers.erl
+++ b/lib/hipe/ppc/hipe_ppc_registers.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ppc/hipe_rtl_to_ppc.erl b/lib/hipe/ppc/hipe_rtl_to_ppc.erl
index a55fc137c3..a994659616 100644
--- a/lib/hipe/ppc/hipe_rtl_to_ppc.erl
+++ b/lib/hipe/ppc/hipe_rtl_to_ppc.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/regalloc/Makefile b/lib/hipe/regalloc/Makefile
index d4be79ea85..aaa4418f37 100644
--- a/lib/hipe/regalloc/Makefile
+++ b/lib/hipe/regalloc/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -76,7 +77,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars# +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += -Werror +warn_export_vars #+warn_missing_spec +warn_untyped_record
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/regalloc/hipe_adj_list.erl b/lib/hipe/regalloc/hipe_adj_list.erl
index b55b22cb22..de59da2410 100644
--- a/lib/hipe/regalloc/hipe_adj_list.erl
+++ b/lib/hipe/regalloc/hipe_adj_list.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_amd64_specific.erl b/lib/hipe/regalloc/hipe_amd64_specific.erl
index 91a8c7253a..6937e71ac7 100644
--- a/lib/hipe/regalloc/hipe_amd64_specific.erl
+++ b/lib/hipe/regalloc/hipe_amd64_specific.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_amd64_specific_sse2.erl b/lib/hipe/regalloc/hipe_amd64_specific_sse2.erl
index 5654455b44..50e5869d45 100644
--- a/lib/hipe/regalloc/hipe_amd64_specific_sse2.erl
+++ b/lib/hipe/regalloc/hipe_amd64_specific_sse2.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_amd64_specific_x87.erl b/lib/hipe/regalloc/hipe_amd64_specific_x87.erl
index b5e8253ae1..2160e93d24 100644
--- a/lib/hipe/regalloc/hipe_amd64_specific_x87.erl
+++ b/lib/hipe/regalloc/hipe_amd64_specific_x87.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_arm_specific.erl b/lib/hipe/regalloc/hipe_arm_specific.erl
index 246095e926..4e34cb1d99 100644
--- a/lib/hipe/regalloc/hipe_arm_specific.erl
+++ b/lib/hipe/regalloc/hipe_arm_specific.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_coalescing_regalloc.erl b/lib/hipe/regalloc/hipe_coalescing_regalloc.erl
index e231098e0a..e2f817d369 100644
--- a/lib/hipe/regalloc/hipe_coalescing_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_coalescing_regalloc.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl b/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
index 6ba4ac814e..bc6e442236 100644
--- a/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_ig.erl b/lib/hipe/regalloc/hipe_ig.erl
index 4991e73e53..8fd5d0df1f 100644
--- a/lib/hipe/regalloc/hipe_ig.erl
+++ b/lib/hipe/regalloc/hipe_ig.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_ig_moves.erl b/lib/hipe/regalloc/hipe_ig_moves.erl
index ebc6ebc20d..b679453de0 100644
--- a/lib/hipe/regalloc/hipe_ig_moves.erl
+++ b/lib/hipe/regalloc/hipe_ig_moves.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_ls_regalloc.erl b/lib/hipe/regalloc/hipe_ls_regalloc.erl
index 7a00a0534a..d24b803524 100644
--- a/lib/hipe/regalloc/hipe_ls_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_ls_regalloc.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_moves.erl b/lib/hipe/regalloc/hipe_moves.erl
index afec4aa4ce..39ccfb4a2f 100644
--- a/lib/hipe/regalloc/hipe_moves.erl
+++ b/lib/hipe/regalloc/hipe_moves.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_node_sets.erl b/lib/hipe/regalloc/hipe_node_sets.erl
index be43ff2bfd..01922a34d4 100644
--- a/lib/hipe/regalloc/hipe_node_sets.erl
+++ b/lib/hipe/regalloc/hipe_node_sets.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_optimistic_regalloc.erl b/lib/hipe/regalloc/hipe_optimistic_regalloc.erl
index 0278a896d2..2ed9ec3b45 100644
--- a/lib/hipe/regalloc/hipe_optimistic_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_optimistic_regalloc.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_ppc_specific.erl b/lib/hipe/regalloc/hipe_ppc_specific.erl
index dd2855208b..c49b1e510f 100644
--- a/lib/hipe/regalloc/hipe_ppc_specific.erl
+++ b/lib/hipe/regalloc/hipe_ppc_specific.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_ppc_specific_fp.erl b/lib/hipe/regalloc/hipe_ppc_specific_fp.erl
index 35623e7994..454aa4c686 100644
--- a/lib/hipe/regalloc/hipe_ppc_specific_fp.erl
+++ b/lib/hipe/regalloc/hipe_ppc_specific_fp.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_reg_worklists.erl b/lib/hipe/regalloc/hipe_reg_worklists.erl
index 897bf0ef77..88585f9f38 100644
--- a/lib/hipe/regalloc/hipe_reg_worklists.erl
+++ b/lib/hipe/regalloc/hipe_reg_worklists.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/regalloc/hipe_regalloc_loop.erl b/lib/hipe/regalloc/hipe_regalloc_loop.erl
index 428a82c87b..d29615a3a0 100644
--- a/lib/hipe/regalloc/hipe_regalloc_loop.erl
+++ b/lib/hipe/regalloc/hipe_regalloc_loop.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/regalloc/hipe_sparc_specific.erl b/lib/hipe/regalloc/hipe_sparc_specific.erl
index 7b8c62e802..8d34604f84 100644
--- a/lib/hipe/regalloc/hipe_sparc_specific.erl
+++ b/lib/hipe/regalloc/hipe_sparc_specific.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_sparc_specific_fp.erl b/lib/hipe/regalloc/hipe_sparc_specific_fp.erl
index 8a27f84e67..2edd3cb47e 100644
--- a/lib/hipe/regalloc/hipe_sparc_specific_fp.erl
+++ b/lib/hipe/regalloc/hipe_sparc_specific_fp.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_spillcost.erl b/lib/hipe/regalloc/hipe_spillcost.erl
index 04b25f6339..b241e637d9 100644
--- a/lib/hipe/regalloc/hipe_spillcost.erl
+++ b/lib/hipe/regalloc/hipe_spillcost.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_spillcost.hrl b/lib/hipe/regalloc/hipe_spillcost.hrl
index e736a561d7..3cadcbe432 100644
--- a/lib/hipe/regalloc/hipe_spillcost.hrl
+++ b/lib/hipe/regalloc/hipe_spillcost.hrl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_temp_map.erl b/lib/hipe/regalloc/hipe_temp_map.erl
index 85678edd54..4085a0e1a7 100644
--- a/lib/hipe/regalloc/hipe_temp_map.erl
+++ b/lib/hipe/regalloc/hipe_temp_map.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_x86_specific.erl b/lib/hipe/regalloc/hipe_x86_specific.erl
index 0f490ba14d..4edf8674b7 100644
--- a/lib/hipe/regalloc/hipe_x86_specific.erl
+++ b/lib/hipe/regalloc/hipe_x86_specific.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/regalloc/hipe_x86_specific_x87.erl b/lib/hipe/regalloc/hipe_x86_specific_x87.erl
index 7fd80b63d8..ece07cb2f9 100644
--- a/lib/hipe/regalloc/hipe_x86_specific_x87.erl
+++ b/lib/hipe/regalloc/hipe_x86_specific_x87.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/Makefile b/lib/hipe/rtl/Makefile
index 751e87636a..b4cdf8b1f2 100644
--- a/lib/hipe/rtl/Makefile
+++ b/lib/hipe/rtl/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2013. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -74,7 +75,7 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
include ../native.mk
-ERL_COMPILE_FLAGS += +inline +warn_unused_import +warn_exported_vars
+ERL_COMPILE_FLAGS += -Werror +inline +warn_unused_import +warn_export_vars
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/rtl/hipe_icode2rtl.erl b/lib/hipe/rtl/hipe_icode2rtl.erl
index 483d0b37f7..22feca47cc 100644
--- a/lib/hipe/rtl/hipe_icode2rtl.erl
+++ b/lib/hipe/rtl/hipe_icode2rtl.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_rtl.erl b/lib/hipe/rtl/hipe_rtl.erl
index 2f62dd79ad..0726827299 100644
--- a/lib/hipe/rtl/hipe_rtl.erl
+++ b/lib/hipe/rtl/hipe_rtl.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -365,7 +366,7 @@
-export([subst_uses_llvm/2]).
--export_type([alub_cond/0]).
+-export_type([alub_cond/0, rtl/0]).
%%
%% RTL
@@ -383,6 +384,7 @@
label_range, %% {Min,Max} First and last name used for labels
info=[] %% A keylist with arbitrary information.
}).
+-opaque rtl() :: #rtl{}.
mk_rtl(Fun, ArgList, Closure, Leaf, Code, Data, VarRange, LabelRange) ->
#rtl{'fun'=Fun, arglist=ArgList, code=Code,
@@ -413,7 +415,9 @@ rtl_info_update(Rtl, Info) -> Rtl#rtl{info=Info}.
%% move
%%
-mk_move(Dst, Src) -> false = is_fpreg(Dst), false = is_fpreg(Src), #move{dst=Dst, src=Src}.
+mk_move(Dst, Src) ->
+ false = is_fpreg(Dst), false = is_fpreg(Src),
+ #move{dst=Dst, src=Src}.
move_dst(#move{dst=Dst}) -> Dst.
move_dst_update(M, NewDst) -> false = is_fpreg(NewDst), M#move{dst=NewDst}.
move_src(#move{src=Src}) -> Src.
diff --git a/lib/hipe/rtl/hipe_rtl.hrl b/lib/hipe/rtl/hipe_rtl.hrl
index fbdf9ac524..cc76e7e5c4 100644
--- a/lib/hipe/rtl/hipe_rtl.hrl
+++ b/lib/hipe/rtl/hipe_rtl.hrl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_rtl_arch.erl b/lib/hipe/rtl/hipe_rtl_arch.erl
index 99eb80f3d1..397b96120e 100644
--- a/lib/hipe/rtl/hipe_rtl_arch.erl
+++ b/lib/hipe/rtl/hipe_rtl_arch.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_rtl_arith.inc b/lib/hipe/rtl/hipe_rtl_arith.inc
index 1d13e59420..0c396c8e76 100644
--- a/lib/hipe/rtl/hipe_rtl_arith.inc
+++ b/lib/hipe/rtl/hipe_rtl_arith.inc
@@ -3,18 +3,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -29,13 +30,13 @@
%% Returns a tuple
%% {Res, Sign, Zero, Overflow, Carry}
%% Res will be a number in the range
-%% MAX_SIGNED_INT >= Res >= MIN_SIGNED_INT
+%% MAX_UNSIGNED_INT >= Res >= 0
%% The other four values are flags that are either true or false
%%
eval_alu(Op, Arg1, Arg2)
- when Arg1 =< ?MAX_SIGNED_INT,
+ when Arg1 =< ?MAX_UNSIGNED_INT,
Arg1 >= ?MIN_SIGNED_INT,
- Arg2 =< ?MAX_SIGNED_INT,
+ Arg2 =< ?MAX_UNSIGNED_INT,
Arg2 >= ?MIN_SIGNED_INT ->
Sign1 = sign_bit(Arg1),
@@ -46,73 +47,80 @@ eval_alu(Op, Arg1, Arg2)
Res = (Arg1 - Arg2) band ?WORDMASK,
N = sign_bit(Res),
Z = zero(Res),
- V = (Sign1 and (not Sign2) and (not N))
+ V = (Sign1 andalso (not Sign2) andalso (not N))
or
- ((not Sign1) and Sign2 and N),
- C = ((not Sign1) and Sign2)
+ ((not Sign1) andalso Sign2 andalso N),
+ C = ((not Sign1) andalso Sign2)
or
- (N and ((not Sign1) or Sign2));
+ (N andalso ((not Sign1) orelse Sign2)),
+ {Res, N, Z, V, C};
'add' ->
Res = (Arg1 + Arg2) band ?WORDMASK,
N = sign_bit(Res),
Z = zero(Res),
- V = (Sign1 and Sign2 and (not N))
+ V = (Sign1 andalso Sign2 andalso (not N))
or
- ((not Sign1) and (not Sign2) and N),
- C = (Sign1 and Sign2)
+ ((not Sign1) andalso (not Sign2) andalso N),
+ C = (Sign1 andalso Sign2)
or
- ((not N) and (Sign1 or Sign2));
+ ((not N) andalso (Sign1 orelse Sign2)),
+ {Res, N, Z, V, C};
'mul' ->
FullRes = Arg1 * Arg2,
Res = FullRes band ?WORDMASK,
ResHi = FullRes bsr ?BITS,
N = sign_bit(Res),
Z = zero(Res),
- V = (N and (ResHi =/= -1)) or ((not N) and (ResHi =/= 0)),
- C = V;
+ V = (N andalso (ResHi =/= -1)) orelse ((not N) andalso (ResHi =/= 0)),
+ C = V,
+ {Res, N, Z, V, C};
'sra' ->
Res = (Arg1 bsr Arg2) band ?WORDMASK,
N = sign_bit(Res),
Z = zero(Res),
V = 0,
- C = 0;
+ C = 0,
+ {Res, N, Z, V, C};
'srl' ->
Res = (Arg1 bsr Arg2) band shiftmask(Arg2),
N = sign_bit(Res),
Z = zero(Res),
V = 0,
- C = 0;
+ C = 0,
+ {Res, N, Z, V, C};
'sll' ->
Res = (Arg1 bsl Arg2) band ?WORDMASK,
N = sign_bit(Res),
Z = zero(Res),
V = 0,
- C = 0;
+ C = 0,
+ {Res, N, Z, V, C};
'or' ->
Res = (Arg1 bor Arg2) band ?WORDMASK,
N = sign_bit(Res),
Z = zero(Res),
V = 0,
- C = 0;
+ C = 0,
+ {Res, N, Z, V, C};
'and' ->
Res = (Arg1 band Arg2) band ?WORDMASK,
N = sign_bit(Res),
Z = zero(Res),
V = 0,
- C = 0;
+ C = 0,
+ {Res, N, Z, V, C};
'xor' ->
Res = (Arg1 bxor Arg2) band ?WORDMASK,
N = sign_bit(Res),
Z = zero(Res),
V = 0,
- C = 0;
+ C = 0,
+ {Res, N, Z, V, C};
Op ->
- Res = N = Z = V = C = 0,
?EXIT({"unknown alu op", Op})
- end,
- {two_comp_to_erl(Res), N, Z, V, C};
+ end;
eval_alu(Op, Arg1, Arg2) ->
- ?EXIT({argument_overflow,Op,Arg1,Arg2}).
+ ?EXIT({argument_overflow, Op, Arg1, Arg2}).
%% Björn & Bjarni:
%% We need to be able to do evaluations based only on the bits, since
@@ -129,9 +137,9 @@ eval_cond_bits(Cond, N, Z, V, C) ->
'ne' ->
not Z;
'gt' ->
- not (Z or (N xor V));
+ not (Z orelse (N xor V));
'gtu' ->
- not (C or Z);
+ not (C orelse Z);
'ge' ->
not (N xor V);
'geu'->
@@ -141,9 +149,9 @@ eval_cond_bits(Cond, N, Z, V, C) ->
'ltu'->
C;
'le' ->
- Z or (N xor V);
+ Z orelse (N xor V);
'leu'->
- C or Z;
+ C orelse Z;
'overflow' ->
V;
'not_overflow' ->
@@ -161,16 +169,9 @@ eval_cond(Cond, Arg1, Arg2) ->
sign_bit(Val) ->
((Val bsr ?SIGN_BIT) band 1) =:= 1.
-two_comp_to_erl(V) ->
- if V > ?MAX_SIGNED_INT ->
- - ((?MAX_UNSIGNED_INT + 1) - V);
- true -> V
- end.
-
shiftmask(Arg) ->
Setbits = ?BITS - Arg,
(1 bsl Setbits) - 1.
zero(Val) ->
Val =:= 0.
-
diff --git a/lib/hipe/rtl/hipe_rtl_arith_32.erl b/lib/hipe/rtl/hipe_rtl_arith_32.erl
index a8a6043cda..12075ed609 100644
--- a/lib/hipe/rtl/hipe_rtl_arith_32.erl
+++ b/lib/hipe/rtl/hipe_rtl_arith_32.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -23,7 +24,8 @@
%% Filename : hipe_rtl_arith_32.erl
%% Module : hipe_rtl_arith_32
%% Purpose : To implement 32-bit RTL-arithmetic
-%% Notes : The arithmetic works on 32-bit signed integers.
+%% Notes : The arithmetic works on 32-bit signed and unsigned
+%% integers.
%% The implementation is taken from the implementation
%% of arithmetic on SPARC.
%% XXX: This code is seldom used, and hence also
diff --git a/lib/hipe/rtl/hipe_rtl_arith_64.erl b/lib/hipe/rtl/hipe_rtl_arith_64.erl
index d0d576b65e..6dac8fb145 100644
--- a/lib/hipe/rtl/hipe_rtl_arith_64.erl
+++ b/lib/hipe/rtl/hipe_rtl_arith_64.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_rtl_binary.erl b/lib/hipe/rtl/hipe_rtl_binary.erl
index 5ea51acedb..fb9c0c196d 100644
--- a/lib/hipe/rtl/hipe_rtl_binary.erl
+++ b/lib/hipe/rtl/hipe_rtl_binary.erl
@@ -1,18 +1,20 @@
+%% -*- erlang-indent-level: 2 -*-
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
@@ -27,11 +29,20 @@
-export([gen_rtl/7]).
+-export([floorlog2/1, get_word_integer/4, make_size/3, make_size/4]).
+
+%%--------------------------------------------------------------------
+
+-define(BYTE_SHIFT, 3). %% Turn bits into bytes or vice versa
+-define(BYTE_SIZE, 8).
+
+%%--------------------------------------------------------------------
+
gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SysLimName, ConstTab) ->
case type_of_operation(BsOP) of
match ->
{hipe_rtl_binary_match:gen_rtl(
- BsOP, Dst, Args, TrueLblName, FalseLblName),ConstTab};
+ BsOP, Dst, Args, TrueLblName, FalseLblName),ConstTab};
construct ->
hipe_rtl_binary_construct:gen_rtl(
BsOP, Dst, Args, TrueLblName, FalseLblName, SysLimName, ConstTab)
@@ -61,7 +72,7 @@ type_of_operation({bs_init,_,_}) -> construct;
type_of_operation({bs_init_bits,_}) -> construct;
type_of_operation({bs_init_bits,_,_}) -> construct;
type_of_operation({bs_put_binary,_,_}) -> construct;
-type_of_operation({bs_put_binary_all,_}) -> construct;
+type_of_operation({bs_put_binary_all,_,_}) -> construct;
type_of_operation({bs_put_float,_,_,_}) -> construct;
type_of_operation({bs_put_integer,_,_,_}) -> construct;
type_of_operation({bs_put_string,_,_}) -> construct;
@@ -78,3 +89,133 @@ type_of_operation(bs_final) -> construct;
type_of_operation({bs_append,_,_,_,_}) -> construct;
type_of_operation({bs_private_append,_,_}) -> construct;
type_of_operation(bs_init_writable) -> construct.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Small utility functions:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+create_lbls(X) when X > 0 ->
+ [hipe_rtl:mk_new_label()|create_lbls(X-1)];
+create_lbls(0) ->
+ [].
+
+%%------------------------------------------------------------------------------
+%% Utilities used by both hipe_rtl_binary_construct and hipe_rtl_binary_match
+%%------------------------------------------------------------------------------
+
+get_word_integer(Var, Register, SystemLimitLblName, FalseLblName) ->
+ [EndLbl] = create_lbls(1),
+ EndName = hipe_rtl:label_name(EndLbl),
+ get_word_integer(Var, Register,SystemLimitLblName, FalseLblName, EndName, EndName,
+ [EndLbl]).
+
+get_word_integer(Var, Register, SystemLimitLblName, FalseLblName, TrueLblName,
+ BigLblName, Tail) ->
+ [FixnumLbl, NotFixnumLbl, BignumLbl, SuccessLbl] = create_lbls(4),
+ [hipe_tagscheme:test_fixnum(Var, hipe_rtl:label_name(FixnumLbl),
+ hipe_rtl:label_name(NotFixnumLbl), 0.99),
+ FixnumLbl,
+ hipe_tagscheme:fixnum_ge(Var, hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(0)),
+ hipe_rtl:label_name(SuccessLbl), FalseLblName,
+ 0.99),
+ SuccessLbl,
+ hipe_tagscheme:untag_fixnum(Register, Var),
+ hipe_rtl:mk_goto(TrueLblName),
+ NotFixnumLbl,
+ hipe_tagscheme:test_pos_bignum_arity(Var, 1, hipe_rtl:label_name(BignumLbl),
+ FalseLblName, SystemLimitLblName, 0.99),
+ BignumLbl,
+ hipe_tagscheme:unsafe_get_one_word_pos_bignum(Register, Var),
+ hipe_rtl:mk_goto(BigLblName) | Tail].
+
+make_size(UnitImm, BitsVar, FailLblName) ->
+ make_size(UnitImm, BitsVar, FailLblName, FailLblName).
+
+make_size(1, BitsVar, OverflowLblName, FalseLblName) ->
+ DstReg = hipe_rtl:mk_new_reg_gcsafe(),
+ {get_word_integer(BitsVar, DstReg, OverflowLblName, FalseLblName), DstReg};
+make_size(?BYTE_SIZE, BitsVar, OverflowLblName, FalseLblName) ->
+ DstReg = hipe_rtl:mk_new_reg_gcsafe(),
+ [FixnumLbl, BignumLbl] = create_lbls(2),
+ WordBits = hipe_rtl_arch:word_size() * ?BYTE_SIZE,
+ FixnumLblName = hipe_rtl:label_name(FixnumLbl),
+ Tail = [BignumLbl,
+ hipe_rtl:mk_branch(DstReg, 'ltu',
+ hipe_rtl:mk_imm(1 bsl (WordBits - ?BYTE_SHIFT)),
+ FixnumLblName, OverflowLblName, 0.99),
+ FixnumLbl,
+ hipe_rtl:mk_alu(DstReg, DstReg, sll, hipe_rtl:mk_imm(?BYTE_SHIFT))],
+ Code = get_word_integer(BitsVar, DstReg, OverflowLblName, FalseLblName,
+ FixnumLblName, hipe_rtl:label_name(BignumLbl), Tail),
+ {Code, DstReg};
+make_size(UnitImm, BitsVar, OverflowLblName, FalseLblName) ->
+ DstReg = hipe_rtl:mk_new_reg_gcsafe(),
+ UnitList = number2list(UnitImm),
+ Code = multiply_code(UnitList, BitsVar, DstReg, OverflowLblName, FalseLblName),
+ {Code, DstReg}.
+
+multiply_code(List=[Head|_Tail], Variable, Result, OverflowLblName,
+ FalseLblName) ->
+ Test = set_high(Head),
+ Tmp1 = hipe_rtl:mk_new_reg(),
+ SuccessLbl = hipe_rtl:mk_new_label(),
+ Register = hipe_rtl:mk_new_reg(),
+ Code = [hipe_rtl:mk_move(Result, hipe_rtl:mk_imm(0))|
+ get_word_integer(Variable, Register, OverflowLblName, FalseLblName)]
+ ++
+ [hipe_rtl:mk_alub(Tmp1, Register, 'and', hipe_rtl:mk_imm(Test),
+ eq, hipe_rtl:label_name(SuccessLbl),
+ OverflowLblName, 0.99),
+ SuccessLbl],
+ multiply_code(List, Register, Result, OverflowLblName, Tmp1, Code).
+
+multiply_code([ShiftSize|Rest], Register, Result, OverflowLblName, Tmp1,
+ OldCode) ->
+ SuccessLbl = hipe_rtl:mk_new_label(),
+ Code =
+ OldCode ++
+ [hipe_rtl:mk_alu(Tmp1, Register, sll, hipe_rtl:mk_imm(ShiftSize)),
+ hipe_rtl:mk_alub(Result, Tmp1, 'add', Result, not_overflow,
+ hipe_rtl:label_name(SuccessLbl), OverflowLblName, 0.99),
+ SuccessLbl],
+ multiply_code(Rest, Register, Result, OverflowLblName, Tmp1, Code);
+multiply_code([], _Register, _Result, _OverflowLblName, _Tmp1, Code) ->
+ Code.
+
+set_high(X) ->
+ WordBits = hipe_rtl_arch:word_size() * ?BYTE_SIZE,
+ set_high(min(X, WordBits), WordBits, 0).
+
+set_high(0, _, Y) ->
+ Y;
+set_high(X, WordBits, Y) ->
+ set_high(X-1, WordBits, Y+(1 bsl (WordBits-X))).
+
+
+number2list(X) when is_integer(X), X >= 0 ->
+ number2list(X, []).
+
+number2list(1, Acc) ->
+ lists:reverse([0|Acc]);
+number2list(0, Acc) ->
+ lists:reverse(Acc);
+number2list(X, Acc) ->
+ F = floorlog2(X),
+ number2list(X-(1 bsl F), [F|Acc]).
+
+floorlog2(X) ->
+ %% Double-precision floats do not have enough precision to make floorlog2
+ %% exact for integers larger than 2^47.
+ Approx = round(math:log(X)/math:log(2)-0.5),
+ floorlog2_refine(X, Approx).
+
+floorlog2_refine(X, Approx) ->
+ if (1 bsl Approx) > X ->
+ floorlog2_refine(X, Approx - 1);
+ (1 bsl (Approx+1)) > X ->
+ Approx;
+ true ->
+ floorlog2_refine(X, Approx + 1)
+ end.
diff --git a/lib/hipe/rtl/hipe_rtl_binary_construct.erl b/lib/hipe/rtl/hipe_rtl_binary_construct.erl
index 29993b9715..367d76b24d 100644
--- a/lib/hipe/rtl/hipe_rtl_binary_construct.erl
+++ b/lib/hipe/rtl/hipe_rtl_binary_construct.erl
@@ -2,37 +2,38 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
%% ====================================================================
-%% Module : hipe_rtl_inline_bs_ops
+%% Module : hipe_rtl_binary_construct
%% Purpose :
%% Notes :
-%% History : * 2001-06-14 Erik Johansson ([email protected]): Created.
+%% History : Written mostly by Per Gustafsson
%% ====================================================================
%% Exports :
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(hipe_rtl_binary_construct).
+
-export([gen_rtl/7]).
--import(hipe_tagscheme, [set_field_from_term/3,
- get_field_from_term/3,
- set_field_from_pointer/3,
- get_field_from_pointer/3]).
+
+-import(hipe_rtl_binary, [get_word_integer/4]).
+
%%-------------------------------------------------------------------------
-include("../main/hipe.hrl").
@@ -45,7 +46,6 @@
-define(BYTE_SIZE, 8).
-define(MAX_BINSIZE, ((1 bsl ((hipe_rtl_arch:word_size()*?BYTE_SIZE)-3)) - 1)).
-
%% -------------------------------------------------------------------------
%% The code is generated as a list of lists, it will be flattened later.
%%
@@ -56,12 +56,12 @@ gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab
{bs_put_string, String, SizeInBytes} ->
[NewOffset] = get_real(Dst),
[Base, Offset] = Args,
- put_string(NewOffset, ConstTab, String, SizeInBytes, Base, Offset,
+ put_string(NewOffset, ConstTab, String, SizeInBytes, Base, Offset,
TrueLblName);
- _ ->
- Code =
+ _ ->
+ Code =
case BsOP of
- {bs_init, Size, _Flags} ->
+ {bs_init, Size, _Flags} ->
[] = Args,
[Dst0, Base, Offset] = Dst,
case is_illegal_const(Size bsl 3) of
@@ -70,14 +70,14 @@ gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab
false ->
const_init2(Size, Dst0, Base, Offset, TrueLblName)
end;
-
- {bs_init, _Flags} ->
+
+ {bs_init, _Flags} ->
[Size] = Args,
[Dst0, Base, Offset] = Dst,
- var_init2(Size, Dst0, Base, Offset, TrueLblName,
+ var_init2(Size, Dst0, Base, Offset, TrueLblName,
SystemLimitLblName, FalseLblName);
- {bs_init_bits, Size, _Flags} ->
+ {bs_init_bits, Size, _Flags} ->
[] = Args,
[Dst0, Base, Offset] = Dst,
case is_illegal_const(Size) of
@@ -86,18 +86,19 @@ gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab
false ->
const_init_bits(Size, Dst0, Base, Offset, TrueLblName)
end;
-
- {bs_init_bits, _Flags} ->
+
+ {bs_init_bits, _Flags} ->
[Size] = Args,
[Dst0, Base, Offset] = Dst,
- var_init_bits(Size, Dst0, Base, Offset, TrueLblName,
+ var_init_bits(Size, Dst0, Base, Offset, TrueLblName,
SystemLimitLblName, FalseLblName);
-
- {bs_put_binary_all, _Flags} ->
+
+ {bs_put_binary_all, Unit, _Flags} ->
[Src, Base, Offset] = Args,
[NewOffset] = get_real(Dst),
- put_binary_all(NewOffset, Src, Base, Offset, TrueLblName, FalseLblName);
-
+ put_binary_all(NewOffset, Src, Base, Offset, Unit,
+ TrueLblName, FalseLblName);
+
{bs_put_binary, Size, _Flags} ->
case is_illegal_const(Size) of
true ->
@@ -106,17 +107,19 @@ gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab
[NewOffset] = get_real(Dst),
case Args of
[Src, Base, Offset] ->
- put_static_binary(NewOffset, Src, Size, Base, Offset,
+ put_static_binary(NewOffset, Src, Size, Base, Offset,
TrueLblName, FalseLblName);
[Src, Bits, Base, Offset] ->
- {SizeCode, SizeReg} = make_size(Size, Bits, FalseLblName),
- InCode = put_dynamic_binary(NewOffset, Src, SizeReg, Base,
+ {SizeCode, SizeReg} =
+ hipe_rtl_binary:make_size(Size, Bits, SystemLimitLblName,
+ FalseLblName),
+ InCode = put_dynamic_binary(NewOffset, Src, SizeReg, Base,
Offset, TrueLblName, FalseLblName),
SizeCode ++ InCode
end
end;
-
- {bs_put_float, Size, Flags, ConstInfo} ->
+
+ {bs_put_float, Size, Flags, ConstInfo} ->
[NewOffset] = get_real(Dst),
Aligned = aligned(Flags),
LittleEndian = littleendian(Flags),
@@ -126,102 +129,108 @@ gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab
false ->
case Args of
[Src, Base, Offset] ->
- CCode = static_float_c_code(NewOffset, Src, Base, Offset, Size, Flags,
+ CCode = static_float_c_code(NewOffset, Src, Base, Offset, Size, Flags,
TrueLblName, FalseLblName),
- put_float(NewOffset, Src, Base, Offset, Size, CCode, Aligned,
+ put_float(NewOffset, Src, Base, Offset, Size, CCode, Aligned,
LittleEndian, ConstInfo, TrueLblName);
[Src, Bits, Base, Offset] ->
- {SizeCode, SizeReg} = make_size(Size, Bits, FalseLblName),
- InCode = float_c_code(NewOffset, Src, Base, Offset, SizeReg,
+ {SizeCode, SizeReg} =
+ hipe_rtl_binary:make_size(Size, Bits, SystemLimitLblName,
+ FalseLblName),
+ InCode = float_c_code(NewOffset, Src, Base, Offset, SizeReg,
Flags, TrueLblName, FalseLblName),
SizeCode ++ InCode
end
end;
- {bs_put_integer, Size, Flags, ConstInfo} ->
- Aligned = aligned(Flags),
+ {bs_put_integer, Size, Flags, ConstInfo} ->
+ Aligned = aligned(Flags),
LittleEndian = littleendian(Flags),
[NewOffset] = get_real(Dst),
case is_illegal_const(Size) of
true ->
[hipe_rtl:mk_goto(FalseLblName)];
false ->
- case ConstInfo of
+ case ConstInfo of
fail ->
[hipe_rtl:mk_goto(FalseLblName)];
- _ ->
- case Args of
- [Src, Base, Offset] ->
+ _ ->
+ case Args of
+ [Src, Base, Offset] ->
CCode = static_int_c_code(NewOffset, Src,
- Base, Offset, Size,
- Flags, TrueLblName,
+ Base, Offset, Size,
+ Flags, TrueLblName,
FalseLblName),
- put_static_int(NewOffset, Src, Base, Offset, Size,
- CCode, Aligned, LittleEndian, TrueLblName);
- [Src, Bits, Base, Offset] ->
- {SizeCode, SizeReg} = make_size(Size, Bits,
+ put_static_int(NewOffset, Src, Base, Offset, Size,
+ CCode, Aligned, LittleEndian, TrueLblName);
+ [Src, Bits, Base, Offset] ->
+ {SizeCode, SizeReg} =
+ hipe_rtl_binary:make_size(Size, Bits,
+ SystemLimitLblName,
FalseLblName),
CCode = int_c_code(NewOffset, Src, Base,
- Offset, SizeReg, Flags,
- TrueLblName, FalseLblName),
+ Offset, SizeReg, Flags,
+ TrueLblName, FalseLblName),
InCode =
- put_dynamic_int(NewOffset, Src, Base, Offset,
+ put_dynamic_int(NewOffset, Src, Base, Offset,
SizeReg, CCode, Aligned,
- LittleEndian, TrueLblName),
- SizeCode ++ InCode
- end
- end
+ LittleEndian, TrueLblName),
+ SizeCode ++ InCode
+ end
+ end
end;
-
- {unsafe_bs_put_integer, 0, _Flags, _ConstInfo} ->
- [NewOffset] = get_real(Dst),
+
+ {unsafe_bs_put_integer, 0, _Flags, _ConstInfo} ->
+ [NewOffset] = get_real(Dst),
case Args of
[_Src, _Base, Offset] ->
[hipe_rtl:mk_move(NewOffset,Offset),
- hipe_rtl:mk_goto(TrueLblName)];
- [_Src, _Bits, _Base, Offset] ->
+ hipe_rtl:mk_goto(TrueLblName)];
+ [_Src, _Bits, _Base, Offset] ->
[hipe_rtl:mk_move(NewOffset,Offset),
- hipe_rtl:mk_goto(TrueLblName)]
- end;
-
- {unsafe_bs_put_integer, Size, Flags, ConstInfo} ->
+ hipe_rtl:mk_goto(TrueLblName)]
+ end;
+
+ {unsafe_bs_put_integer, Size, Flags, ConstInfo} ->
case is_illegal_const(Size) of
true ->
[hipe_rtl:mk_goto(FalseLblName)];
false ->
Aligned = aligned(Flags),
- LittleEndian = littleendian(Flags),
- [NewOffset] = get_real(Dst),
- case ConstInfo of
+ LittleEndian = littleendian(Flags),
+ [NewOffset] = get_real(Dst),
+ case ConstInfo of
fail ->
- [hipe_rtl:mk_goto(FalseLblName)];
- _ ->
- case Args of
- [Src, Base, Offset] ->
+ [hipe_rtl:mk_goto(FalseLblName)];
+ _ ->
+ case Args of
+ [Src, Base, Offset] ->
CCode = static_int_c_code(NewOffset, Src,
- Base, Offset, Size,
- Flags, TrueLblName,
+ Base, Offset, Size,
+ Flags, TrueLblName,
FalseLblName),
- put_unsafe_static_int(NewOffset, Src, Base,
+ put_unsafe_static_int(NewOffset, Src, Base,
Offset, Size,
- CCode, Aligned, LittleEndian,
- TrueLblName);
- [Src, Bits, Base, Offset] ->
- {SizeCode, SizeReg} = make_size(Size, Bits,
- FalseLblName),
+ CCode, Aligned, LittleEndian,
+ TrueLblName);
+ [Src, Bits, Base, Offset] ->
+ {SizeCode, SizeReg} =
+ hipe_rtl_binary:make_size(Size, Bits,
+ SystemLimitLblName,
+ FalseLblName),
CCode = int_c_code(NewOffset, Src, Base,
- Offset, SizeReg, Flags,
- TrueLblName, FalseLblName),
+ Offset, SizeReg, Flags,
+ TrueLblName, FalseLblName),
InCode =
- put_unsafe_dynamic_int(NewOffset, Src, Base,
- Offset, SizeReg, CCode,
- Aligned, LittleEndian,
+ put_unsafe_dynamic_int(NewOffset, Src, Base,
+ Offset, SizeReg, CCode,
+ Aligned, LittleEndian,
TrueLblName),
- SizeCode ++ InCode
- end
+ SizeCode ++ InCode
+ end
end
- end;
-
+ end;
+
bs_utf8_size ->
case Dst of
[_DstVar] ->
@@ -264,13 +273,13 @@ gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab
[hipe_rtl:mk_call([], bs_validate_unicode, Args,
TrueLblName, FalseLblName, not_remote)];
- bs_final ->
+ bs_final ->
Zero = hipe_rtl:mk_imm(0),
- [Src, Offset] = Args,
+ [Src, Offset] = Args,
[BitSize, ByteSize] = create_regs(2),
[ShortLbl, LongLbl] = create_lbls(2),
- case Dst of
- [DstVar] ->
+ case Dst of
+ [DstVar] ->
[hipe_rtl:mk_alub(BitSize, Offset, 'and', ?LOW_BITS, eq,
hipe_rtl:label_name(ShortLbl),
hipe_rtl:label_name(LongLbl)), ShortLbl,
@@ -280,11 +289,11 @@ gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab
hipe_rtl:mk_alu(ByteSize, Offset, 'srl', ?BYTE_SHIFT),
hipe_tagscheme:mk_sub_binary(DstVar, ByteSize,
Zero, BitSize, Zero, Src),
- hipe_rtl:mk_goto(TrueLblName)];
+ hipe_rtl:mk_goto(TrueLblName)];
[] ->
- [hipe_rtl:mk_goto(TrueLblName)]
- end;
-
+ [hipe_rtl:mk_goto(TrueLblName)]
+ end;
+
bs_init_writable ->
Zero = hipe_rtl:mk_imm(0),
[Size] = Args,
@@ -292,63 +301,66 @@ gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab
[SizeReg] = create_regs(1),
[Base] = create_unsafe_regs(1),
[hipe_rtl:mk_gctest(?PROC_BIN_WORDSIZE + ?SUB_BIN_WORDSIZE),
- check_and_untag_fixnum(Size, SizeReg, FalseLblName),
+ get_word_integer(Size, SizeReg, SystemLimitLblName, FalseLblName),
allocate_writable(DstVar, Base, SizeReg, Zero, Zero),
- hipe_rtl:mk_goto(TrueLblName)];
-
+ hipe_rtl:mk_goto(TrueLblName)];
+
{bs_private_append, _U, _F} ->
- [Size, Bin] = Args,
+ [Size, Bin] = Args,
[DstVar, Base, Offset] = Dst,
[ProcBin] = create_vars(1),
[SubSize, SizeReg, EndSubSize, EndSubBitSize] = create_regs(4),
SubBinSize = {sub_binary, binsize},
- [get_field_from_term({sub_binary, orig}, Bin, ProcBin),
- get_field_from_term(SubBinSize, Bin, SubSize),
- check_and_untag_fixnum(Size, SizeReg, FalseLblName),
+ [hipe_tagscheme:get_field_from_term({sub_binary, orig}, Bin, ProcBin),
+ hipe_tagscheme:get_field_from_term(SubBinSize, Bin, SubSize),
+ get_word_integer(Size, SizeReg, SystemLimitLblName, FalseLblName),
realloc_binary(SizeReg, ProcBin, Base),
calculate_sizes(Bin, SizeReg, Offset, EndSubSize, EndSubBitSize),
- set_field_from_term(SubBinSize, Bin, EndSubSize),
- set_field_from_term({sub_binary, bitsize}, Bin, EndSubBitSize),
+ hipe_tagscheme:set_field_from_term(SubBinSize, Bin, EndSubSize),
+ hipe_tagscheme:set_field_from_term({sub_binary, bitsize}, Bin, EndSubBitSize),
hipe_rtl:mk_move(DstVar, Bin),
hipe_rtl:mk_goto(TrueLblName)];
- {bs_append, _U, _F, _B, _Bla} ->
- [Size, Bin] = Args,
- [DstVar, Base, Offset] = Dst,
+ {bs_append, _U, _F, Unit, _Bla} ->
+ [Size, Bin] = Args,
+ [DstVar, Base, Offset] = Dst,
[ProcBin] = create_vars(1),
- [Flags, SizeReg, IsWritable, EndSubSize, EndSubBitSize] =
+ [Flags, SizeReg, IsWritable, EndSubSize, EndSubBitSize] =
create_regs(5),
- [ContLbl,ContLbl2,ContLbl3,WritableLbl,NotWritableLbl] = Lbls =
- create_lbls(5),
- [ContLblName, ContLbl2Name, ContLbl3Name, Writable, NotWritable] =
+ [ContLbl,ContLbl2,ContLbl3,ContLbl4,WritableLbl,NotWritableLbl] =
+ Lbls = create_lbls(6),
+ [ContLblName, ContLbl2Name, ContLbl3Name, ContLbl4Name,
+ Writable, NotWritable] =
[hipe_rtl:label_name(Lbl) || Lbl <- Lbls],
Zero = hipe_rtl:mk_imm(0),
SubIsWritable = {sub_binary, is_writable},
[hipe_rtl:mk_gctest(?SUB_BIN_WORDSIZE + ?PROC_BIN_WORDSIZE),
- check_and_untag_fixnum(Size, SizeReg, FalseLblName),
- hipe_tagscheme:test_bitstr(Bin, ContLblName, FalseLblName, 0.99),
- ContLbl,
- hipe_tagscheme:test_subbinary(Bin,ContLbl2Name, NotWritable),
+ get_word_integer(Size, SizeReg, SystemLimitLblName, FalseLblName),
+ hipe_tagscheme:test_bitstr(Bin, ContLblName, FalseLblName, 0.99),
+ ContLbl,
+ hipe_tagscheme:test_subbinary(Bin,ContLbl2Name, NotWritable),
ContLbl2,
- get_field_from_term(SubIsWritable, Bin, IsWritable),
+ hipe_tagscheme:get_field_from_term(SubIsWritable, Bin, IsWritable),
hipe_rtl:mk_branch(IsWritable, 'ne', Zero,
ContLbl3Name, NotWritable),
ContLbl3,
- get_field_from_term({sub_binary, orig}, Bin, ProcBin),
- get_field_from_term({proc_bin, flags}, ProcBin, Flags),
+ hipe_tagscheme:get_field_from_term({sub_binary, orig}, Bin, ProcBin),
+ hipe_tagscheme:get_field_from_term({proc_bin, flags}, ProcBin, Flags),
hipe_rtl:mk_alub(Flags, Flags, 'and',
- hipe_rtl:mk_imm(?PB_IS_WRITABLE),
- eq, NotWritable, Writable, 0.01),
+ hipe_rtl:mk_imm(?PB_IS_WRITABLE),
+ eq, NotWritable, ContLbl4Name, 0.01),
+ ContLbl4,
+ calculate_sizes(Bin, SizeReg, Offset, EndSubSize, EndSubBitSize),
+ is_divisible(Offset, Unit, Writable, FalseLblName),
WritableLbl,
- set_field_from_term(SubIsWritable, Bin, Zero),
+ hipe_tagscheme:set_field_from_term(SubIsWritable, Bin, Zero),
realloc_binary(SizeReg, ProcBin, Base),
- calculate_sizes(Bin, SizeReg, Offset, EndSubSize, EndSubBitSize),
hipe_tagscheme:mk_sub_binary(DstVar, EndSubSize, Zero,
EndSubBitSize, Zero,
hipe_rtl:mk_imm(1), ProcBin),
hipe_rtl:mk_goto(TrueLblName),
NotWritableLbl,
- not_writable_code(Bin, SizeReg, DstVar, Base, Offset,
+ not_writable_code(Bin, SizeReg, DstVar, Base, Offset, Unit,
TrueLblName, FalseLblName)]
end,
{Code, ConstTab}
@@ -360,7 +372,7 @@ gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-not_writable_code(Bin, SizeReg, Dst, Base, Offset,
+not_writable_code(Bin, SizeReg, Dst, Base, Offset, Unit,
TrueLblName, FalseLblName) ->
[SrcBase] = create_unsafe_regs(1),
[SrcOffset, SrcSize, TotSize, TotBytes, UsedBytes] = create_regs(5),
@@ -371,15 +383,15 @@ not_writable_code(Bin, SizeReg, Dst, Base, Offset,
hipe_rtl:mk_alu(TotBytes, TotSize, add, ?LOW_BITS),
hipe_rtl:mk_alu(TotBytes, TotBytes, srl, ?BYTE_SHIFT),
hipe_rtl:mk_alu(UsedBytes, TotBytes, sll, hipe_rtl:mk_imm(1)),
- hipe_rtl:mk_branch(UsedBytes, ge, hipe_rtl:mk_imm(256),
+ hipe_rtl:mk_branch(UsedBytes, geu, hipe_rtl:mk_imm(256),
AllLblName, IncLblName),
IncLbl,
hipe_rtl:mk_move(UsedBytes, hipe_rtl:mk_imm(256)),
AllLbl,
allocate_writable(Dst, Base, UsedBytes, TotBytes, TotSize),
- put_binary_all(Offset, Bin, Base, hipe_rtl:mk_imm(0),
+ put_binary_all(Offset, Bin, Base, hipe_rtl:mk_imm(0), Unit,
TrueLblName, FalseLblName)].
-
+
allocate_writable(Dst, Base, UsedBytes, TotBytes, TotSize) ->
Zero = hipe_rtl:mk_imm(0),
[NextLbl] = create_lbls(1),
@@ -396,17 +408,7 @@ allocate_writable(Dst, Base, UsedBytes, TotBytes, TotSize) ->
hipe_tagscheme:mk_sub_binary(Dst, EndSubSize, Zero, EndSubBitSize,
Zero, hipe_rtl:mk_imm(1), ProcBin)].
-check_and_untag_fixnum(Size, SizeReg, FalseLblName) ->
- [ContLbl,NextLbl] = Lbls = create_lbls(2),
- [ContLblName,NextLblName] = get_label_names(Lbls),
- [hipe_tagscheme:test_fixnum(Size, ContLblName, FalseLblName, 0.99),
- ContLbl,
- hipe_tagscheme:untag_fixnum(SizeReg,Size),
- hipe_rtl:mk_branch(SizeReg, ge, hipe_rtl:mk_imm(0), NextLblName,
- FalseLblName),
- NextLbl].
-
-realloc_binary(SizeReg, ProcBin, Base) ->
+realloc_binary(SizeReg, ProcBin, Base) ->
[NoReallocLbl, ReallocLbl, NextLbl, ContLbl] = Lbls = create_lbls(4),
[NoReallocLblName, ReallocLblName, NextLblName, ContLblName] =
[hipe_rtl:label_name(Lbl) || Lbl <- Lbls],
@@ -417,36 +419,36 @@ realloc_binary(SizeReg, ProcBin, Base) ->
ProcBinValTag = {proc_bin, val},
ProcBinBytesTag = {proc_bin, bytes},
BinOrigSizeTag = {binary, orig_size},
- [get_field_from_term(ProcBinSizeTag, ProcBin, PBSize),
+ [hipe_tagscheme:get_field_from_term(ProcBinSizeTag, ProcBin, PBSize),
hipe_rtl:mk_alu(Tmp, SizeReg, 'add', ?LOW_BITS),
hipe_rtl:mk_alu(ByteSize, Tmp, 'srl', ?BYTE_SHIFT),
hipe_rtl:mk_alu(ResultingSize, ByteSize, 'add', PBSize),
- set_field_from_term(ProcBinSizeTag, ProcBin, ResultingSize),
- get_field_from_term(ProcBinFlagsTag, ProcBin, Flags),
+ hipe_tagscheme:set_field_from_term(ProcBinSizeTag, ProcBin, ResultingSize),
+ hipe_tagscheme:get_field_from_term(ProcBinFlagsTag, ProcBin, Flags),
hipe_rtl:mk_alu(Flags, Flags, 'or', hipe_rtl:mk_imm(?PB_ACTIVE_WRITER)),
- set_field_from_term(ProcBinFlagsTag, ProcBin, Flags),
- get_field_from_term(ProcBinValTag, ProcBin, BinPointer),
- get_field_from_pointer(BinOrigSizeTag, BinPointer, OrigSize),
- hipe_rtl:mk_branch(OrigSize, 'lt', ResultingSize,
+ hipe_tagscheme:set_field_from_term(ProcBinFlagsTag, ProcBin, Flags),
+ hipe_tagscheme:get_field_from_term(ProcBinValTag, ProcBin, BinPointer),
+ hipe_tagscheme:get_field_from_pointer(BinOrigSizeTag, BinPointer, OrigSize),
+ hipe_rtl:mk_branch(OrigSize, 'ltu', ResultingSize,
ReallocLblName, NoReallocLblName),
NoReallocLbl,
- get_field_from_term(ProcBinBytesTag, ProcBin, Base),
+ hipe_tagscheme:get_field_from_term(ProcBinBytesTag, ProcBin, Base),
hipe_rtl:mk_goto(ContLblName),
ReallocLbl,
hipe_rtl:mk_alu(NewSize, ResultingSize, 'sll', hipe_rtl:mk_imm(1)),
- hipe_rtl:mk_call([BinPointer], bs_reallocate, [BinPointer, NewSize],
+ hipe_rtl:mk_call([BinPointer], bs_reallocate, [BinPointer, NewSize],
NextLblName, [], not_remote),
NextLbl,
- set_field_from_pointer(BinOrigSizeTag, BinPointer, NewSize),
- set_field_from_term(ProcBinValTag, ProcBin, BinPointer),
+ hipe_tagscheme:set_field_from_pointer(BinOrigSizeTag, BinPointer, NewSize),
+ hipe_tagscheme:set_field_from_term(ProcBinValTag, ProcBin, BinPointer),
hipe_tagscheme:extract_binary_bytes(BinPointer, Base),
- set_field_from_term(ProcBinBytesTag, ProcBin, Base),
+ hipe_tagscheme:set_field_from_term(ProcBinBytesTag, ProcBin, Base),
ContLbl].
calculate_sizes(Bin, SizeReg, Offset, EndSubSize, EndSubBitSize) ->
[SubSize, SubBitSize, EndSize] = create_regs(3),
- [get_field_from_term({sub_binary, binsize}, Bin, SubSize),
- get_field_from_term({sub_binary, bitsize}, Bin, SubBitSize),
+ [hipe_tagscheme:get_field_from_term({sub_binary, binsize}, Bin, SubSize),
+ hipe_tagscheme:get_field_from_term({sub_binary, bitsize}, Bin, SubBitSize),
hipe_rtl:mk_alu(Offset, SubSize, 'sll', ?BYTE_SHIFT),
hipe_rtl:mk_alu(Offset, Offset, 'add', SubBitSize),
hipe_rtl:mk_alu(EndSize, Offset, 'add', SizeReg),
@@ -487,7 +489,7 @@ static_int_c_code(NewOffset, Src, Base, Offset, Size, Flags,
int_c_code(NewOffset, Src, Base, Offset, SizeReg, Flags,
TrueLblName, FalseLblName) ->
- put_c_code(bs_put_big_integer, NewOffset, Src, Base, Offset, SizeReg,
+ put_c_code(bs_put_big_integer, NewOffset, Src, Base, Offset, SizeReg,
Flags, TrueLblName, FalseLblName).
binary_c_code(NewOffset, Src, Base, Offset, Size, TrueLblName) ->
@@ -495,8 +497,8 @@ binary_c_code(NewOffset, Src, Base, Offset, Size, TrueLblName) ->
[SizeReg, FlagsReg] = create_regs(2),
[hipe_rtl:mk_move(FlagsReg, hipe_rtl:mk_imm(0)),
hipe_rtl:mk_move(SizeReg, Size),
- hipe_rtl:mk_call([], bs_put_bits, [Src, SizeReg, Base, Offset, FlagsReg],
- hipe_rtl:label_name(PassedLbl),[],not_remote),
+ hipe_rtl:mk_call([], bs_put_bits, [Src, SizeReg, Base, Offset, FlagsReg],
+ hipe_rtl:label_name(PassedLbl), [], not_remote),
PassedLbl,
hipe_rtl:mk_alu(NewOffset, Offset, add, SizeReg),
hipe_rtl:mk_goto(TrueLblName)].
@@ -506,7 +508,7 @@ put_c_code(Func, NewOffset, Src, Base, Offset, SizeReg, Flags,
PassedLbl = hipe_rtl:mk_new_label(),
[FlagsReg] = create_regs(1),
[hipe_rtl:mk_move(FlagsReg, hipe_rtl:mk_imm(Flags)),
- gen_test_sideffect_bs_call(Func, [Src, SizeReg, Base, Offset, FlagsReg],
+ gen_test_sideffect_bs_call(Func, [Src, SizeReg, Base, Offset, FlagsReg],
hipe_rtl:label_name(PassedLbl), FalseLblName),
PassedLbl,
hipe_rtl:mk_alu(NewOffset, Offset, add, SizeReg),
@@ -518,7 +520,7 @@ gen_test_sideffect_bs_call(Name, Args, TrueLblName, FalseLblName) ->
[hipe_rtl:mk_call([Tmp1], Name, Args,
hipe_rtl:label_name(RetLbl), [], not_remote),
RetLbl,
- hipe_rtl:mk_branch(Tmp1, eq, hipe_rtl:mk_imm(0),
+ hipe_rtl:mk_branch(Tmp1, eq, hipe_rtl:mk_imm(0),
FalseLblName, TrueLblName, 0.01)].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -539,7 +541,7 @@ create_unsafe_regs(0) ->
create_vars(X) when X > 0 ->
[hipe_rtl:mk_new_var()|create_vars(X-1)];
-create_vars(0) ->
+create_vars(0) ->
[].
create_lbls(X) when X > 0 ->
@@ -577,7 +579,7 @@ get_real(Dst) ->
%% The following functions are called from the translation switch:
%%
%% - put_string/7 creates code to copy a string to a binary
-%% starting at base+offset and ending at base+newoffset
+%% starting at base+offset and ending at base+newoffset
%%
%% - const_init2/6 initializes the creation of a binary of constant size
%%
@@ -604,10 +606,9 @@ put_string(NewOffset, ConstTab, String, SizeInBytes, Base, Offset, TLName) ->
[StringBase] = create_regs(1),
{NewTab, Lbl} = hipe_consttab:insert_block(ConstTab, byte, String),
{[hipe_rtl:mk_load_address(StringBase, Lbl, constant)|
- copy_string(StringBase, SizeInBytes, Base, Offset,
- NewOffset, TLName)],
+ copy_string(StringBase, SizeInBytes, Base, Offset, NewOffset, TLName)],
NewTab}.
-
+
const_init2(Size, Dst, Base, Offset, TrueLblName) ->
Log2WordSize = hipe_rtl_arch:log2_word_size(),
WordSize = hipe_rtl_arch:word_size(),
@@ -637,27 +638,29 @@ const_init_bits(Size, Dst, Base, Offset, TrueLblName) ->
TmpDst = hipe_rtl:mk_new_var(),
Zero = hipe_rtl:mk_imm(0),
{ExtraSpace, SubBinCode} =
- if (Size rem ?BYTE_SIZE) =:= 0 ->
- {0,[hipe_rtl:mk_move(Dst, TmpDst)]};
- true ->
+ case (Size rem ?BYTE_SIZE) =:= 0 of
+ true ->
+ {0, [hipe_rtl:mk_move(Dst, TmpDst)]};
+ false ->
{?SUB_BIN_WORDSIZE,
- hipe_tagscheme:mk_sub_binary(Dst, hipe_rtl:mk_imm(Size bsr 3), Zero,
+ hipe_tagscheme:mk_sub_binary(Dst, hipe_rtl:mk_imm(Size bsr 3), Zero,
hipe_rtl:mk_imm(Size band ?LOW_BITS_INT),
Zero, TmpDst)}
end,
BaseBinCode =
- if Size =< (?MAX_HEAP_BIN_SIZE * 8) ->
- ByteSize = (Size + 7) div 8,
- [hipe_rtl:mk_gctest(((ByteSize+ 3*WordSize-1) bsr Log2WordSize)+ ExtraSpace),
+ case Size =< (?MAX_HEAP_BIN_SIZE * 8) of
+ true ->
+ ByteSize = (Size + 7) div 8,
+ [hipe_rtl:mk_gctest(((ByteSize + 3*WordSize-1) bsr Log2WordSize) + ExtraSpace),
hipe_tagscheme:create_heap_binary(Base, ByteSize, TmpDst),
hipe_rtl:mk_move(Offset, Zero)];
- true ->
+ false ->
ByteSize = hipe_rtl:mk_new_reg(),
[hipe_rtl:mk_gctest(?PROC_BIN_WORDSIZE+ExtraSpace),
hipe_rtl:mk_move(Offset, Zero),
hipe_rtl:mk_move(ByteSize, hipe_rtl:mk_imm((Size+7) bsr 3)),
hipe_rtl:mk_call([Base], bs_allocate, [ByteSize],
- hipe_rtl:label_name(NextLbl),[],not_remote),
+ hipe_rtl:label_name(NextLbl), [], not_remote),
NextLbl,
hipe_tagscheme:create_refc_binary(Base, ByteSize, TmpDst)]
end,
@@ -666,16 +669,16 @@ const_init_bits(Size, Dst, Base, Offset, TrueLblName) ->
var_init2(Size, Dst, Base, Offset, TrueLblName, SystemLimitLblName, FalseLblName) ->
Log2WordSize = hipe_rtl_arch:log2_word_size(),
WordSize = hipe_rtl_arch:word_size(),
- [ContLbl,HeapLbl,REFCLbl,NextLbl] = create_lbls(4),
- [USize,Tmp] = create_unsafe_regs(2),
- [get_32_bit_value(Size, USize, SystemLimitLblName, FalseLblName),
- hipe_rtl:mk_branch(USize, le, hipe_rtl:mk_imm(?MAX_BINSIZE),
- hipe_rtl:label_name(ContLbl),
+ [ContLbl, HeapLbl, REFCLbl, NextLbl] = create_lbls(4),
+ [USize, Tmp] = create_unsafe_regs(2),
+ [get_word_integer(Size, USize, SystemLimitLblName, FalseLblName),
+ hipe_rtl:mk_branch(USize, leu, hipe_rtl:mk_imm(?MAX_BINSIZE),
+ hipe_rtl:label_name(ContLbl),
SystemLimitLblName),
ContLbl,
hipe_rtl:mk_move(Offset, hipe_rtl:mk_imm(0)),
- hipe_rtl:mk_branch(USize, le, hipe_rtl:mk_imm(?MAX_HEAP_BIN_SIZE),
- hipe_rtl:label_name(HeapLbl),
+ hipe_rtl:mk_branch(USize, leu, hipe_rtl:mk_imm(?MAX_HEAP_BIN_SIZE),
+ hipe_rtl:label_name(HeapLbl),
hipe_rtl:label_name(REFCLbl)),
HeapLbl,
hipe_rtl:mk_alu(Tmp, USize, add, hipe_rtl:mk_imm(3*WordSize-1)),
@@ -693,20 +696,20 @@ var_init2(Size, Dst, Base, Offset, TrueLblName, SystemLimitLblName, FalseLblName
hipe_rtl:mk_goto(TrueLblName)].
var_init_bits(Size, Dst, Base, Offset, TrueLblName, SystemLimitLblName, FalseLblName) ->
- [HeapLbl,REFCLbl,NextLbl,NoSubLbl,SubLbl,ContLbl,
- NoCreateSubBin, CreateSubBin, JoinLbl, JoinLbl2] = create_lbls(10),
- [USize,ByteSize,TotByteSize,OffsetBits] = create_regs(4),
+ [HeapLbl, REFCLbl, NextLbl, NoSubLbl, SubLbl,
+ NoCreateSubBin, CreateSubBin, JoinLbl, JoinLbl2] = create_lbls(9),
+ [USize, ByteSize, TotByteSize, OffsetBits] = create_regs(4),
[TmpDst] = create_unsafe_regs(1),
Log2WordSize = hipe_rtl_arch:log2_word_size(),
WordSize = hipe_rtl_arch:word_size(),
- MaximumWords =
+ MaximumWords =
erlang:max((?MAX_HEAP_BIN_SIZE + 3*WordSize) bsr Log2WordSize,
?PROC_BIN_WORDSIZE) + ?SUB_BIN_WORDSIZE,
Zero = hipe_rtl:mk_imm(0),
[hipe_rtl:mk_gctest(MaximumWords),
- get_32_bit_value(Size, USize, SystemLimitLblName, FalseLblName),
+ get_word_integer(Size, USize, SystemLimitLblName, FalseLblName),
hipe_rtl:mk_alu(ByteSize, USize, srl, ?BYTE_SHIFT),
- hipe_rtl:mk_alub(OffsetBits, USize, 'and', ?LOW_BITS, eq,
+ hipe_rtl:mk_alub(OffsetBits, USize, 'and', ?LOW_BITS, eq,
hipe_rtl:label_name(NoSubLbl),
hipe_rtl:label_name(SubLbl)),
NoSubLbl,
@@ -715,25 +718,21 @@ var_init_bits(Size, Dst, Base, Offset, TrueLblName, SystemLimitLblName, FalseLbl
SubLbl,
hipe_rtl:mk_alu(TotByteSize, ByteSize, 'add', hipe_rtl:mk_imm(1)),
JoinLbl,
- hipe_rtl:mk_branch(USize, le, hipe_rtl:mk_imm(?MAX_BINSIZE),
- hipe_rtl:label_name(ContLbl),
- SystemLimitLblName),
- ContLbl,
- hipe_rtl:mk_branch(TotByteSize, 'le', hipe_rtl:mk_imm(?MAX_HEAP_BIN_SIZE),
- hipe_rtl:label_name(HeapLbl),
+ hipe_rtl:mk_branch(TotByteSize, 'leu', hipe_rtl:mk_imm(?MAX_HEAP_BIN_SIZE),
+ hipe_rtl:label_name(HeapLbl),
hipe_rtl:label_name(REFCLbl)),
HeapLbl,
hipe_tagscheme:create_heap_binary(Base, TotByteSize, TmpDst),
hipe_rtl:mk_goto(hipe_rtl:label_name(JoinLbl2)),
REFCLbl,
hipe_rtl:mk_call([Base], bs_allocate, [TotByteSize],
- hipe_rtl:label_name(NextLbl),[],not_remote),
+ hipe_rtl:label_name(NextLbl), [], not_remote),
NextLbl,
hipe_tagscheme:create_refc_binary(Base, TotByteSize, TmpDst),
JoinLbl2,
hipe_rtl:mk_move(Offset, Zero),
hipe_rtl:mk_branch(OffsetBits, 'eq', Zero,
- hipe_rtl:label_name(NoCreateSubBin),
+ hipe_rtl:label_name(NoCreateSubBin),
hipe_rtl:label_name(CreateSubBin)),
CreateSubBin,
hipe_tagscheme:mk_sub_binary(Dst, ByteSize, Zero, OffsetBits, Zero, TmpDst),
@@ -742,20 +741,23 @@ var_init_bits(Size, Dst, Base, Offset, TrueLblName, SystemLimitLblName, FalseLbl
hipe_rtl:mk_move(Dst, TmpDst),
hipe_rtl:mk_goto(TrueLblName)].
-put_binary_all(NewOffset, Src, Base, Offset, TLName, FLName) ->
- [SrcBase,SrcOffset,NumBits] = create_regs(3),
+put_binary_all(NewOffset, Src, Base, Offset, Unit, TLName, FLName) ->
+ [SrcBase, SrcOffset, NumBits] = create_regs(3),
+ [ContLbl] = create_lbls(1),
CCode = binary_c_code(NewOffset, Src, Base, Offset, NumBits, TLName),
- AlignedCode = copy_aligned_bytes(SrcBase, SrcOffset, NumBits, Base, Offset,
+ AlignedCode = copy_aligned_bytes(SrcBase, SrcOffset, NumBits, Base, Offset,
NewOffset, TLName),
- get_base_offset_size(Src, SrcBase, SrcOffset, NumBits,FLName) ++
- test_alignment(SrcOffset, NumBits, Offset, AlignedCode, CCode).
+ [get_base_offset_size(Src, SrcBase, SrcOffset, NumBits,FLName),
+ is_divisible(NumBits, Unit, hipe_rtl:label_name(ContLbl), FLName),
+ ContLbl
+ |test_alignment(SrcOffset, NumBits, Offset, AlignedCode, CCode)].
test_alignment(SrcOffset, NumBits, Offset, AlignedCode, CCode) ->
- [Tmp] = create_regs(1),
- [AlignedLbl,CLbl] = create_lbls(2),
+ [Tmp] = create_regs(1),
+ [AlignedLbl, CLbl] = create_lbls(2),
[hipe_rtl:mk_alu(Tmp, SrcOffset, 'or', NumBits),
hipe_rtl:mk_alu(Tmp, Tmp, 'or', Offset),
- hipe_rtl:mk_alub(Tmp, Tmp, 'and', ?LOW_BITS, 'eq',
+ hipe_rtl:mk_alub(Tmp, Tmp, 'and', ?LOW_BITS, 'eq',
hipe_rtl:label_name(AlignedLbl),
hipe_rtl:label_name(CLbl)),
AlignedLbl,
@@ -764,12 +766,12 @@ test_alignment(SrcOffset, NumBits, Offset, AlignedCode, CCode) ->
CCode].
put_static_binary(NewOffset, Src, Size, Base, Offset, TLName, FLName) ->
- [SrcBase] = create_unsafe_regs(1),
+ [SrcBase] = create_unsafe_regs(1),
[SrcOffset, SrcSize] = create_regs(2),
case Size of
0 ->
get_base_offset_size(Src, SrcBase, SrcOffset, SrcSize, FLName) ++
- [hipe_rtl:mk_move(NewOffset, Offset),
+ [hipe_rtl:mk_move(NewOffset, Offset),
hipe_rtl:mk_goto(TLName)];
_ ->
SizeImm = hipe_rtl:mk_imm(Size),
@@ -785,13 +787,13 @@ put_dynamic_binary(NewOffset, Src, SizeReg, Base, Offset, TLName, FLName) ->
[SrcBase] = create_unsafe_regs(1),
[SrcOffset, SrcSize] = create_regs(2),
CCode = binary_c_code(NewOffset, Src, Base, Offset, SizeReg, TLName),
- AlignedCode = copy_aligned_bytes(SrcBase, SrcOffset, SizeReg, Base, Offset,
+ AlignedCode = copy_aligned_bytes(SrcBase, SrcOffset, SizeReg, Base, Offset,
NewOffset, TLName),
get_base_offset_size(Src, SrcBase, SrcOffset, SrcSize, FLName) ++
small_check(SizeReg, SrcSize, FLName) ++
test_alignment(SrcOffset, SizeReg, Offset, AlignedCode, CCode).
-put_float(NewOffset, Src, Base, Offset, 64, CCode, Aligned, LittleEndian,
+put_float(NewOffset, Src, Base, Offset, 64, CCode, Aligned, LittleEndian,
ConstInfo, TrueLblName) ->
[CLbl] = create_lbls(1),
case {Aligned, LittleEndian} of
@@ -825,12 +827,12 @@ put_static_int(NewOffset, Src, Base, Offset, Size, CCode, Aligned,
{false, true} ->
CCode;
{false, false} ->
- Init ++
+ Init ++
copy_offset_int_big(Base, Offset, NewOffset, Size, UntaggedSrc) ++
End
end.
-put_unsafe_static_int(NewOffset, Src, Base, Offset, Size, CCode, Aligned,
+put_unsafe_static_int(NewOffset, Src, Base, Offset, Size, CCode, Aligned,
LittleEndian, TrueLblName) ->
{Init, End, UntaggedSrc} = make_init_end(Src, TrueLblName),
case {Aligned, LittleEndian} of
@@ -845,7 +847,7 @@ put_unsafe_static_int(NewOffset, Src, Base, Offset, Size, CCode, Aligned,
{false, true} ->
CCode;
{false, false} ->
- Init ++
+ Init ++
copy_offset_int_big(Base, Offset, NewOffset, Size, UntaggedSrc) ++
End
end.
@@ -857,7 +859,7 @@ put_dynamic_int(NewOffset, Src, Base, Offset, SizeReg, CCode, Aligned,
true ->
case LittleEndian of
true ->
- Init ++
+ Init ++
copy_int_little(Base, Offset, NewOffset, SizeReg, UntaggedSrc) ++
End;
false ->
@@ -876,7 +878,7 @@ put_unsafe_dynamic_int(NewOffset, Src, Base, Offset, SizeReg, CCode, Aligned,
true ->
case LittleEndian of
true ->
- Init ++
+ Init ++
copy_int_little(Base, Offset, NewOffset, SizeReg, UntaggedSrc) ++
End;
false ->
@@ -887,7 +889,7 @@ put_unsafe_dynamic_int(NewOffset, Src, Base, Offset, SizeReg, CCode, Aligned,
false ->
CCode
end.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
@@ -898,7 +900,7 @@ put_unsafe_dynamic_int(NewOffset, Src, Base, Offset, SizeReg, CCode, Aligned,
make_init_end(Src, CCode, TrueLblName) ->
[CLbl, SuccessLbl] = create_lbls(2),
[UntaggedSrc] = create_regs(1),
- Init = [hipe_tagscheme:test_fixnum(Src, hipe_rtl:label_name(SuccessLbl),
+ Init = [hipe_tagscheme:test_fixnum(Src, hipe_rtl:label_name(SuccessLbl),
hipe_rtl:label_name(CLbl), 0.99),
SuccessLbl,
hipe_tagscheme:untag_fixnum(UntaggedSrc,Src)],
@@ -911,28 +913,28 @@ make_init_end(Src, TrueLblName) ->
End = [hipe_rtl:mk_goto(TrueLblName)],
{Init, End, UntaggedSrc}.
-get_base_offset_size(Binary, SrcBase, SrcOffset, SrcSize, FLName) ->
+get_base_offset_size(Binary, SrcBase, SrcOffset, SrcSize, FLName) ->
[JoinLbl, EndLbl, SuccessLbl, SubLbl, OtherLbl, HeapLbl, REFCLbl] =
Lbls = create_lbls(7),
- [JoinLblName, EndLblName, SuccessLblName, SubLblName,
+ [JoinLblName, EndLblName, SuccessLblName, SubLblName,
OtherLblName, HeapLblName, REFCLblName] = get_label_names(Lbls),
- [BitSize,BitOffset] = create_regs(2),
+ [BitSize, BitOffset] = create_regs(2),
[Orig] = create_vars(1),
[hipe_tagscheme:test_bitstr(Binary, SuccessLblName, FLName, 0.99),
SuccessLbl,
- get_field_from_term({sub_binary,binsize}, Binary, SrcSize),
+ hipe_tagscheme:get_field_from_term({sub_binary,binsize}, Binary, SrcSize),
hipe_rtl:mk_alu(SrcSize, SrcSize, sll, ?BYTE_SHIFT),
hipe_tagscheme:test_subbinary(Binary, SubLblName, OtherLblName),
SubLbl,
- get_field_from_term({sub_binary,bitsize}, Binary, BitSize),
- get_field_from_term({sub_binary,offset}, Binary, SrcOffset),
+ hipe_tagscheme:get_field_from_term({sub_binary,bitsize}, Binary, BitSize),
+ hipe_tagscheme:get_field_from_term({sub_binary,offset}, Binary, SrcOffset),
hipe_rtl:mk_alu(SrcSize, SrcSize, add, BitSize),
- get_field_from_term({sub_binary,bitoffset}, Binary, BitOffset),
+ hipe_tagscheme:get_field_from_term({sub_binary,bitoffset}, Binary, BitOffset),
hipe_rtl:mk_alu(SrcOffset, SrcOffset, sll, ?BYTE_SHIFT),
hipe_rtl:mk_alu(SrcOffset, SrcOffset, add, BitOffset),
- get_field_from_term({sub_binary,orig}, Binary, Orig),
+ hipe_tagscheme:get_field_from_term({sub_binary,orig}, Binary, Orig),
hipe_rtl:mk_goto(JoinLblName),
- OtherLbl,
+ OtherLbl,
hipe_rtl:mk_move(SrcOffset, hipe_rtl:mk_imm(0)),
hipe_rtl:mk_move(Orig, Binary),
JoinLbl,
@@ -941,29 +943,29 @@ get_base_offset_size(Binary, SrcBase, SrcOffset, SrcSize, FLName) ->
hipe_rtl:mk_alu(SrcBase, Orig, add, hipe_rtl:mk_imm(?HEAP_BIN_DATA-2)),
hipe_rtl:mk_goto(EndLblName),
REFCLbl,
- get_field_from_term({proc_bin,bytes}, Orig, SrcBase),
+ hipe_tagscheme:get_field_from_term({proc_bin,bytes}, Orig, SrcBase),
EndLbl].
copy_aligned_bytes(CopyBase, CopyOffset, Size, Base, Offset, NewOffset, TrueLblName) ->
[BaseDst, BaseSrc] = create_unsafe_regs(2),
[Iter, Extra, BothOffset] = create_regs(3),
initializations(BaseSrc, BaseDst, BothOffset, CopyOffset, Offset, CopyBase, Base) ++
- [hipe_rtl:mk_alu(Extra, Size, 'and', ?LOW_BITS),
- hipe_rtl:mk_alu(Iter, Size, srl, ?BYTE_SHIFT),
+ [hipe_rtl:mk_alu(Extra, Size, 'and', ?LOW_BITS),
+ hipe_rtl:mk_alu(Iter, Size, srl, ?BYTE_SHIFT),
hipe_rtl:mk_alu(NewOffset, Offset, 'add', Size)] ++
easy_loop(BaseSrc, BaseDst, BothOffset, Iter, Extra, TrueLblName).
copy_string(StringBase, StringSize, BinBase, BinOffset, NewOffset, TrueLblName) ->
[TmpOffset,BothOffset,InitOffs] = create_regs(3),
[NewBinBase] = create_unsafe_regs(1),
- [EasyLbl,HardLbl] = create_lbls(2),
+ [EasyLbl, HardLbl] = create_lbls(2),
[hipe_rtl:mk_alu(TmpOffset, BinOffset, srl, ?BYTE_SHIFT),
hipe_rtl:mk_alu(NewBinBase, BinBase, add, TmpOffset),
hipe_rtl:mk_move(BothOffset, hipe_rtl:mk_imm(0)),
hipe_rtl:mk_alub(InitOffs, BinOffset, 'and', ?LOW_BITS, eq,
hipe_rtl:label_name(EasyLbl), hipe_rtl:label_name(HardLbl)),
EasyLbl,
- hipe_rtl:mk_alu(NewOffset, BinOffset, add,
+ hipe_rtl:mk_alu(NewOffset, BinOffset, add,
hipe_rtl:mk_imm(?bytes_to_bits(StringSize)))] ++
easy_loop(StringBase, NewBinBase, BothOffset,
hipe_rtl:mk_imm(StringSize), hipe_rtl:mk_imm(0), TrueLblName) ++
@@ -975,13 +977,13 @@ copy_string(StringBase, StringSize, BinBase, BinOffset, NewOffset, TrueLblName)
small_check(SizeVar, CopySize, FalseLblName) ->
SuccessLbl = hipe_rtl:mk_new_label(),
- [hipe_rtl:mk_branch(SizeVar, le, CopySize,
+ [hipe_rtl:mk_branch(SizeVar, leu, CopySize,
hipe_rtl:label_name(SuccessLbl), FalseLblName),
SuccessLbl].
-easy_loop(BaseSrc, BaseDst, BothOffset, Iterations, Extra, TrueLblName) ->
- [Tmp1,Shift] = create_regs(2),
- [LoopLbl,TopLbl,EndLbl,ExtraLbl] = create_lbls(4),
+easy_loop(BaseSrc, BaseDst, BothOffset, Iterations, Extra, TrueLblName) ->
+ [Tmp1, Shift] = create_regs(2),
+ [LoopLbl, TopLbl, EndLbl, ExtraLbl] = create_lbls(4),
[TopLbl,
hipe_rtl:mk_branch(BothOffset, ne, Iterations, hipe_rtl:label_name(LoopLbl),
hipe_rtl:label_name(EndLbl), 0.99),
@@ -1001,17 +1003,17 @@ easy_loop(BaseSrc, BaseDst, BothOffset, Iterations, Extra, TrueLblName) ->
hipe_rtl:mk_store(BaseDst, BothOffset, Tmp1, byte),
hipe_rtl:mk_goto(TrueLblName)].
-hard_loop(BaseSrc, BaseDst, BothOffset, Iterations,
+hard_loop(BaseSrc, BaseDst, BothOffset, Iterations,
InitOffset, TrueLblName) ->
[Tmp1, Tmp2, OldByte, NewByte, SaveByte] = create_regs(5),
- [LoopLbl,EndLbl,TopLbl] = create_lbls(3),
+ [LoopLbl, EndLbl, TopLbl] = create_lbls(3),
[hipe_rtl:mk_load(OldByte, BaseDst, BothOffset, byte, unsigned),
- hipe_rtl:mk_alu(Tmp1, hipe_rtl:mk_imm(?BYTE_SIZE), sub, InitOffset),
+ hipe_rtl:mk_alu(Tmp1, hipe_rtl:mk_imm(?BYTE_SIZE), sub, InitOffset),
TopLbl,
- hipe_rtl:mk_branch(BothOffset, ne, Iterations,
- hipe_rtl:label_name(LoopLbl),
+ hipe_rtl:mk_branch(BothOffset, ne, Iterations,
+ hipe_rtl:label_name(LoopLbl),
hipe_rtl:label_name(EndLbl)),
- LoopLbl,
+ LoopLbl,
hipe_rtl:mk_load(NewByte, BaseSrc, BothOffset, byte, unsigned),
hipe_rtl:mk_alu(Tmp2, NewByte, srl, InitOffset),
hipe_rtl:mk_alu(SaveByte, OldByte, 'or', Tmp2),
@@ -1033,12 +1035,12 @@ initializations(BaseTmp1, BaseTmp2, BothOffset, CopyOffset, Offset, CopyBase, Ba
copy_int_little(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) ->
[Tmp2,TmpOffset] = create_regs(2),
- ByteSize = Size div ?BYTE_SIZE,
- [hipe_rtl:mk_alu(TmpOffset, Offset, srl, ?BYTE_SHIFT),
- hipe_rtl:mk_alu(Tmp2, hipe_rtl:mk_imm(ByteSize), 'add', TmpOffset)] ++
-
+ ByteSize = Size div ?BYTE_SIZE,
+ [hipe_rtl:mk_alu(TmpOffset, Offset, srl, ?BYTE_SHIFT),
+ hipe_rtl:mk_alu(Tmp2, hipe_rtl:mk_imm(ByteSize), 'add', TmpOffset)] ++
+
little_loop(Tmp1, Tmp2, TmpOffset, Base) ++
-
+
case Size band 7 of
0 ->
[hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(Size))];
@@ -1047,18 +1049,16 @@ copy_int_little(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) ->
hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(Size))]
end;
-
copy_int_little(Base, Offset, NewOffset, Size, Tmp1) ->
[Tmp2, Tmp3, Tmp4, TmpOffset] = create_regs(4),
-
[hipe_rtl:mk_alu(Tmp2, Size, srl, ?BYTE_SHIFT),
hipe_rtl:mk_alu(TmpOffset, Offset, srl, ?BYTE_SHIFT),
hipe_rtl:mk_alu(Tmp3, Tmp2, 'add', TmpOffset)] ++
-
+
little_loop(Tmp1, Tmp3, TmpOffset, Base) ++
-
+
[hipe_rtl:mk_alu(Tmp4, Size, 'and', ?LOW_BITS),
- hipe_rtl:mk_alu(Tmp4, hipe_rtl:mk_imm(?BYTE_SIZE), 'sub', Tmp4),
+ hipe_rtl:mk_alu(Tmp4, hipe_rtl:mk_imm(?BYTE_SIZE), 'sub', Tmp4),
hipe_rtl:mk_alu(Tmp1, Tmp1, sll, Tmp4),
hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
hipe_rtl:mk_alu(NewOffset, Offset, 'add', Size)].
@@ -1093,37 +1093,37 @@ copy_int_big(_Base, Offset, NewOffset, 0, _Tmp1) ->
[hipe_rtl:mk_move(NewOffset, Offset)];
copy_int_big(Base, Offset, NewOffset, ?BYTE_SIZE, Tmp1) ->
TmpOffset = hipe_rtl:mk_new_reg(),
- [hipe_rtl:mk_alu(TmpOffset, Offset, 'srl', hipe_rtl:mk_imm(3)),
- hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
- hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(8))];
+ [hipe_rtl:mk_alu(TmpOffset, Offset, 'srl', hipe_rtl:mk_imm(3)),
+ hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
+ hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(8))];
copy_int_big(Base, Offset, NewOffset, 2*?BYTE_SIZE, Tmp1) ->
TmpOffset = hipe_rtl:mk_new_reg(),
- [hipe_rtl:mk_alu(TmpOffset, Offset, 'srl', hipe_rtl:mk_imm(3)),
- hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'add', hipe_rtl:mk_imm(1)),
- hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
- hipe_rtl:mk_alu(TmpOffset, TmpOffset, sub, hipe_rtl:mk_imm(1)),
- hipe_rtl:mk_alu(Tmp1, Tmp1, 'sra', hipe_rtl:mk_imm(8)),
- hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
- hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(16))];
+ [hipe_rtl:mk_alu(TmpOffset, Offset, 'srl', hipe_rtl:mk_imm(3)),
+ hipe_rtl:mk_alu(TmpOffset, TmpOffset, 'add', hipe_rtl:mk_imm(1)),
+ hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
+ hipe_rtl:mk_alu(TmpOffset, TmpOffset, sub, hipe_rtl:mk_imm(1)),
+ hipe_rtl:mk_alu(Tmp1, Tmp1, 'sra', hipe_rtl:mk_imm(8)),
+ hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
+ hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(16))];
copy_int_big(Base, Offset, NewOffset, 3*?BYTE_SIZE, Tmp1) ->
- TmpOffset = hipe_rtl:mk_new_reg(),
- [hipe_rtl:mk_alu(TmpOffset, Offset, srl, hipe_rtl:mk_imm(3)),
- hipe_rtl:mk_alu(TmpOffset, TmpOffset, add, hipe_rtl:mk_imm(2)),
- hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
- hipe_rtl:mk_alu(TmpOffset, TmpOffset, sub, hipe_rtl:mk_imm(1)),
- hipe_rtl:mk_alu(Tmp1, Tmp1, sra, hipe_rtl:mk_imm(8)),
- hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
- hipe_rtl:mk_alu(TmpOffset, TmpOffset, sub, hipe_rtl:mk_imm(1)),
- hipe_rtl:mk_alu(Tmp1, Tmp1, sra, hipe_rtl:mk_imm(8)),
- hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
- hipe_rtl:mk_alu(NewOffset, Offset, add, hipe_rtl:mk_imm(24))];
+ TmpOffset = hipe_rtl:mk_new_reg(),
+ [hipe_rtl:mk_alu(TmpOffset, Offset, srl, hipe_rtl:mk_imm(3)),
+ hipe_rtl:mk_alu(TmpOffset, TmpOffset, add, hipe_rtl:mk_imm(2)),
+ hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
+ hipe_rtl:mk_alu(TmpOffset, TmpOffset, sub, hipe_rtl:mk_imm(1)),
+ hipe_rtl:mk_alu(Tmp1, Tmp1, sra, hipe_rtl:mk_imm(8)),
+ hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
+ hipe_rtl:mk_alu(TmpOffset, TmpOffset, sub, hipe_rtl:mk_imm(1)),
+ hipe_rtl:mk_alu(Tmp1, Tmp1, sra, hipe_rtl:mk_imm(8)),
+ hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
+ hipe_rtl:mk_alu(NewOffset, Offset, add, hipe_rtl:mk_imm(24))];
copy_int_big(Base, Offset,NewOffset, 4*?BYTE_SIZE, Tmp1) ->
copy_big_word(Base, Offset, NewOffset, Tmp1);
copy_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) ->
[OldOffset, TmpOffset, Bits] = create_regs(3),
ByteSize = (Size + 7) div ?BYTE_SIZE,
- case Size band 7 of
- 0 ->
+ case Size band 7 of
+ 0 ->
[hipe_rtl:mk_alu(OldOffset, Offset, sra, hipe_rtl:mk_imm(3)),
hipe_rtl:mk_alu(TmpOffset, OldOffset, add, hipe_rtl:mk_imm(ByteSize))];
Rest ->
@@ -1134,7 +1134,7 @@ copy_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) ->
hipe_rtl:mk_alu(Tmp1, Tmp1, sra, hipe_rtl:mk_imm(Rest))]
end ++
big_loop(Tmp1, OldOffset, TmpOffset, Base) ++
- [hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(Size))];
+ [hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(Size))];
copy_int_big(Base, Offset, NewOffset, Size, Tmp1) ->
Tmp2 = hipe_rtl:mk_new_reg(),
Tmp3 = hipe_rtl:mk_new_reg(),
@@ -1147,7 +1147,7 @@ copy_int_big(Base, Offset, NewOffset, Size, Tmp1) ->
[hipe_rtl:mk_alu(Tmp2, Size, 'srl', hipe_rtl:mk_imm(3)),
hipe_rtl:mk_alu(Tmp3, Offset, 'srl', hipe_rtl:mk_imm(3)),
hipe_rtl:mk_alu(TmpOffset, Tmp2, 'add', Tmp3),
- hipe_rtl:mk_alub(Tmp4, Size, 'and', hipe_rtl:mk_imm(7), 'eq',
+ hipe_rtl:mk_alub(Tmp4, Size, 'and', hipe_rtl:mk_imm(7), 'eq',
hipe_rtl:label_name(EvenLbl), hipe_rtl:label_name(OddLbl)),
OddLbl,
hipe_rtl:mk_alu(Tmp6, hipe_rtl:mk_imm(8), 'sub', Tmp4),
@@ -1155,9 +1155,7 @@ copy_int_big(Base, Offset, NewOffset, Size, Tmp1) ->
hipe_rtl:mk_store(Base, TmpOffset, Tmp5, byte),
EvenLbl,
hipe_rtl:mk_alu(Tmp1, Tmp1, srl, Tmp4)] ++
-
big_loop(Tmp1, Tmp3, TmpOffset, Base) ++
-
[hipe_rtl:mk_alu(NewOffset, Offset, 'add', Size)].
copy_big_word(Base, Offset, NewOffset, Word) ->
@@ -1191,7 +1189,10 @@ copy_little_word(Base, Offset, NewOffset, Word) ->
hipe_rtl:mk_store(Base, TmpOffset, Word, byte),
hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(32))].
-copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) ->
+copy_offset_int_big(_Base, Offset, NewOffset, 0, _Tmp1) ->
+ [hipe_rtl:mk_move(NewOffset, Offset)];
+copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1)
+ when is_integer(Size), Size > 0 ->
Tmp2 = hipe_rtl:mk_new_reg(),
Tmp3 = hipe_rtl:mk_new_reg(),
Tmp4 = hipe_rtl:mk_new_reg(),
@@ -1202,7 +1203,7 @@ copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) -
Tmp9 = hipe_rtl:mk_new_reg(),
OldByte = hipe_rtl:mk_new_reg(),
TmpOffset = hipe_rtl:mk_new_reg(),
- BranchLbl = hipe_rtl:mk_new_label(),
+ BranchLbl = hipe_rtl:mk_new_label(),
BodyLbl = hipe_rtl:mk_new_label(),
EndLbl = hipe_rtl:mk_new_label(),
NextLbl = hipe_rtl:mk_new_label(),
@@ -1217,8 +1218,8 @@ copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) -
hipe_rtl:mk_alu(Tmp6, Tmp6, 'and', ?LOW_BITS),
hipe_rtl:mk_alu(Tmp4, hipe_rtl:mk_imm(?BYTE_SIZE), 'sub', Tmp6),
hipe_rtl:mk_move(Tmp5, Tmp1),
- hipe_rtl:mk_alu(Tmp1, Tmp1, 'sll', Tmp6),
- hipe_rtl:mk_branch(TmpOffset, 'ne', Tmp3, hipe_rtl:label_name(NextLbl),
+ hipe_rtl:mk_alu(Tmp1, Tmp1, 'sll', Tmp6),
+ hipe_rtl:mk_branch(TmpOffset, 'ne', Tmp3, hipe_rtl:label_name(NextLbl),
hipe_rtl:label_name(EndLbl)),
NextLbl,
hipe_rtl:mk_store(Base, TmpOffset, Tmp1, byte),
@@ -1265,7 +1266,7 @@ copy_float_big(_Base, _Offset, _NewOffset, _Src, FalseLblName, _TrueLblName, fai
copy_float_big(Base, Offset, NewOffset, Src, _FalseLblName, TrueLblName,pass) ->
FloatLo = hipe_rtl:mk_new_reg(),
FloatHi = hipe_rtl:mk_new_reg(),
- TmpOffset =hipe_rtl:mk_new_reg(),
+ TmpOffset = hipe_rtl:mk_new_reg(),
hipe_tagscheme:unsafe_load_float(FloatLo, FloatHi, Src) ++
copy_big_word(Base, Offset, TmpOffset, FloatHi) ++
copy_big_word(Base, TmpOffset, NewOffset, FloatLo) ++
@@ -1275,89 +1276,18 @@ copy_float_big(Base, Offset, NewOffset, Src, FalseLblName, TrueLblName, var) ->
hipe_tagscheme:test_flonum(Src, hipe_rtl:label_name(SuccessLbl), FalseLblName, 0.99) ++
[SuccessLbl|copy_float_big(Base, Offset, NewOffset, Src, FalseLblName, TrueLblName, pass)].
-make_size(1, BitsVar, FalseLblName) ->
- [DstReg] = create_regs(1),
- {first_part(BitsVar, DstReg, FalseLblName), DstReg};
-make_size(?BYTE_SIZE, BitsVar, FalseLblName) ->
- [DstReg] = create_regs(1),
- Code =
- first_part(BitsVar, DstReg, FalseLblName) ++
- [hipe_rtl:mk_alu(DstReg, DstReg, 'sll', ?BYTE_SHIFT)],
- {Code, DstReg};
-make_size(UnitImm, BitsVar, FalseLblName) ->
- [DstReg] = create_regs(1),
- UnitList = number2list(UnitImm),
- Code = multiply_code(UnitList, BitsVar, DstReg, FalseLblName),
- {Code, DstReg}.
-
-multiply_code(List=[Head|_Tail], Variable, Result, FalseLblName) ->
- Test = set_high(Head),
- Tmp1 = hipe_rtl:mk_new_reg(),
- SuccessLbl = hipe_rtl:mk_new_label(),
- Register = hipe_rtl:mk_new_reg(),
- Code = [hipe_rtl:mk_move(Result, hipe_rtl:mk_imm(0))|
- first_part(Variable, Register, FalseLblName)]
- ++
- [hipe_rtl:mk_alub(Tmp1, Register, 'and', hipe_rtl:mk_imm(Test),
- 'eq', hipe_rtl:label_name(SuccessLbl),
- FalseLblName, 0.99),
- SuccessLbl],
- multiply_code(List, Register, Result, FalseLblName, Tmp1, Code).
-
-multiply_code([ShiftSize|Rest], Register, Result, FalseLblName, Tmp1, OldCode) ->
- SuccessLbl = hipe_rtl:mk_new_label(),
- Code = OldCode ++ [hipe_rtl:mk_alu(Tmp1, Register, 'sll',
- hipe_rtl:mk_imm(ShiftSize)),
- hipe_rtl:mk_alub(Result, Tmp1, 'add', Result, not_overflow, hipe_rtl:label_name(SuccessLbl), FalseLblName, 0.99),
- SuccessLbl],
- multiply_code(Rest, Register, Result, FalseLblName, Tmp1, Code);
-multiply_code([], _Register, _Result, _FalseLblName, _Tmp1, Code) ->
- Code.
-
-number2list(X) when is_integer(X), X >= 0 ->
- number2list(X, []).
-
-number2list(1, Acc) ->
- lists:reverse([0|Acc]);
-number2list(0, Acc) ->
- lists:reverse(Acc);
-number2list(X, Acc) ->
- F = floorlog2(X),
- number2list(X-(1 bsl F), [F|Acc]).
-
-floorlog2(X) ->
- round(math:log(X)/math:log(2)-0.5).
-
-set_high(X) ->
- set_high(X, 0).
-
-set_high(0, Y) ->
- Y;
-set_high(X, Y) ->
- set_high(X-1, Y+(1 bsl (27-X))).
-
-get_32_bit_value(Size, USize, SystemLimitLblName, NegLblName) ->
- Lbls = [FixLbl, BigLbl, OkLbl, PosBigLbl] = create_lbls(4),
- [FixLblName, BigLblName, OkLblName, PosBigLblName] = [hipe_rtl:label_name(Lbl) || Lbl <- Lbls],
- [hipe_tagscheme:test_fixnum(Size, FixLblName, BigLblName, 0.99),
- FixLbl,
- hipe_tagscheme:untag_fixnum(USize, Size),
- hipe_rtl:mk_branch(USize, ge, hipe_rtl:mk_imm(0), OkLblName, NegLblName),
- BigLbl,
- hipe_tagscheme:test_pos_bignum(Size, PosBigLblName, NegLblName, 0.99),
- PosBigLbl,
- hipe_tagscheme:get_one_word_pos_bignum(USize, Size, SystemLimitLblName),
- OkLbl].
-
-
-first_part(Var, Register, FalseLblName) ->
- [SuccessLbl1, SuccessLbl2] = create_lbls(2),
- [hipe_tagscheme:test_fixnum(Var, hipe_rtl:label_name(SuccessLbl1),
- FalseLblName, 0.99),
- SuccessLbl1,
- hipe_tagscheme:fixnum_ge(Var, hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(0)),
- hipe_rtl:label_name(SuccessLbl2), FalseLblName, 0.99),
- SuccessLbl2,
- hipe_tagscheme:untag_fixnum(Register, Var)].
-
-
+is_divisible(_Dividend, 1, SuccLbl, _FailLbl) ->
+ [hipe_rtl:mk_goto(SuccLbl)];
+is_divisible(Dividend, Divisor, SuccLbl, FailLbl) ->
+ Log2 = hipe_rtl_binary:floorlog2(Divisor),
+ case Divisor =:= 1 bsl Log2 of
+ true -> %% Divisor is a power of 2
+ %% Test that the Log2-1 lowest bits are clear
+ Mask = hipe_rtl:mk_imm(Divisor - 1),
+ [Tmp] = create_regs(1),
+ [hipe_rtl:mk_alub(Tmp, Dividend, 'and', Mask, eq, SuccLbl, FailLbl, 0.99)];
+ false ->
+ %% We need division, fall back to a primop
+ [hipe_rtl:mk_call([], is_divisible, [Dividend, hipe_rtl:mk_imm(Divisor)],
+ SuccLbl, FailLbl, not_remote)]
+ end.
diff --git a/lib/hipe/rtl/hipe_rtl_binary_match.erl b/lib/hipe/rtl/hipe_rtl_binary_match.erl
index af8903904b..528672b893 100644
--- a/lib/hipe/rtl/hipe_rtl_binary_match.erl
+++ b/lib/hipe/rtl/hipe_rtl_binary_match.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
+%%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
@@ -30,11 +31,12 @@
-import(hipe_tagscheme, [set_field_from_term/3, get_field_from_term/3]).
+-import(hipe_rtl_binary, [make_size/3]).
+
-include("hipe_literals.hrl").
%%--------------------------------------------------------------------
--define(MAX_BINSIZE, trunc(?MAX_HEAP_BIN_SIZE / hipe_rtl_arch:word_size()) + 2).
-define(BYTE_SHIFT, 3). %% Turn bits into bytes or vice versa
-define(LOW_BITS, 7). %% Three lowest bits set
-define(BYTE_SIZE, 8).
@@ -180,17 +182,20 @@ gen_rtl({bs_get_binary, Size, Flags}, [Dst, NewMs], Args,
[hipe_rtl:mk_goto(FalseLblName)];
false ->
Unsafe = unsafe(Flags),
- case Args of
- [Ms] ->
- SizeReg = hipe_rtl:mk_new_reg(),
- SizeCode = [hipe_rtl:mk_move(SizeReg, hipe_rtl:mk_imm(Size))];
- [Ms, BitsVar] ->
- {SizeCode, SizeReg} = make_size(Size, BitsVar, FalseLblName)
- end,
- InCode = get_binary(Dst, Ms, SizeReg, Unsafe,
+ {OldMs, SizeReg, SizeCode} =
+ case Args of
+ [Ms] ->
+ SzReg = hipe_rtl:mk_new_reg(),
+ SzCode = [hipe_rtl:mk_move(SzReg, hipe_rtl:mk_imm(Size))],
+ {Ms, SzReg, SzCode};
+ [Ms, BitsVar] ->
+ {SzCode, SzReg} = make_size(Size, BitsVar, FalseLblName),
+ {Ms, SzReg, SzCode}
+ end,
+ InCode = get_binary(Dst, OldMs, SizeReg, Unsafe,
TrueLblName, FalseLblName),
[hipe_rtl:mk_gctest(?SUB_BIN_WORDSIZE)] ++
- update_ms(NewMs, Ms) ++ SizeCode ++ InCode
+ update_ms(NewMs, OldMs) ++ SizeCode ++ InCode
end;
%% ----- bs_get_utf8 -----
gen_rtl(bs_get_utf8, [Dst, NewMs], [Ms], TrueLblName, FalseLblName) ->
@@ -229,14 +234,26 @@ gen_rtl({bs_skip_bits_all, Unit, _Flags}, Dst, [Ms],
skip_bits_all(Unit, Ms, TrueLblName, FalseLblName);
%% ----- bs_skip_bits -----
gen_rtl({bs_skip_bits, Bits}, Dst, [Ms|Args], TrueLblName, FalseLblName) ->
+ MaxValue = (1 bsl (hipe_rtl_arch:word_size() * ?BYTE_SIZE)),
opt_update_ms(Dst, Ms) ++
- case Args of
- [] ->
- skip_bits2(Ms, hipe_rtl:mk_imm(Bits), TrueLblName, FalseLblName);
- [Arg] ->
- {SizeCode, SizeReg} = make_size(Bits, Arg, FalseLblName),
- InCode = skip_bits2(Ms, SizeReg, TrueLblName, FalseLblName),
- SizeCode ++ InCode
+ case Bits < MaxValue of
+ true ->
+ case Args of
+ [] ->
+ skip_bits2(Ms, hipe_rtl:mk_imm(Bits), TrueLblName, FalseLblName);
+ [Arg] ->
+ {SizeCode, SizeReg} = make_size(Bits, Arg, FalseLblName),
+ InCode = skip_bits2(Ms, SizeReg, TrueLblName, FalseLblName),
+ SizeCode ++ InCode
+ end;
+ false -> % handle overflow case
+ case Args of
+ [] ->
+ [hipe_rtl:mk_goto(FalseLblName)];
+ [Arg] ->
+ [hipe_rtl:mk_branch(Arg, 'eq', hipe_tagscheme:mk_fixnum(0),
+ TrueLblName, FalseLblName, 0.5)]
+ end
end;
%% ----- bs_restore -----
gen_rtl({bs_restore, Slot}, [NewMs], [Ms], TrueLblName, _FalseLblName) ->
@@ -317,32 +334,50 @@ float_get_c_code(Dst1, Ms, Size, Flags, TrueLblName, FalseLblName) ->
get_c_code(Func, Dst1, Ms, Size, Flags, TrueLblName, FalseLblName) ->
SizeReg = hipe_rtl:mk_new_reg_gcsafe(),
FlagsReg = hipe_rtl:mk_new_reg_gcsafe(),
+ RetReg = hipe_rtl:mk_new_reg_gcsafe(),
MatchBuf = hipe_rtl:mk_new_reg(),
RetLabel = hipe_rtl:mk_new_label(),
+ OkLabel = hipe_rtl:mk_new_label(),
NonVal = hipe_rtl:mk_imm(hipe_tagscheme:mk_non_value()),
[hipe_rtl:mk_move(SizeReg, Size),
hipe_rtl:mk_move(FlagsReg, hipe_rtl:mk_imm(Flags)),
hipe_tagscheme:extract_matchbuffer(MatchBuf, Ms),
- hipe_rtl_arch:call_bif([Dst1], Func, [SizeReg, FlagsReg, MatchBuf],
+ hipe_rtl_arch:call_bif([RetReg], Func, [SizeReg, FlagsReg, MatchBuf],
hipe_rtl:label_name(RetLabel), FalseLblName),
RetLabel,
- hipe_rtl:mk_branch(Dst1, eq, NonVal, FalseLblName, TrueLblName, 0.01)].
+ hipe_rtl:mk_branch(RetReg, eq, NonVal, FalseLblName,
+ hipe_rtl:label_name(OkLabel), 0.01),
+ OkLabel,
+ hipe_rtl:mk_move(Dst1, RetReg),
+ hipe_rtl:mk_goto(TrueLblName)].
utf8_get_c_code(Dst, Ms, TrueLblName, FalseLblName) ->
+ RetReg = hipe_rtl:mk_new_reg_gcsafe(),
+ OkLabel = hipe_rtl:mk_new_label(),
MatchBuf = hipe_rtl:mk_new_reg(),
NonVal = hipe_rtl:mk_imm(hipe_tagscheme:mk_non_value()),
[hipe_tagscheme:extract_matchbuffer(MatchBuf, Ms),
- hipe_rtl_arch:call_bif([Dst], bs_get_utf8, [MatchBuf], [], []),
- hipe_rtl:mk_branch(Dst, eq, NonVal, FalseLblName, TrueLblName, 0.01)].
+ hipe_rtl_arch:call_bif([RetReg], bs_get_utf8, [MatchBuf], [], []),
+ hipe_rtl:mk_branch(RetReg, eq, NonVal, FalseLblName,
+ hipe_rtl:label_name(OkLabel), 0.01),
+ OkLabel,
+ hipe_rtl:mk_move(Dst, RetReg),
+ hipe_rtl:mk_goto(TrueLblName)].
utf16_get_c_code(Flags, Dst, Ms, TrueLblName, FalseLblName) ->
+ RetReg = hipe_rtl:mk_new_reg_gcsafe(),
+ OkLabel = hipe_rtl:mk_new_label(),
MatchBuf = hipe_rtl:mk_new_reg(),
NonVal = hipe_rtl:mk_imm(hipe_tagscheme:mk_non_value()),
FlagsReg = hipe_rtl:mk_new_reg_gcsafe(),
[hipe_tagscheme:extract_matchbuffer(MatchBuf, Ms),
hipe_rtl:mk_move(FlagsReg, hipe_rtl:mk_imm(Flags)),
- hipe_rtl_arch:call_bif([Dst], bs_get_utf16, [MatchBuf, FlagsReg], [], []),
- hipe_rtl:mk_branch(Dst, eq, NonVal, FalseLblName, TrueLblName, 0.01)].
+ hipe_rtl_arch:call_bif([RetReg], bs_get_utf16, [MatchBuf, FlagsReg], [], []),
+ hipe_rtl:mk_branch(RetReg, eq, NonVal, FalseLblName,
+ hipe_rtl:label_name(OkLabel), 0.01),
+ OkLabel,
+ hipe_rtl:mk_move(Dst, RetReg),
+ hipe_rtl:mk_goto(TrueLblName)].
validate_unicode_retract_c_code(Src, Ms, TrueLblName, FalseLblName) ->
MatchBuf = hipe_rtl:mk_new_reg(),
@@ -697,13 +732,22 @@ get_binary_bytes(Binary, BinSize, Base, Offset, Orig,
%%%%%%%%%%%%%%%%%%%%%%%%% UTILS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_base(Orig,Base) ->
- [HeapLbl,REFCLbl,EndLbl] = create_lbls(3),
+ [HeapLbl,REFCLbl,WritableLbl,NotWritableLbl,EndLbl] = create_lbls(5),
+ Flags = hipe_rtl:mk_new_reg_gcsafe(),
+
[hipe_tagscheme:test_heap_binary(Orig, hipe_rtl:label_name(HeapLbl),
hipe_rtl:label_name(REFCLbl)),
HeapLbl,
hipe_rtl:mk_alu(Base, Orig, 'add', hipe_rtl:mk_imm(?HEAP_BIN_DATA-2)),
hipe_rtl:mk_goto(hipe_rtl:label_name(EndLbl)),
REFCLbl,
+ get_field_from_term({proc_bin, flags}, Orig, Flags),
+ hipe_rtl:mk_branch(Flags, 'ne', hipe_rtl:mk_imm(0),
+ hipe_rtl:label_name(WritableLbl),
+ hipe_rtl:label_name(NotWritableLbl)),
+ WritableLbl,
+ hipe_rtl:mk_call([], emasculate_binary, [Orig], [], [], 'not_remote'),
+ NotWritableLbl,
hipe_rtl:mk_load(Base, Orig, hipe_rtl:mk_imm(?PROC_BIN_BYTES-2)),
EndLbl].
@@ -792,10 +836,10 @@ create_lbls(0) ->
create_lbls(X) when X > 0 ->
[hipe_rtl:mk_new_label()|create_lbls(X-1)].
-make_dyn_prep(SizeReg, CCode) ->
+make_dyn_prep(SizeReg, CCode) ->
[CLbl, SuccessLbl] = create_lbls(2),
- Init = [hipe_rtl:mk_branch(SizeReg, le, hipe_rtl:mk_imm(?MAX_SMALL_BITS),
- hipe_rtl:label_name(SuccessLbl),
+ Init = [hipe_rtl:mk_branch(SizeReg, leu, hipe_rtl:mk_imm(?MAX_SMALL_BITS),
+ hipe_rtl:label_name(SuccessLbl),
hipe_rtl:label_name(CLbl)),
SuccessLbl],
End = [CLbl|CCode],
@@ -840,8 +884,8 @@ get_unaligned_int_to_reg(Reg, Size, Base, Offset, LowBits, Shiftr, Type) ->
hipe_rtl:mk_imm((WordSize-MinLoad)*?BYTE_SIZE))];
{_, WordSize} ->
UnsignedBig = {unsigned, big},
- [hipe_rtl:mk_branch(TotBits, le, hipe_rtl:mk_imm(MinLoad*?BYTE_SIZE),
- hipe_rtl:label_name(LessLbl),
+ [hipe_rtl:mk_branch(TotBits, leu, hipe_rtl:mk_imm(MinLoad*?BYTE_SIZE),
+ hipe_rtl:label_name(LessLbl),
hipe_rtl:label_name(MoreLbl)),
LessLbl,
load_bytes(LoadDst, Base, ByteOffset, Type, MinLoad),
@@ -901,7 +945,7 @@ get_big_unknown_int(Dst1, Base, Offset, NewOffset,
hipe_rtl:mk_alu(ByteOffset, Offset, srl, hipe_rtl:mk_imm(?BYTE_SHIFT)),
load_bytes(LoadDst, Base, ByteOffset, Type, 1),
BackLbl,
- hipe_rtl:mk_branch(ByteOffset, le, Limit, hipe_rtl:label_name(LoopLbl),
+ hipe_rtl:mk_branch(ByteOffset, leu, Limit, hipe_rtl:label_name(LoopLbl),
hipe_rtl:label_name(EndLbl)),
LoopLbl,
load_bytes(Tmp, Base, ByteOffset, {unsigned, big}, 1),
@@ -930,8 +974,8 @@ get_little_unknown_int(Dst1, Base, Offset, NewOffset,
hipe_rtl:mk_alu(Limit, Tmp, srl, hipe_rtl:mk_imm(?BYTE_SHIFT)),
hipe_rtl:mk_move(ShiftReg, hipe_rtl:mk_imm(0)),
BackLbl,
- hipe_rtl:mk_branch(ByteOffset, lt, Limit,
- hipe_rtl:label_name(LoopLbl),
+ hipe_rtl:mk_branch(ByteOffset, ltu, Limit,
+ hipe_rtl:label_name(LoopLbl),
hipe_rtl:label_name(DoneLbl)),
LoopLbl,
load_bytes(Tmp, Base, ByteOffset, {unsigned, big}, 1),
@@ -1047,7 +1091,7 @@ load_bytes(Dst, Base, Offset, {Signedness, Endianness}, X) when X > 1 ->
hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(1)),
hipe_rtl:mk_alu(Dst, Dst, sll, hipe_rtl:mk_imm(8)),
hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1),
- hipe_rtl:mk_branch(Offset, lt, Limit, hipe_rtl:label_name(LoopLbl),
+ hipe_rtl:mk_branch(Offset, ltu, Limit, hipe_rtl:label_name(LoopLbl),
hipe_rtl:label_name(EndLbl)),
EndLbl];
little ->
@@ -1059,7 +1103,7 @@ load_bytes(Dst, Base, Offset, {Signedness, Endianness}, X) when X > 1 ->
hipe_rtl:mk_load(Tmp1, Base, TmpOffset, byte, Signedness),
hipe_rtl:mk_alu(Dst, Dst, sll, hipe_rtl:mk_imm(8)),
hipe_rtl:mk_alu(Dst, Dst, 'or', Tmp1),
- hipe_rtl:mk_branch(Offset, lt, TmpOffset, hipe_rtl:label_name(LoopLbl),
+ hipe_rtl:mk_branch(Offset, ltu, TmpOffset, hipe_rtl:label_name(LoopLbl),
hipe_rtl:label_name(EndLbl)),
EndLbl,
hipe_rtl:mk_move(Offset, Limit)]
@@ -1075,78 +1119,5 @@ create_gcsafe_regs(X) when X > 0 ->
create_gcsafe_regs(0) ->
[].
-first_part(Var, Register, FalseLblName) ->
- [SuccessLbl1, SuccessLbl2] = create_lbls(2),
- [hipe_tagscheme:test_fixnum(Var, hipe_rtl:label_name(SuccessLbl1),
- FalseLblName, 0.99),
- SuccessLbl1,
- hipe_tagscheme:fixnum_ge(Var, hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(0)),
- hipe_rtl:label_name(SuccessLbl2), FalseLblName, 0.99),
- SuccessLbl2,
- hipe_tagscheme:untag_fixnum(Register, Var)].
-
-make_size(1, BitsVar, FalseLblName) ->
- [DstReg] = create_regs(1),
- {first_part(BitsVar, DstReg, FalseLblName), DstReg};
-make_size(?BYTE_SIZE, BitsVar, FalseLblName) ->
- [DstReg] = create_regs(1),
- Code =
- first_part(BitsVar, DstReg, FalseLblName) ++
- [hipe_rtl:mk_alu(DstReg, DstReg, sll, hipe_rtl:mk_imm(?BYTE_SHIFT))],
- {Code, DstReg};
-make_size(UnitImm, BitsVar, FalseLblName) ->
- [DstReg] = create_regs(1),
- UnitList = number2list(UnitImm),
- Code = multiply_code(UnitList, BitsVar, DstReg, FalseLblName),
- {Code, DstReg}.
-
-multiply_code(List=[Head|_Tail], Variable, Result, FalseLblName) ->
- Test = set_high(Head),
- Tmp1 = hipe_rtl:mk_new_reg(),
- SuccessLbl = hipe_rtl:mk_new_label(),
- Register = hipe_rtl:mk_new_reg(),
- Code = [hipe_rtl:mk_move(Result, hipe_rtl:mk_imm(0))|
- first_part(Variable, Register, FalseLblName)]
- ++
- [hipe_rtl:mk_alub(Tmp1, Register, 'and', hipe_rtl:mk_imm(Test),
- eq, hipe_rtl:label_name(SuccessLbl),
- FalseLblName, 0.99),
- SuccessLbl],
- multiply_code(List, Register, Result, FalseLblName, Tmp1, Code).
-
-multiply_code([ShiftSize|Rest], Register, Result, FalseLblName, Tmp1, OldCode) ->
- SuccessLbl = hipe_rtl:mk_new_label(),
- Code =
- OldCode ++
- [hipe_rtl:mk_alu(Tmp1, Register, sll, hipe_rtl:mk_imm(ShiftSize)),
- hipe_rtl:mk_alub(Result, Tmp1, 'add', Result, not_overflow,
- hipe_rtl:label_name(SuccessLbl), FalseLblName, 0.99),
- SuccessLbl],
- multiply_code(Rest, Register, Result, FalseLblName, Tmp1, Code);
-multiply_code([], _Register, _Result, _FalseLblName, _Tmp1, Code) ->
- Code.
-
-number2list(X) when is_integer(X), X >= 0 ->
- number2list(X, []).
-
-number2list(1, Acc) ->
- lists:reverse([0|Acc]);
-number2list(0, Acc) ->
- lists:reverse(Acc);
-number2list(X, Acc) ->
- F = floorlog2(X),
- number2list(X-(1 bsl F), [F|Acc]).
-
-floorlog2(X) ->
- round(math:log(X)/math:log(2)-0.5).
-
-set_high(X) ->
- set_high(X, 0).
-
-set_high(0, Y) ->
- Y;
-set_high(X, Y) ->
- set_high(X-1, Y+(1 bsl (27-X))).
-
is_illegal_const(Const) ->
Const >= 1 bsl (hipe_rtl_arch:word_size() * ?BYTE_SIZE) orelse Const < 0.
diff --git a/lib/hipe/rtl/hipe_rtl_cfg.erl b/lib/hipe/rtl/hipe_rtl_cfg.erl
index b6c1d63262..f49e8f815f 100644
--- a/lib/hipe/rtl/hipe_rtl_cfg.erl
+++ b/lib/hipe/rtl/hipe_rtl_cfg.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_rtl_cleanup_const.erl b/lib/hipe/rtl/hipe_rtl_cleanup_const.erl
index d3e71a56c1..0a1cdbacb8 100644
--- a/lib/hipe/rtl/hipe_rtl_cleanup_const.erl
+++ b/lib/hipe/rtl/hipe_rtl_cleanup_const.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/rtl/hipe_rtl_exceptions.erl b/lib/hipe/rtl/hipe_rtl_exceptions.erl
index 879b84c0b0..331719f344 100644
--- a/lib/hipe/rtl/hipe_rtl_exceptions.erl
+++ b/lib/hipe/rtl/hipe_rtl_exceptions.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_rtl_lcm.erl b/lib/hipe/rtl/hipe_rtl_lcm.erl
index 262aedb409..71bd06c0df 100644
--- a/lib/hipe/rtl/hipe_rtl_lcm.erl
+++ b/lib/hipe/rtl/hipe_rtl_lcm.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -62,10 +63,10 @@ rtl_lcm(CFG, Options) ->
pp_debug("-------------------------------------------------~n",[]),
%% pp_debug( "~w~n", [MFA]),
-
+
%% A check if we should pretty print the result.
case proplists:get_bool(pp_rtl_lcm, Options) of
- true->
+ true ->
pp_debug("-------------------------------------------------~n",[]),
%% pp_debug("AllExpr: ~w~n", [AllExpr]),
pp_debug("AllExpr:~n", []),
@@ -75,21 +76,21 @@ rtl_lcm(CFG, Options) ->
_ ->
ok
end,
-
+
pp_debug("-------------------------------------------------~n",[]),
- ?option_time({CFG1, MoveSet} = perform_lcm(CFG, NodeInfo, EdgeInfo, ExprMap,
- IdMap, AllExpr, mk_edge_bb_map(),
+ {CFG1, MoveSet} = ?option_time(perform_lcm(CFG, NodeInfo, EdgeInfo, ExprMap,
+ IdMap, AllExpr, mk_edge_bb_map(),
?SETS:new(), Labels),
- "RTL LCM perform_lcm", Options),
+ "RTL LCM perform_lcm", Options),
%% Scan through list of moved expressions and replace their
%% assignments with the new temporary created for that expression
MoveList = ?SETS:to_list(MoveSet),
- ?option_time(CFG2 = moved_expr_replace_assignments(CFG1, ExprMap, IdMap,
+ CFG2 = ?option_time(moved_expr_replace_assignments(CFG1, ExprMap, IdMap,
MoveList),
- "RTL LCM moved_expr_replace_assignments", Options),
+ "RTL LCM moved_expr_replace_assignments", Options),
pp_debug("-------------------------------------------------~n~n",[]),
-
+
CFG2.
%%=============================================================================
@@ -465,10 +466,10 @@ expr_clear_dst(I) ->
%% easy access later.
lcm_precalc(CFG, Options) ->
%% Calculate use map and expression map.
- ?option_time({ExprMap, IdMap} = mk_expr_map(CFG),
- "RTL LCM mk_expr_map", Options),
- ?option_time(UseMap = mk_use_map(CFG, ExprMap),
- "RTL LCM mk_use_map", Options),
+ {ExprMap, IdMap} = ?option_time(mk_expr_map(CFG),
+ "RTL LCM mk_expr_map", Options),
+ UseMap = ?option_time(mk_use_map(CFG, ExprMap),
+ "RTL LCM mk_use_map", Options),
%% Labels = hipe_rtl_cfg:reverse_postorder(CFG),
Labels = hipe_rtl_cfg:labels(CFG),
%% StartLabel = hipe_rtl_cfg:start_label(CFG),
@@ -476,28 +477,28 @@ lcm_precalc(CFG, Options) ->
AllExpr = ?SETS:from_list(gb_trees:keys(IdMap)),
%% Calculate the data sets.
- ?option_time(NodeInfo0 = mk_node_info(Labels), "RTL LCM mk_node_info",
- Options),
+ NodeInfo0 = ?option_time(mk_node_info(Labels),
+ "RTL LCM mk_node_info", Options),
%% ?option_time(EdgeInfo0 = mk_edge_info(), "RTL LCM mk_edge_info",
%% Options),
EdgeInfo0 = mk_edge_info(),
- ?option_time(NodeInfo1 = calc_up_exp(CFG, ExprMap, NodeInfo0, Labels),
- "RTL LCM calc_up_exp", Options),
- ?option_time(NodeInfo2 = calc_down_exp(CFG, ExprMap, NodeInfo1, Labels),
- "RTL LCM calc_down_exp", Options),
- ?option_time(NodeInfo3 = calc_killed_expr(CFG, NodeInfo2, UseMap, AllExpr,
+ NodeInfo1 = ?option_time(calc_up_exp(CFG, ExprMap, NodeInfo0, Labels),
+ "RTL LCM calc_up_exp", Options),
+ NodeInfo2 = ?option_time(calc_down_exp(CFG, ExprMap, NodeInfo1, Labels),
+ "RTL LCM calc_down_exp", Options),
+ NodeInfo3 = ?option_time(calc_killed_expr(CFG, NodeInfo2, UseMap, AllExpr,
IdMap, Labels),
- "RTL LCM calc_killed_exp", Options),
- ?option_time(NodeInfo4 = calc_avail(CFG, NodeInfo3),
- "RTL LCM calc_avail", Options),
- ?option_time(NodeInfo5 = calc_antic(CFG, NodeInfo4, AllExpr),
- "RTL LCM calc_antic", Options),
- ?option_time(EdgeInfo1 = calc_earliest(CFG, NodeInfo5, EdgeInfo0, Labels),
- "RTL LCM calc_earliest", Options),
- ?option_time({NodeInfo6, EdgeInfo2} = calc_later(CFG, NodeInfo5, EdgeInfo1),
- "RTL LCM calc_later", Options),
- ?option_time(NodeInfo7 = calc_delete(CFG, NodeInfo6, Labels),
- "RTL LCM calc_delete", Options),
+ "RTL LCM calc_killed_exp", Options),
+ NodeInfo4 = ?option_time(calc_avail(CFG, NodeInfo3),
+ "RTL LCM calc_avail", Options),
+ NodeInfo5 = ?option_time(calc_antic(CFG, NodeInfo4, AllExpr),
+ "RTL LCM calc_antic", Options),
+ EdgeInfo1 = ?option_time(calc_earliest(CFG, NodeInfo5, EdgeInfo0, Labels),
+ "RTL LCM calc_earliest", Options),
+ {NodeInfo6, EdgeInfo2} = ?option_time(calc_later(CFG, NodeInfo5, EdgeInfo1),
+ "RTL LCM calc_later", Options),
+ NodeInfo7 = ?option_time(calc_delete(CFG, NodeInfo6, Labels),
+ "RTL LCM calc_delete", Options),
{NodeInfo7, EdgeInfo2, AllExpr, ExprMap, IdMap, Labels}.
%%%%%%%%%%%%%%%%%%% AVAILABLE IN/OUT FLOW ANALYSIS %%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -940,15 +941,16 @@ calc_insert_edge(NodeInfo, EdgeInfo, From, To) ->
calc_delete(_, NodeInfo, []) ->
NodeInfo;
calc_delete(CFG, NodeInfo, [Label|Labels]) ->
- case Label =:= hipe_rtl_cfg:start_label(CFG) of
- true ->
- NewNodeInfo = set_delete(NodeInfo, Label, ?SETS:new());
- false ->
- UpExp = up_exp(NodeInfo, Label),
- LaterIn = later_in(NodeInfo, Label),
- Delete = ?SETS:subtract(UpExp, LaterIn),
- NewNodeInfo = set_delete(NodeInfo, Label, Delete)
- end,
+ NewNodeInfo =
+ case Label =:= hipe_rtl_cfg:start_label(CFG) of
+ true ->
+ set_delete(NodeInfo, Label, ?SETS:new());
+ false ->
+ UpExp = up_exp(NodeInfo, Label),
+ LaterIn = later_in(NodeInfo, Label),
+ Delete = ?SETS:subtract(UpExp, LaterIn),
+ set_delete(NodeInfo, Label, Delete)
+ end,
calc_delete(CFG, NewNodeInfo, Labels).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/hipe/rtl/hipe_rtl_liveness.erl b/lib/hipe/rtl/hipe_rtl_liveness.erl
index 0c4b6b2e11..674043ec3c 100644
--- a/lib/hipe/rtl/hipe_rtl_liveness.erl
+++ b/lib/hipe/rtl/hipe_rtl_liveness.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_rtl_mk_switch.erl b/lib/hipe/rtl/hipe_rtl_mk_switch.erl
index c14fa5628e..5f9dffa8cf 100644
--- a/lib/hipe/rtl/hipe_rtl_mk_switch.erl
+++ b/lib/hipe/rtl/hipe_rtl_mk_switch.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_rtl_primops.erl b/lib/hipe/rtl/hipe_rtl_primops.erl
index d9d08356ce..062fab842f 100644
--- a/lib/hipe/rtl/hipe_rtl_primops.erl
+++ b/lib/hipe/rtl/hipe_rtl_primops.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_rtl_ssa.erl b/lib/hipe/rtl/hipe_rtl_ssa.erl
index f55cc0dd5c..1e3b21d6be 100644
--- a/lib/hipe/rtl/hipe_rtl_ssa.erl
+++ b/lib/hipe/rtl/hipe_rtl_ssa.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_rtl_ssa_avail_expr.erl b/lib/hipe/rtl/hipe_rtl_ssa_avail_expr.erl
index cae6da542f..f08ff22ed9 100644
--- a/lib/hipe/rtl/hipe_rtl_ssa_avail_expr.erl
+++ b/lib/hipe/rtl/hipe_rtl_ssa_avail_expr.erl
@@ -1,18 +1,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl b/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl
index 2f594333c1..7158383010 100644
--- a/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl
+++ b/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_rtl_ssapre.erl b/lib/hipe/rtl/hipe_rtl_ssapre.erl
index 2ebebb5197..df1a4b9376 100644
--- a/lib/hipe/rtl/hipe_rtl_ssapre.erl
+++ b/lib/hipe/rtl/hipe_rtl_ssapre.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -106,7 +107,7 @@ rtl_ssapre(RtlSSACfg, Options) ->
case XsiList of
[] ->
%% No Xsi
- ?option_time(?pp_debug("~n~n################ No Xsi Inserted ################~n",[]),"RTL A-SSAPRE No Xsi inserted (skip Downsafety and Will Be Available)",Options),
+ ?pp_debug("~n~n################ No Xsi Inserted ################~n",[]),
ok;
_ ->
?pp_debug("~n############ Downsafety ##########~n",[]),
@@ -125,7 +126,7 @@ rtl_ssapre(RtlSSACfg, Options) ->
?pp_debug("~n~n################ Xsi CFG ################~n",[]),pp_cfg(CFG2,XsiGraph),
init_redundancy_count(),
- ?option_time(FinalCFG=perform_code_motion(Labels,CFG2,XsiGraph),"RTL A-SSAPRE Code Motion",Options),
+ FinalCFG = ?option_time(perform_code_motion(Labels,CFG2,XsiGraph),"RTL A-SSAPRE Code Motion",Options),
?pp_debug("\n############ No more need for the Xsi Graph....Deleting...",[]),?GRAPH:delete(XsiGraph),
@@ -145,7 +146,7 @@ perform_Xsi_insertion(Cfg, Options) ->
init_counters(), %% Init counters for Bottoms and Temps
DigraphOpts = [cyclic, private],
XsiGraph = digraph:new(DigraphOpts),
- %% Be carefull, the digraph component is NOT garbage collected,
+ %% Be careful, the digraph component is NOT garbage collected,
%% so don't create 20 millions of instances!
%% finds the longest depth
%% Depth-first, preorder traversal over Basic Blocks.
@@ -153,13 +154,13 @@ perform_Xsi_insertion(Cfg, Options) ->
Labels = ?CFG:preorder(Cfg),
?pp_debug("~n~n############# Finding definitions for computation~n~n",[]),
- ?option_time({Cfg2,XsiGraph} = find_definition_for_computations(Labels,Cfg,XsiGraph),"RTL A-SSAPRE Xsi Insertion, searching from instructions",Options),
+ {Cfg2,XsiGraph} = ?option_time(find_definition_for_computations(Labels,Cfg,XsiGraph),"RTL A-SSAPRE Xsi Insertion, searching from instructions",Options),
%% Active List creation
GeneratorXsiList = lists:sort(?GRAPH:vertices(XsiGraph)),
?pp_debug("~n~n############# Inserted Xsis ~w",[GeneratorXsiList]),
?pp_debug("~n~n############# Finding operands~n",[]),
- ?option_time({Cfg3,XsiGraph} = find_operands(Cfg2,XsiGraph,GeneratorXsiList,0),"RTL A-SSAPRE Xsi Insertion, finding operands",Options),
+ {Cfg3,XsiGraph} = ?option_time(find_operands(Cfg2,XsiGraph,GeneratorXsiList,0),"RTL A-SSAPRE Xsi Insertion, finding operands",Options),
%% Creating the CFGGraph
?pp_debug("~n~n############# Creating CFG Graph",[]),
@@ -169,9 +170,9 @@ perform_Xsi_insertion(Cfg, Options) ->
?pp_debug("~nAdding a vertex for the start label: ~w",[StartLabel]),
?GRAPH:add_vertex(CFGGraph, StartLabel, #block{type = top}),
% Doing the others
- ?option_time(MPs=create_cfggraph(Others,Cfg3,CFGGraph,[],[],[],XsiGraph),"RTL A-SSAPRE Xsi Insertion, creating intermediate 'SSAPRE Graph'",Options),
+ MPs = ?option_time(create_cfggraph(Others,Cfg3,CFGGraph,[],[],[],XsiGraph),"RTL A-SSAPRE Xsi Insertion, creating intermediate 'SSAPRE Graph'",Options),
- %% Return the bloody collected information
+ %% Return the collected information
{Cfg3,XsiGraph,CFGGraph,MPs}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -220,22 +221,21 @@ find_definition_for_computations_in_block(BlockLabel,[Inst|Rest],Cfg,
?pp_debug(" Inserting Xsi: ",[]),pp_xsi(Xsi),
Label = Xsi#xsi.label,
- case BlockLabel =:= Label of
- false ->
- %% Insert the Xsi in the appropriate block
- Code = hipe_bb:code(?CFG:bb(Cfg,Label)),
- {BeforeCode,AfterCode} = split_for_xsi(lists:reverse(Code),[]),
- NewCode = BeforeCode++[XsiLink|AfterCode],
- NewBB = hipe_bb:mk_bb(NewCode),
- NewCfg = ?CFG:bb_add(Cfg,Label,NewBB),
- NewVisited = [NewInst|VisitedInstructions];
- _->
- {BeforeCode,AfterCode} = split_for_xsi(VisitedInstructions,[]),
- TempVisited = BeforeCode++[XsiLink|AfterCode],
- TempVisited2 = lists:reverse(TempVisited),
- NewVisited = [NewInst|TempVisited2],
- NewCfg = Cfg
- end,
+ {NewCfg, NewVisited} =
+ case BlockLabel =:= Label of
+ false ->
+ %% Insert the Xsi in the appropriate block
+ Code = hipe_bb:code(?CFG:bb(Cfg,Label)),
+ {BeforeCode,AfterCode} = split_for_xsi(lists:reverse(Code),[]),
+ NewCode = BeforeCode++[XsiLink|AfterCode],
+ NewBB = hipe_bb:mk_bb(NewCode),
+ {?CFG:bb_add(Cfg,Label,NewBB), [NewInst|VisitedInstructions]};
+ _->
+ {BeforeCode,AfterCode} = split_for_xsi(VisitedInstructions,[]),
+ TempVisited = BeforeCode++[XsiLink|AfterCode],
+ TempVisited2 = lists:reverse(TempVisited),
+ {Cfg, [NewInst|TempVisited2]}
+ end,
find_definition_for_computations_in_block(BlockLabel, Rest, NewCfg,
NewVisited, XsiGraph)
end;
@@ -786,14 +786,15 @@ create_cfggraph([Label|Ls],Cfg,CFGGraph,ToBeFactorizedAcc,MPAcc,LateEdges,XsiGra
Defs = get_defs_in_non_merge_block(Code, []),
?pp_debug("~nAdding a vertex for ~w", [Label]),
Succs = ?CFG:succ(Cfg, Label),
- case Succs of
- [] -> %% Exit point
- ?GRAPH:add_vertex(CFGGraph, Label, #block{type = exit}),
- NewToBeFactorizedAcc = ToBeFactorizedAcc;
- _ -> %% Split point
- ?GRAPH:add_vertex(CFGGraph,Label,#block{type=not_mp,attributes={P,Succs}}),
- NewToBeFactorizedAcc = [Label|ToBeFactorizedAcc]
- end,
+ NewToBeFactorizedAcc =
+ case Succs of
+ [] -> %% Exit point
+ ?GRAPH:add_vertex(CFGGraph, Label, #block{type = exit}),
+ ToBeFactorizedAcc;
+ _ -> %% Split point
+ ?GRAPH:add_vertex(CFGGraph,Label,#block{type=not_mp,attributes={P,Succs}}),
+ [Label|ToBeFactorizedAcc]
+ end,
?pp_debug("~nAdding an edge ~w -> ~w (~w)",[P,Label,Defs]),
case ?GRAPH:add_edge(CFGGraph,P,Label,Defs) of
{error,Reason} ->
@@ -861,56 +862,53 @@ add_edges_for_mp([P|Ps], Label, LateEdges) ->
%% Doesn't do anything so far
add_map_and_uses([], _Key, Maps, Uses) ->
- {Maps,Uses};
+ {Maps, Uses};
add_map_and_uses([XsiOp|Ops], Key, Maps, Uses) ->
- case XsiOp#xsi_op.op of
- #bottom{} ->
- Set = case gb_trees:lookup(XsiOp,Maps) of
- {value, V} ->
- ?SETS:add_element(Key,V);
- none ->
- ?SETS:from_list([Key])
- end,
- NewMaps = gb_trees:enter(XsiOp,Set,Maps),
- NewUses = Uses;
- #temp{} ->
- Set = case gb_trees:lookup(XsiOp,Maps) of
- {value, V} ->
- ?SETS:add_element(Key,V);
- none ->
- ?SETS:from_list([Key])
- end,
- NewMaps = gb_trees:enter(XsiOp,Set,Maps),
- Pred = XsiOp#xsi_op.pred,
- OOP = XsiOp#xsi_op.op,
- SSet = case gb_trees:lookup(Pred,Uses) of
- {value, VV} ->
- ?SETS:add_element(OOP#temp.key,VV);
- none ->
- ?SETS:from_list([OOP#temp.key])
- end,
- NewUses = gb_trees:enter(Pred,SSet,Uses);
- #eop{} ->
- Set = case gb_trees:lookup(XsiOp,Maps) of
- {value, V} ->
- ?SETS:add_element(Key,V);
- none ->
- ?SETS:from_list([Key])
- end,
- NewMaps = gb_trees:enter(XsiOp,Set,Maps),
- Pred = XsiOp#xsi_op.pred,
- Op = XsiOp#xsi_op.op,
- SSet = case gb_trees:lookup(Pred,Uses) of
- {value, VV} ->
- ?SETS:add_element(Op#eop.stopped_by,VV);
- none ->
- ?SETS:from_list([Op#eop.stopped_by])
- end,
- NewUses = gb_trees:enter(Pred,SSet,Uses);
- _->
- NewMaps = Maps,
- NewUses = Uses
- end,
+ {NewMaps, NewUses} =
+ case XsiOp#xsi_op.op of
+ #bottom{} ->
+ Set = case gb_trees:lookup(XsiOp, Maps) of
+ {value, V} ->
+ ?SETS:add_element(Key, V);
+ none ->
+ ?SETS:from_list([Key])
+ end,
+ {gb_trees:enter(XsiOp, Set, Maps), Uses};
+ #temp{} ->
+ Set = case gb_trees:lookup(XsiOp, Maps) of
+ {value, V} ->
+ ?SETS:add_element(Key, V);
+ none ->
+ ?SETS:from_list([Key])
+ end,
+ Pred = XsiOp#xsi_op.pred,
+ OOP = XsiOp#xsi_op.op,
+ SSet = case gb_trees:lookup(Pred, Uses) of
+ {value, VV} ->
+ ?SETS:add_element(OOP#temp.key, VV);
+ none ->
+ ?SETS:from_list([OOP#temp.key])
+ end,
+ {gb_trees:enter(XsiOp, Set, Maps), gb_trees:enter(Pred, SSet, Uses)};
+ #eop{} ->
+ Set = case gb_trees:lookup(XsiOp, Maps) of
+ {value, V} ->
+ ?SETS:add_element(Key, V);
+ none ->
+ ?SETS:from_list([Key])
+ end,
+ Pred = XsiOp#xsi_op.pred,
+ Op = XsiOp#xsi_op.op,
+ SSet = case gb_trees:lookup(Pred, Uses) of
+ {value, VV} ->
+ ?SETS:add_element(Op#eop.stopped_by, VV);
+ none ->
+ ?SETS:from_list([Op#eop.stopped_by])
+ end,
+ {gb_trees:enter(XsiOp, Set, Maps), gb_trees:enter(Pred, SSet, Uses)};
+ _->
+ {Maps, Uses}
+ end,
add_map_and_uses(Ops, Key, NewMaps, NewUses).
post_process([], _CFGGraph) -> ok;
@@ -1161,37 +1159,38 @@ code_motion_in_block(L,[Inst|Insts],Cfg,XsiG,Visited,InsertionsAcc) ->
#pre_candidate{} ->
Def = Inst#pre_candidate.def,
Alu = Inst#pre_candidate.alu,
- case Def of
- bottom ->
- InstToAdd = Alu;
- #temp{} ->
- Key = Def#temp.key,
- {_V,Xsi} = ?GRAPH:vertex(XsiG,Key),
- case Xsi#xsi.wba of
- true ->
- %% Turn into a move
- Dst = ?RTL:alu_dst(Alu),
- Move = ?RTL:mk_move(Dst,Def#temp.var),
- pp_instr(Inst#pre_candidate.alu,nil), ?pp_debug(" ==> ",[]), pp_instr(Move,nil),
- %% Counting redundancies
- redundancy_add(),
- InstToAdd = Move;
- _ ->
- InstToAdd = Alu
- end;
- _ -> %% Def is a real variable
- %% Turn into a move
- Dst = ?RTL:alu_dst(Alu),
- Move = ?RTL:mk_move(Dst,Def),
- pp_instr(Alu,nil), ?pp_debug(" ==> ",[]), pp_instr(Move,nil),
- %% Counting redundancies
- redundancy_add(),
- InstToAdd = Move
- end,
+ InstToAdd =
+ case Def of
+ bottom ->
+ Alu;
+ #temp{} ->
+ Key = Def#temp.key,
+ {_V,Xsi} = ?GRAPH:vertex(XsiG,Key),
+ case Xsi#xsi.wba of
+ true ->
+ %% Turn into a move
+ Dst = ?RTL:alu_dst(Alu),
+ Move = ?RTL:mk_move(Dst,Def#temp.var),
+ pp_instr(Inst#pre_candidate.alu,nil), ?pp_debug(" ==> ",[]), pp_instr(Move,nil),
+ %% Counting redundancies
+ redundancy_add(),
+ Move;
+ _ ->
+ Alu
+ end;
+ _ -> %% Def is a real variable
+ %% Turn into a move
+ Dst = ?RTL:alu_dst(Alu),
+ Move = ?RTL:mk_move(Dst,Def),
+ pp_instr(Alu,nil), ?pp_debug(" ==> ",[]), pp_instr(Move,nil),
+ %% Counting redundancies
+ redundancy_add(),
+ Move
+ end,
code_motion_in_block(L,Insts,Cfg,XsiG,[InstToAdd|Visited],InsertionsAcc);
#xsi_link{} ->
Key = Inst#xsi_link.num,
- {_V,Xsi} = ?GRAPH:vertex(XsiG,Key),
+ {_V,Xsi} = ?GRAPH:vertex(XsiG,Key),
case Xsi#xsi.wba of
true ->
%% Xsi is a WBA, it might trigger insertions
@@ -1234,139 +1233,133 @@ get_insertions([],OpAcc,InsertionsAcc,_Visited,_Expr,_XsiG) ->
get_insertions([XsiOp|Ops],OpAcc,InsertionsAcc,Visited,Expr,XsiG) ->
Pred = XsiOp#xsi_op.pred,
Op = XsiOp#xsi_op.op,
- case Op of
- #bottom{} ->
- case gb_trees:lookup(Pred,InsertionsAcc) of
- {value,Insertion} ->
- From = Insertion#insertion.from,
- case lists:keyfind(Op, 1, From) of
- false ->
- ?pp_debug("~nThere has been insertions along the edge L~w already, but not for that operand | Op=",[Pred]),pp_arg(Op),
- Dst = Op#bottom.var,
- Expr2 = ?RTL:alu_dst_update(Expr,Dst),
- Inst = manufacture_computation(Pred,Expr2,Visited),
- Code = Insertion#insertion.code,
- NewInsertion = Insertion#insertion{from=[{Op,Dst}|From],code=[Inst|Code]},
- NewInsertionsAcc = gb_trees:update(Pred,NewInsertion,InsertionsAcc);
- {_, Val} ->
- ?pp_debug("~nThere has been insertions along the edge L~w already, and for that operand too | Op=",[Pred]),pp_arg(Op),
- Dst = Val,
- NewInsertionsAcc = InsertionsAcc
- end;
- none ->
- ?pp_debug("~nThere has been no insertion along the edge L~w, (and not for that operand, of course)| Op=",[Pred]),pp_arg(Op),
- Dst = Op#bottom.var,
- Expr2 = ?RTL:alu_dst_update(Expr,Dst),
- Inst = manufacture_computation(Pred,Expr2,Visited),
- NewInsertion = #insertion{from=[{Op,Dst}],code=[Inst]},
- NewInsertionsAcc = gb_trees:insert(Pred,NewInsertion,InsertionsAcc)
- end;
- #const_expr{} ->
- case gb_trees:lookup(Pred,InsertionsAcc) of
- {value,Insertion} ->
- From = Insertion#insertion.from,
- case lists:keyfind(Op, 1, From) of
- false ->
- ?pp_debug("~nThere have been insertions along the edge L~w already, but not for that operand | Op=",[Pred]),pp_arg(Op),
- Dst = Op#const_expr.var,
- Val = Op#const_expr.value,
- Inst = ?RTL:mk_move(Dst,Val),
- Code = Insertion#insertion.code,
- NewInsertion = Insertion#insertion{from=[{Op,Dst}|From],code=[Inst|Code]},
- NewInsertionsAcc = gb_trees:update(Pred,NewInsertion,InsertionsAcc);
- {_, Val} ->
- ?pp_debug("~nThere have been insertions along the edge L~w already, and for that operand too | Op=",[Pred]),pp_arg(Op),
- Dst = Val,
- NewInsertionsAcc = InsertionsAcc
- end;
- none ->
- ?pp_debug("~nThere has been no insertion along the edge L~w, (and not for that operand, of course)| Op=",[Pred]),pp_arg(Op),
- Dst = Op#const_expr.var,
- Val = Op#const_expr.value,
- Inst = ?RTL:mk_move(Dst,Val),
- NewInsertion = #insertion{from=[{Op,Dst}],code=[Inst]},
- NewInsertionsAcc = gb_trees:insert(Pred,NewInsertion,InsertionsAcc)
- end;
- #eop{} ->
- %% We treat expressions like bottoms
- %% The value must be recomputed, and therefore not available...
- case gb_trees:lookup(Pred,InsertionsAcc) of
- {value,Insertion} ->
- From = Insertion#insertion.from,
- case lists:keyfind(Op, 1, From) of
- false ->
- ?pp_debug("~nThere has been insertions along the edge L~w already, but not for that operand | Op=",[Pred]),pp_arg(Op),
- Dst = Op#eop.var,
- Expr2 = ?RTL:alu_dst_update(Expr,Dst),
- Inst = manufacture_computation(Pred,Expr2,Visited),
- Code = Insertion#insertion.code,
- NewInsertion = Insertion#insertion{from=[{Op,Dst}|From],code=[Inst|Code]},
- NewInsertionsAcc = gb_trees:update(Pred,NewInsertion,InsertionsAcc);
- {_, Val} ->
- ?pp_debug("~nThere has been insertions along the edge L~w already, and for that operand too | Op=",[Pred]),pp_arg(Op),
- Dst = Val,
- NewInsertionsAcc = InsertionsAcc
- end;
- none ->
- ?pp_debug("~nThere has been no insertion along the edge L~w, (and not for that operand, of course)| Op=",[Pred]),pp_arg(Op),
- Dst = Op#eop.var,
- Expr2 = ?RTL:alu_dst_update(Expr,Dst),
- Inst = manufacture_computation(Pred,Expr2,Visited),
- NewInsertion = #insertion{from=[{Op,Dst}],code=[Inst]},
- NewInsertionsAcc = gb_trees:insert(Pred,NewInsertion,InsertionsAcc)
- end;
- #temp{} ->
- case gb_trees:lookup(Pred,InsertionsAcc) of
- {value,Insertion} ->
- From = Insertion#insertion.from,
- case lists:keyfind(Op, 1, From) of
- false ->
- ?pp_debug("~nThere has been insertions along the edge L~w already, but not for that operand | Op=",[Pred]),pp_arg(Op),
- Key = Op#temp.key,
- {_V,Xsi} = ?GRAPH:vertex(XsiG,Key),
- case Xsi#xsi.wba of
- true ->
- ?pp_debug("~nBut the operand is a WBA Xsi: no need for insertion",[]),
- Dst = Op#temp.var,
- NewInsertionsAcc = InsertionsAcc;
- _ ->
- ?pp_debug("~nBut the operand is a NOT WBA Xsi: we must make an insertion",[]),
- Dst = ?RTL:mk_new_var(),
- Expr2 = ?RTL:alu_dst_update(Expr,Dst),
- Inst = manufacture_computation(Pred,Expr2,Visited),
- Code = Insertion#insertion.code,
- NewInsertion = Insertion#insertion{from=[{Op,Dst}|From],code=[Inst|Code]},
- NewInsertionsAcc = gb_trees:update(Pred,NewInsertion,InsertionsAcc)
- end;
- {_, Val} ->
- ?pp_debug("~nThere has been insertions along the edge L~w already, and for that operand too (Op=~w)",[Pred,Op]),
- ?pp_debug("~nThis means, this temp is a WBA Xsi's definition",[]),
- Dst = Val,
- NewInsertionsAcc = InsertionsAcc
- end;
- none ->
- ?pp_debug("~nThere has been no insertion along the edge L~w, (and not for that operand, of course | Op=",[Pred]),pp_arg(Op),
- Key = Op#temp.key,
- {_V,Xsi} = ?GRAPH:vertex(XsiG,Key),
- case Xsi#xsi.wba of
- true ->
- ?pp_debug("~nBut the operand is a WBA Xsi: no need for insertion",[]),
- Dst = Op#temp.var,
- NewInsertionsAcc = InsertionsAcc;
- _ ->
- ?pp_debug("~nBut the operand is a NOT WBA Xsi: we must make an insertion",[]),
- Dst = ?RTL:mk_new_var(),
- Expr2 = ?RTL:alu_dst_update(Expr,Dst),
- Inst = manufacture_computation(Pred,Expr2,Visited),
- NewInsertion = #insertion{from=[{Op,Dst}],code=[Inst]},
- NewInsertionsAcc = gb_trees:insert(Pred,NewInsertion,InsertionsAcc)
- end
- end;
- _ ->
- ?pp_debug("~nThe operand (Op=",[]),pp_arg(Op),?pp_debug(") is a real variable, no need for insertion along L~w",[Pred]),
- Dst = Op,
- NewInsertionsAcc = InsertionsAcc
- end,
+ {Dst, NewInsertionsAcc} =
+ case Op of
+ #bottom{} ->
+ case gb_trees:lookup(Pred,InsertionsAcc) of
+ {value,Insertion} ->
+ From = Insertion#insertion.from,
+ case lists:keyfind(Op, 1, From) of
+ false ->
+ ?pp_debug("~nThere has been insertions along the edge L~w already, but not for that operand | Op=",[Pred]),pp_arg(Op),
+ D = Op#bottom.var,
+ Expr2 = ?RTL:alu_dst_update(Expr,D),
+ Inst = manufacture_computation(Pred,Expr2,Visited),
+ Code = Insertion#insertion.code,
+ NewInsertion = Insertion#insertion{from=[{Op,D}|From],code=[Inst|Code]},
+ {D, gb_trees:update(Pred, NewInsertion, InsertionsAcc)};
+ {_, Val} ->
+ ?pp_debug("~nThere has been insertions along the edge L~w already, and for that operand too | Op=",[Pred]),pp_arg(Op),
+ {Val, InsertionsAcc}
+ end;
+ none ->
+ ?pp_debug("~nThere has been no insertion along the edge L~w, (and not for that operand, of course)| Op=",[Pred]),pp_arg(Op),
+ D = Op#bottom.var,
+ Expr2 = ?RTL:alu_dst_update(Expr, D),
+ Inst = manufacture_computation(Pred,Expr2,Visited),
+ NewInsertion = #insertion{from=[{Op,D}],code=[Inst]},
+ {D, gb_trees:insert(Pred,NewInsertion, InsertionsAcc)}
+ end;
+ #const_expr{} ->
+ case gb_trees:lookup(Pred,InsertionsAcc) of
+ {value,Insertion} ->
+ From = Insertion#insertion.from,
+ case lists:keyfind(Op, 1, From) of
+ false ->
+ ?pp_debug("~nThere have been insertions along the edge L~w already, but not for that operand | Op=",[Pred]),pp_arg(Op),
+ D = Op#const_expr.var,
+ Val = Op#const_expr.value,
+ Inst = ?RTL:mk_move(D, Val),
+ Code = Insertion#insertion.code,
+ NewInsertion = Insertion#insertion{from=[{Op,D}|From],code=[Inst|Code]},
+ {D, gb_trees:update(Pred,NewInsertion,InsertionsAcc)};
+ {_, Val} ->
+ ?pp_debug("~nThere have been insertions along the edge L~w already, and for that operand too | Op=",[Pred]),pp_arg(Op),
+ {Val, InsertionsAcc}
+ end;
+ none ->
+ ?pp_debug("~nThere has been no insertion along the edge L~w, (and not for that operand, of course)| Op=",[Pred]),pp_arg(Op),
+ D = Op#const_expr.var,
+ Val = Op#const_expr.value,
+ Inst = ?RTL:mk_move(D, Val),
+ NewInsertion = #insertion{from=[{Op,D}],code=[Inst]},
+ {D, gb_trees:insert(Pred,NewInsertion, InsertionsAcc)}
+ end;
+ #eop{} ->
+ %% We treat expressions like bottoms
+ %% The value must be recomputed, and therefore not available...
+ case gb_trees:lookup(Pred,InsertionsAcc) of
+ {value,Insertion} ->
+ From = Insertion#insertion.from,
+ case lists:keyfind(Op, 1, From) of
+ false ->
+ ?pp_debug("~nThere has been insertions along the edge L~w already, but not for that operand | Op=",[Pred]),pp_arg(Op),
+ D = Op#eop.var,
+ Expr2 = ?RTL:alu_dst_update(Expr, D),
+ Inst = manufacture_computation(Pred,Expr2,Visited),
+ Code = Insertion#insertion.code,
+ NewInsertion = Insertion#insertion{from=[{Op,D}|From],code=[Inst|Code]},
+ {D, gb_trees:update(Pred,NewInsertion, InsertionsAcc)};
+ {_, Val} ->
+ ?pp_debug("~nThere has been insertions along the edge L~w already, and for that operand too | Op=",[Pred]),pp_arg(Op),
+ {Val, InsertionsAcc}
+ end;
+ none ->
+ ?pp_debug("~nThere has been no insertion along the edge L~w, (and not for that operand, of course)| Op=",[Pred]),pp_arg(Op),
+ D = Op#eop.var,
+ Expr2 = ?RTL:alu_dst_update(Expr, D),
+ Inst = manufacture_computation(Pred,Expr2,Visited),
+ NewInsertion = #insertion{from=[{Op,D}],code=[Inst]},
+ {D, gb_trees:insert(Pred, NewInsertion, InsertionsAcc)}
+ end;
+ #temp{} ->
+ case gb_trees:lookup(Pred,InsertionsAcc) of
+ {value,Insertion} ->
+ From = Insertion#insertion.from,
+ case lists:keyfind(Op, 1, From) of
+ false ->
+ ?pp_debug("~nThere has been insertions along the edge L~w already, but not for that operand | Op=",[Pred]),pp_arg(Op),
+ Key = Op#temp.key,
+ {_V,Xsi} = ?GRAPH:vertex(XsiG,Key),
+ case Xsi#xsi.wba of
+ true ->
+ ?pp_debug("~nBut the operand is a WBA Xsi: no need for insertion",[]),
+ {Op#temp.var, InsertionsAcc};
+ _ ->
+ ?pp_debug("~nBut the operand is a NOT WBA Xsi: we must make an insertion",[]),
+ D = ?RTL:mk_new_var(),
+ Expr2 = ?RTL:alu_dst_update(Expr, D),
+ Inst = manufacture_computation(Pred,Expr2,Visited),
+ Code = Insertion#insertion.code,
+ NewInsertion = Insertion#insertion{from=[{Op,D}|From],code=[Inst|Code]},
+ {D, gb_trees:update(Pred, NewInsertion, InsertionsAcc)}
+ end;
+ {_, Val} ->
+ ?pp_debug("~nThere has been insertions along the edge L~w already, and for that operand too (Op=~w)",[Pred,Op]),
+ ?pp_debug("~nThis means, this temp is a WBA Xsi's definition",[]),
+ {Val, InsertionsAcc}
+ end;
+ none ->
+ ?pp_debug("~nThere has been no insertion along the edge L~w, (and not for that operand, of course | Op=",[Pred]),pp_arg(Op),
+ Key = Op#temp.key,
+ {_V,Xsi} = ?GRAPH:vertex(XsiG,Key),
+ case Xsi#xsi.wba of
+ true ->
+ ?pp_debug("~nBut the operand is a WBA Xsi: no need for insertion",[]),
+ {Op#temp.var, InsertionsAcc};
+ _ ->
+ ?pp_debug("~nBut the operand is a NOT WBA Xsi: we must make an insertion",[]),
+ D = ?RTL:mk_new_var(),
+ Expr2 = ?RTL:alu_dst_update(Expr, D),
+ Inst = manufacture_computation(Pred,Expr2,Visited),
+ NewInsertion = #insertion{from=[{Op,D}],code=[Inst]},
+ {D, gb_trees:insert(Pred, NewInsertion, InsertionsAcc)}
+ end
+ end;
+ _ ->
+ ?pp_debug("~nThe operand (Op=",[]),pp_arg(Op),?pp_debug(") is a real variable, no need for insertion along L~w",[Pred]),
+ {Op, InsertionsAcc}
+ end,
NewXsiOp = XsiOp#xsi_op{op=Dst},
get_insertions(Ops, [NewXsiOp|OpAcc], NewInsertionsAcc, Visited, Expr, XsiG).
diff --git a/lib/hipe/rtl/hipe_rtl_symbolic.erl b/lib/hipe/rtl/hipe_rtl_symbolic.erl
index bc8640dec9..1d7e0ec55e 100644
--- a/lib/hipe/rtl/hipe_rtl_symbolic.erl
+++ b/lib/hipe/rtl/hipe_rtl_symbolic.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_rtl_varmap.erl b/lib/hipe/rtl/hipe_rtl_varmap.erl
index 9bd5e88611..31165d91a4 100644
--- a/lib/hipe/rtl/hipe_rtl_varmap.erl
+++ b/lib/hipe/rtl/hipe_rtl_varmap.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/rtl/hipe_tagscheme.erl b/lib/hipe/rtl/hipe_tagscheme.erl
index c27c682915..8825a3ade3 100644
--- a/lib/hipe/rtl/hipe_tagscheme.erl
+++ b/lib/hipe/rtl/hipe_tagscheme.erl
@@ -2,25 +2,26 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
%%========================================================================
%%
%% Filename : hipe_tagscheme.erl
-%% Note : This is specific to Erlang 5.* (i.e. starting with R9).
+%% Note : This is specific to Erlang >= 5.* (i.e. starting with R9).
%%
%% Modifications:
%% 020904: Happi - added support for external pids and ports.
@@ -40,7 +41,8 @@
test_any_pid/4, test_any_port/4,
test_ref/4, test_fun/4, test_fun2/5, test_matchstate/4,
test_binary/4, test_bitstr/4, test_list/4, test_map/4,
- test_integer/4, test_number/4, test_tuple_N/5]).
+ test_integer/4, test_number/4, test_tuple_N/5,
+ test_pos_bignum_arity/6]).
-export([realtag_fixnum/2, tag_fixnum/2, realuntag_fixnum/2, untag_fixnum/2]).
-export([test_two_fixnums/3, test_fixnums/4, unsafe_fixnum_add/3,
unsafe_fixnum_sub/3,
@@ -52,9 +54,10 @@
-export([unsafe_closure_element/3]).
-export([mk_fun_header/0, tag_fun/2]).
-export([unsafe_untag_float/2, unsafe_tag_float/2]).
--export([mk_sub_binary/6,mk_sub_binary/7]).
+-export([mk_sub_binary/6, mk_sub_binary/7]).
-export([unsafe_mk_big/3, unsafe_load_float/3]).
--export([bignum_sizeneed/1,bignum_sizeneed_code/2, get_one_word_pos_bignum/3]).
+-export([bignum_sizeneed/1, bignum_sizeneed_code/2, get_one_word_pos_bignum/3,
+ unsafe_get_one_word_pos_bignum/2]).
-export([test_subbinary/3, test_heap_binary/3]).
-export([create_heap_binary/3, create_refc_binary/3, create_refc_binary/4]).
-export([create_matchstate/6, convert_matchstate/1, compare_matchstate/4]).
@@ -141,7 +144,7 @@ mk_non_value() -> ?THE_NON_VALUE.
-spec is_fixnum(integer()) -> boolean().
is_fixnum(N) when is_integer(N) ->
Bits = ?bytes_to_bits(hipe_rtl_arch:word_size()) - ?TAG_IMMED1_SIZE,
- (N =< ((1 bsl (Bits - 1)) - 1)) and (N >= -(1 bsl (Bits - 1))).
+ (N =< ((1 bsl (Bits - 1)) - 1)) andalso (N >= -(1 bsl (Bits - 1))).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -348,6 +351,24 @@ test_pos_bignum(X, TrueLab, FalseLab, Pred) ->
mask_and_compare(Tmp, BigMask, ?TAG_HEADER_POS_BIG,
TrueLab, FalseLab, Pred)].
+test_pos_bignum_arity(X, Arity, TrueLab, NotPosBignumLab, FalseLab, Pred) ->
+ Tmp = hipe_rtl:mk_new_reg_gcsafe(),
+ BoxedLab = hipe_rtl:mk_new_label(),
+ HeaderImm = hipe_rtl:mk_imm(mk_header(Arity, ?TAG_HEADER_POS_BIG)),
+ [test_is_boxed(X, hipe_rtl:label_name(BoxedLab), NotPosBignumLab, Pred),
+ BoxedLab,
+ get_header(Tmp, X)] ++
+ case NotPosBignumLab =:= FalseLab of
+ true -> [];
+ false ->
+ BignumLab = hipe_rtl:mk_new_label(),
+ BigMask = ?TAG_HEADER_MASK,
+ [mask_and_compare(Tmp, BigMask, ?TAG_HEADER_POS_BIG,
+ hipe_rtl:label_name(BignumLab), NotPosBignumLab, Pred),
+ BignumLab]
+ end ++
+ [hipe_rtl:mk_branch(Tmp, 'eq', HeaderImm, TrueLab, FalseLab, Pred)].
+
test_matchstate(X, TrueLab, FalseLab, Pred) ->
Tmp = hipe_rtl:mk_new_reg_gcsafe(),
HalfTrueLab = hipe_rtl:mk_new_label(),
@@ -962,22 +983,25 @@ get_one_word_pos_bignum(USize, Size, Fail) ->
Header = hipe_rtl:mk_new_reg(),
HalfLbl = hipe_rtl:mk_new_label(),
HalfLblName = hipe_rtl:label_name(HalfLbl),
- WordSize = hipe_rtl_arch:word_size(),
PosHead = hipe_rtl:mk_imm(mk_header(1, ?TAG_HEADER_POS_BIG)),
[get_header(Header, Size),
hipe_rtl:mk_branch(Header, eq, PosHead, HalfLblName, Fail),
- HalfLbl,
- hipe_rtl:mk_load(USize, Size, hipe_rtl:mk_imm(1*WordSize
- -?TAG_PRIMARY_BOXED))].
+ HalfLbl |
+ unsafe_get_one_word_pos_bignum(USize, Size)].
+
+unsafe_get_one_word_pos_bignum(USize, Size) ->
+ WordSize = hipe_rtl_arch:word_size(),
+ Imm = hipe_rtl:mk_imm(1*WordSize-?TAG_PRIMARY_BOXED),
+ [hipe_rtl:mk_load(USize, Size, Imm)].
-spec bignum_sizeneed(non_neg_integer()) -> non_neg_integer().
bignum_sizeneed(Size) ->
- WordSizeBits = hipe_rtl_arch:word_size() * 8,
case is_fixnum(1 bsl Size) of
true ->
0;
false ->
+ WordSizeBits = hipe_rtl_arch:word_size() * 8,
((Size + (WordSizeBits-1)) div WordSizeBits) + 1
end.
@@ -1116,14 +1140,11 @@ get_field_offset({matchbuffer, binsize}) ->
?MB_SIZE.
get_field_size(Field) ->
- size_to_atom(get_field_size1(Field)).
-
-size_to_atom(Bytes) ->
WordSize = hipe_rtl_arch:word_size(),
- case Bytes of
+ case get_field_size1(Field) of
WordSize -> word;
- 4 -> int32;
- %%2 -> int16; So far there are no 2 byte fields
+ %% 4 -> int32; Seems not needed: covered by the previous case
+ %% 2 -> int16; So far there are no 2 byte fields
1 -> byte
end.
diff --git a/lib/hipe/sparc/Makefile b/lib/hipe/sparc/Makefile
index eb40117691..0e36a43d8e 100644
--- a/lib/hipe/sparc/Makefile
+++ b/lib/hipe/sparc/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -75,7 +76,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars
+ERL_COMPILE_FLAGS += -Werror +warn_export_vars
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/sparc/hipe_rtl_to_sparc.erl b/lib/hipe/sparc/hipe_rtl_to_sparc.erl
index fd21be3ae7..f9c043eafe 100644
--- a/lib/hipe/sparc/hipe_rtl_to_sparc.erl
+++ b/lib/hipe/sparc/hipe_rtl_to_sparc.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -749,13 +750,25 @@ xaluop_commutes(XAluOp) ->
xaluop_is_shift(XAluOp) ->
case XAluOp of
+ 'add' -> false;
+ 'addcc' -> false;
+ 'and' -> false;
+ 'andcc' -> false;
+ 'cmpcc' -> false;
+ 'ldsb' -> false;
+ 'ldub' -> false;
+ 'lduw' -> false;
+ 'or' -> false;
'sll' -> true;
- 'srl' -> true;
+ %% 'sllx' -> true;
+ 'smul' -> false;
'sra' -> true;
- 'sllx' -> true;
- 'srlx' -> true;
- 'srax' -> true;
- _ -> false
+ %% 'srax' -> true;
+ 'srl' -> true;
+ %% 'srlx' -> true;
+ 'sub' -> false;
+ 'subcc' -> false;
+ 'xor' -> false
end.
%%% Convert an extended SPARC AluOp back to a plain AluOp.
@@ -763,9 +776,23 @@ xaluop_is_shift(XAluOp) ->
xaluop_normalise(XAluOp) ->
case XAluOp of
- 'cmp' -> 'sub';
+ 'add' -> 'add';
+ 'addcc' -> 'addcc';
+ 'and' -> 'and';
+ 'andcc' -> 'andcc';
+ %% 'cmp' -> 'sub';
'cmpcc' -> 'subcc';
- _ -> XAluOp
+ 'ldsb' -> 'ldsb';
+ 'ldub' -> 'ldub';
+ 'lduw' -> 'lduw';
+ 'or' -> 'or';
+ 'sll' -> 'sll';
+ 'smul' -> 'smul';
+ 'sra' -> 'sra';
+ 'srl' -> 'srl';
+ 'sub' -> 'sub';
+ 'subcc' -> 'subcc';
+ 'xor' -> 'xor'
end.
%%% Convert an RTL condition code.
diff --git a/lib/hipe/sparc/hipe_sparc.erl b/lib/hipe/sparc/hipe_sparc.erl
index 9fcb94afb6..5ecb6aa8b9 100644
--- a/lib/hipe/sparc/hipe_sparc.erl
+++ b/lib/hipe/sparc/hipe_sparc.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc.hrl b/lib/hipe/sparc/hipe_sparc.hrl
index 107541f96a..01c8d07f22 100644
--- a/lib/hipe/sparc/hipe_sparc.hrl
+++ b/lib/hipe/sparc/hipe_sparc.hrl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_assemble.erl b/lib/hipe/sparc/hipe_sparc_assemble.erl
index 68a4e1b349..e92f024968 100644
--- a/lib/hipe/sparc/hipe_sparc_assemble.erl
+++ b/lib/hipe/sparc/hipe_sparc_assemble.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -48,7 +49,7 @@ assemble(CompiledCode, Closures, Exports, Options) ->
DataRelocs = hipe_pack_constants:mk_data_relocs(RefsFromConsts, LabelMap),
SSE = hipe_pack_constants:slim_sorted_exportmap(ExportMap,Closures,Exports),
SlimRefs = hipe_pack_constants:slim_refs(AccRefs),
- Bin = term_to_binary([{?VERSION_STRING(),?HIPE_SYSTEM_CRC},
+ Bin = term_to_binary([{?VERSION_STRING(),?HIPE_ERTS_CHECKSUM},
ConstAlign, ConstSize,
SC,
DataRelocs, % nee LM, LabelMap
diff --git a/lib/hipe/sparc/hipe_sparc_cfg.erl b/lib/hipe/sparc/hipe_sparc_cfg.erl
index d938a3bdf1..0b2c77f27b 100644
--- a/lib/hipe/sparc/hipe_sparc_cfg.erl
+++ b/lib/hipe/sparc/hipe_sparc_cfg.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_defuse.erl b/lib/hipe/sparc/hipe_sparc_defuse.erl
index d59ad436b5..4f66299f1d 100644
--- a/lib/hipe/sparc/hipe_sparc_defuse.erl
+++ b/lib/hipe/sparc/hipe_sparc_defuse.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_encode.erl b/lib/hipe/sparc/hipe_sparc_encode.erl
index 8a28f33ab9..6a7d502fd3 100644
--- a/lib/hipe/sparc/hipe_sparc_encode.erl
+++ b/lib/hipe/sparc/hipe_sparc_encode.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/sparc/hipe_sparc_finalise.erl b/lib/hipe/sparc/hipe_sparc_finalise.erl
index b44a21f7c0..2b7125fb73 100644
--- a/lib/hipe/sparc/hipe_sparc_finalise.erl
+++ b/lib/hipe/sparc/hipe_sparc_finalise.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_frame.erl b/lib/hipe/sparc/hipe_sparc_frame.erl
index f7d7f40df3..a42c1983f4 100644
--- a/lib/hipe/sparc/hipe_sparc_frame.erl
+++ b/lib/hipe/sparc/hipe_sparc_frame.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_liveness_all.erl b/lib/hipe/sparc/hipe_sparc_liveness_all.erl
index c6f78f9f7a..b7c3e1962a 100644
--- a/lib/hipe/sparc/hipe_sparc_liveness_all.erl
+++ b/lib/hipe/sparc/hipe_sparc_liveness_all.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_liveness_fpr.erl b/lib/hipe/sparc/hipe_sparc_liveness_fpr.erl
index ac67e499ad..497c554c3e 100644
--- a/lib/hipe/sparc/hipe_sparc_liveness_fpr.erl
+++ b/lib/hipe/sparc/hipe_sparc_liveness_fpr.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_liveness_gpr.erl b/lib/hipe/sparc/hipe_sparc_liveness_gpr.erl
index 0b07ae5c9d..55d639e3a2 100644
--- a/lib/hipe/sparc/hipe_sparc_liveness_gpr.erl
+++ b/lib/hipe/sparc/hipe_sparc_liveness_gpr.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_main.erl b/lib/hipe/sparc/hipe_sparc_main.erl
index 2e5c8e0494..c16751c7bd 100644
--- a/lib/hipe/sparc/hipe_sparc_main.erl
+++ b/lib/hipe/sparc/hipe_sparc_main.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_pp.erl b/lib/hipe/sparc/hipe_sparc_pp.erl
index 6b49acdd11..8fa0a9c788 100644
--- a/lib/hipe/sparc/hipe_sparc_pp.erl
+++ b/lib/hipe/sparc/hipe_sparc_pp.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_ra.erl b/lib/hipe/sparc/hipe_sparc_ra.erl
index 40360e97fe..afea8c9b4c 100644
--- a/lib/hipe/sparc/hipe_sparc_ra.erl
+++ b/lib/hipe/sparc/hipe_sparc_ra.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_ra_finalise.erl b/lib/hipe/sparc/hipe_sparc_ra_finalise.erl
index 3403636118..dc1e69c101 100644
--- a/lib/hipe/sparc/hipe_sparc_ra_finalise.erl
+++ b/lib/hipe/sparc/hipe_sparc_ra_finalise.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_ra_ls.erl b/lib/hipe/sparc/hipe_sparc_ra_ls.erl
index cdb15e738c..19e7c92d2f 100644
--- a/lib/hipe/sparc/hipe_sparc_ra_ls.erl
+++ b/lib/hipe/sparc/hipe_sparc_ra_ls.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_ra_naive.erl b/lib/hipe/sparc/hipe_sparc_ra_naive.erl
index 8c378c4850..b6c33dec6c 100644
--- a/lib/hipe/sparc/hipe_sparc_ra_naive.erl
+++ b/lib/hipe/sparc/hipe_sparc_ra_naive.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_ra_postconditions.erl b/lib/hipe/sparc/hipe_sparc_ra_postconditions.erl
index f7fdae0491..ab31b3c8d9 100644
--- a/lib/hipe/sparc/hipe_sparc_ra_postconditions.erl
+++ b/lib/hipe/sparc/hipe_sparc_ra_postconditions.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_ra_postconditions_fp.erl b/lib/hipe/sparc/hipe_sparc_ra_postconditions_fp.erl
index 17dc0f88d5..d893ac26e9 100644
--- a/lib/hipe/sparc/hipe_sparc_ra_postconditions_fp.erl
+++ b/lib/hipe/sparc/hipe_sparc_ra_postconditions_fp.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/sparc/hipe_sparc_registers.erl b/lib/hipe/sparc/hipe_sparc_registers.erl
index adb01a65ca..6681a10070 100644
--- a/lib/hipe/sparc/hipe_sparc_registers.erl
+++ b/lib/hipe/sparc/hipe_sparc_registers.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -85,6 +86,8 @@
-define(I7, 31).
-define(LAST_PRECOLOURED,31). % must handle both GRP and FPR ranges
+-define(RA, ?O7).
+
-define(ARG0, ?O1).
-define(ARG1, ?O2).
-define(ARG2, ?O3).
@@ -173,7 +176,7 @@ stack_pointer() -> ?STACK_POINTER.
proc_pointer() -> ?PROC_POINTER.
-return_address() -> ?O7.
+return_address() -> ?RA.
g0() -> ?G0.
@@ -282,7 +285,9 @@ call_clobbered() -> % does the RA strip the type or not?
].
tailcall_clobbered() -> % tailcall crapola needs one temp
- [{?TEMP1,tagged},{?TEMP1,untagged}].
+ [{?TEMP1,tagged},{?TEMP1,untagged}
+ ,{?RA,tagged},{?RA,untagged}
+ ].
live_at_return() ->
[{?HEAP_POINTER,untagged},
diff --git a/lib/hipe/ssa/hipe_ssa.inc b/lib/hipe/ssa/hipe_ssa.inc
index 2766c10e4f..83ab320306 100644
--- a/lib/hipe/ssa/hipe_ssa.inc
+++ b/lib/hipe/ssa/hipe_ssa.inc
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ssa/hipe_ssa_const_prop.inc b/lib/hipe/ssa/hipe_ssa_const_prop.inc
index 0876fca34a..648490f9a3 100644
--- a/lib/hipe/ssa/hipe_ssa_const_prop.inc
+++ b/lib/hipe/ssa/hipe_ssa_const_prop.inc
@@ -3,18 +3,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/ssa/hipe_ssa_copy_prop.inc b/lib/hipe/ssa/hipe_ssa_copy_prop.inc
index 311940a1fc..fd80d97b02 100644
--- a/lib/hipe/ssa/hipe_ssa_copy_prop.inc
+++ b/lib/hipe/ssa/hipe_ssa_copy_prop.inc
@@ -3,18 +3,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/ssa/hipe_ssa_liveness.inc b/lib/hipe/ssa/hipe_ssa_liveness.inc
index 05c8a88059..78488c65fc 100644
--- a/lib/hipe/ssa/hipe_ssa_liveness.inc
+++ b/lib/hipe/ssa/hipe_ssa_liveness.inc
@@ -3,18 +3,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/test/Makefile b/lib/hipe/test/Makefile
index 009f503abb..544888719f 100644
--- a/lib/hipe/test/Makefile
+++ b/lib/hipe/test/Makefile
@@ -6,12 +6,15 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# ----------------------------------------------------
MODULES= \
- hipe_SUITE
+ hipe_SUITE \
+ opt_verify_SUITE
# .erl files for these modules are automatically generated
GEN_MODULES= \
+ basic_SUITE \
bs_SUITE \
- maps_SUITE
+ maps_SUITE \
+ sanity_SUITE
ERL_FILES= $(MODULES:%=%.erl)
@@ -34,7 +37,7 @@ RELSYSDIR = $(RELEASE_PATH)/hipe_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
@@ -77,4 +80,4 @@ release_tests_spec: make_emakefile
@tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
cd "$(RELSYSDIR)";\
erlc hipe_testsuite_driver.erl;\
- erl -noshell -run hipe_testsuite_driver create_all_suites -s erlang halt
+ erl -noshell -run hipe_testsuite_driver create_all_suites $(GEN_MODULES) -s erlang halt
diff --git a/lib/hipe/test/basic_SUITE_data/basic_arith.erl b/lib/hipe/test/basic_SUITE_data/basic_arith.erl
new file mode 100644
index 0000000000..28e99be053
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_arith.erl
@@ -0,0 +1,72 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%---------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests cases for compilation of arithmetic.
+%%%---------------------------------------------------------------------
+-module(basic_arith).
+
+-export([test/0]).
+
+test() ->
+ ok = test_rem(),
+ ok = test_bit_ops(),
+ ok = test_uplus(),
+ ok = test_bsl_errors(),
+ ok.
+
+%%----------------------------------------------------------------------
+%% Tests the remainder operator.
+
+test_rem() ->
+ 2 = ret_rem(42, 20),
+ -2 = ret_rem(-42, 20),
+ -2 = ret_rem(-42, -20),
+ {'EXIT', {badarith, _}} = ret_rem(3.14, 2),
+ {'EXIT', {badarith, _}} = ret_rem(42, 3.14),
+ ok.
+
+ret_rem(X, Y) ->
+ catch X rem Y.
+
+%%----------------------------------------------------------------------
+%%
+
+test_bit_ops() ->
+ 2 = bbb(11, 2, 16#3ff),
+ ok.
+
+bbb(X, Y, Z) ->
+ ((1 bsl X) bor Y) band Z.
+
+%%----------------------------------------------------------------------
+%% Tests unary plus: it used to be the identity function but not anymore
+
+test_uplus() ->
+ badarith = try uplus(gazonk) catch error:Err -> Err end,
+ 42 = uplus(42),
+ ok.
+
+uplus(X) -> +(X).
+
+%%----------------------------------------------------------------------
+%% The first part of this test triggered a bug in the emulator as one
+%% of the arguments to bsl is not an integer.
+%%
+%% The second part triggered a compilation crash since an arithmetic
+%% expression resulting in a 'system_limit' exception was statically
+%% evaluated and an arithmetic result was expected.
+
+test_bsl_errors() ->
+ {'EXIT', {'badarith', _}} = (catch (t1(0, pad, 0))),
+ badarith = try t2(0, pad, 0) catch error:Err1 -> Err1 end,
+ system_limit = try (id(1) bsl 100000000) catch error:Err2 -> Err2 end,
+ ok.
+
+t1(_, X, _) ->
+ (1 bsl X) + 1.
+
+t2(_, X, _) ->
+ (X bsl 1) + 1.
+
+id(I) -> I.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_beam_instrs.erl b/lib/hipe/test/basic_SUITE_data/basic_beam_instrs.erl
new file mode 100644
index 0000000000..6fafea3b09
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_beam_instrs.erl
@@ -0,0 +1,102 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Tests for correct translation of various BEAM instructions.
+%%%-------------------------------------------------------------------
+-module(basic_beam_instrs).
+
+-export([test/0]).
+
+test() ->
+ ok = test_make_fun(),
+ ok = test_switch_val(),
+ ok = test_put_literal(),
+ ok = test_set_tuple_element(),
+ ok = test_unguarded_unsafe_element(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Tests whether the translation of make_fun works.
+
+test_make_fun() ->
+ {F, G} = double_the_fun(),
+ ok = F(),
+ {ok, 42} = G(42),
+ FV1 = {ok, free_var1},
+ FV2 = {also, {free, var2}},
+ {FV1, {ok, [bv]}, FV2} = contains_fun(FV1, ignored, FV2),
+ ok.
+
+double_the_fun() ->
+ {fun () -> ok end, fun (V) -> {ok, V} end}.
+
+contains_fun(X, _IGNORED_ARG, Y) ->
+ calls_fun(fun(Term) -> {X, Term, Y} end).
+
+calls_fun(F) ->
+ F({ok, [bv]}).
+
+%%--------------------------------------------------------------------
+%% Tests whether the translation of switch_val works.
+
+test_switch_val() ->
+ 'A' = sv(a),
+ 'B' = sv(b),
+ 'C' = sv(c),
+ foo = sv(d),
+ ok.
+
+sv(a) -> 'A';
+sv(b) -> 'B';
+sv(c) -> 'C';
+sv(_) -> foo.
+
+%%--------------------------------------------------------------------
+%% Tests correct handling of literals (statically constant terms)
+
+-define(QUADRUPLE, {a,b,c,42}).
+-define(DEEP_LIST, [42,[42,[42]]]).
+
+test_put_literal() ->
+ ?QUADRUPLE = mk_literal_quadruple(),
+ ?DEEP_LIST = mk_literal_deep_list(),
+ ok.
+
+mk_literal_quadruple() ->
+ ?QUADRUPLE.
+
+mk_literal_deep_list() ->
+ ?DEEP_LIST.
+
+%%--------------------------------------------------------------------
+%% Tests whether the translation of set_tuple_element works.
+
+-record(rec, {f1, f2, f3, f4, f5}).
+
+test_set_tuple_element() ->
+ F2 = [a,b,c], F4 = {a,b},
+ State0 = init_rec(F2, F4),
+ State1 = simple_set(State0, 42),
+ #rec{f1 = foo, f2 = F2, f3 = 42, f4 = F4, f5 = 42.0} = odd_set(State1, 21),
+ ok.
+
+init_rec(F2, F4) ->
+ #rec{f1 = bar, f2 = F2, f3 = 10, f4 = F4, f5 = 3.14}.
+
+simple_set(State, Val) -> %% f3 = Val is the one used in set_element;
+ State#rec{f3 = Val, f5 = Val*2}. %% this checks the case of variable
+
+odd_set(State, Val) -> %% f3 = foo is the one used in set_element;
+ State#rec{f1 = foo, f5 = Val*2.0}. %% this checks the case of constant
+
+%%--------------------------------------------------------------------
+%% Tests the handling of unguarded unsafe_element operations that BEAM
+%% can sometimes construct on records (when it has enough context).
+
+test_unguarded_unsafe_element() ->
+ {badrecord, rec} = try unguarded_unsafe_element(42) catch error:E -> E end,
+ ok.
+
+unguarded_unsafe_element(X) ->
+ X#rec{f1 = X#rec.f3}.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_bifs.erl b/lib/hipe/test/basic_SUITE_data/basic_bifs.erl
new file mode 100644
index 0000000000..e7ee2f3678
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_bifs.erl
@@ -0,0 +1,257 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests for handling of BIFs in guards and body calls.
+%%%-------------------------------------------------------------------
+-module(basic_bifs).
+
+-export([test/0]).
+
+-define(BIG, 1398479237498374913984792374983749).
+
+test() ->
+ ok = test_abs(),
+ ok = test_binary_part(),
+ ok = test_element(),
+ ok = test_float(),
+ ok = test_float_to_list(),
+ ok = test_integer_to_list(),
+ ok = test_list_to_float(),
+ ok = test_list_to_integer(),
+ ok = test_round(),
+ ok = test_trunc(),
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_abs() ->
+ t_abs(5.5, 0.0, -100.0, 5, 0, -100, ?BIG).
+
+t_abs(F1, F2, F3, I1, I2, I3, BigNum) ->
+ %% Floats.
+ 5.5 = abs(F1),
+ 0.0 = abs(F2),
+ 100.0 = abs(F3),
+ %% Integers.
+ 5 = abs(I1),
+ 0 = abs(I2),
+ 100 = abs(I3),
+ %% Bignums.
+ BigNum = abs(BigNum),
+ BigNum = abs(-BigNum),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Checks that 2-ary and 3-ary BIFs can be compiled to native code.
+
+test_binary_part() ->
+ Bin = <<1,2,3,4,5,6,7,8,9,10>>,
+ BinPart = bp3(Bin),
+ <<7,8>> = bp2(BinPart),
+ ok.
+
+bp2(Bin) ->
+ binary_part(Bin, {1, 2}).
+
+bp3(Bin) ->
+ binary_part(Bin, byte_size(Bin), -5).
+
+%%--------------------------------------------------------------------
+
+test_element() ->
+ true = elem({a, b}),
+ false = elem({a, c}),
+ other = elem(gazonk),
+ ok.
+
+elem(T) when element(1, T) == a -> element(2, T) == b;
+elem(_) -> other.
+
+%%--------------------------------------------------------------------
+
+test_float() ->
+ t_float(0, 42, -100, 2.5, 0.0, -100.42, ?BIG, -?BIG).
+
+t_float(I1, I2, I3, F1, F2, F3, B1, B2) ->
+ 0.0 = float(I1),
+ 2.5 = float(F1),
+ 0.0 = float(F2),
+ -100.42 = float(F3),
+ 42.0 = float(I2),
+ -100.0 = float(I3),
+ %% Bignums.
+ 1398479237498374913984792374983749.0 = float(B1),
+ -1398479237498374913984792374983749.0 = float(B2),
+ %% Extremly big bignums.
+ Big = list_to_integer(duplicate(2000, $1)),
+ {'EXIT', _} = (catch float(Big)),
+ %% Invalid types and lists.
+ {'EXIT', _} = (catch my_list_to_integer(atom)),
+ {'EXIT', _} = (catch my_list_to_integer(123)),
+ {'EXIT', _} = (catch my_list_to_integer([$1, [$2]])),
+ {'EXIT', _} = (catch my_list_to_integer("1.2")),
+ {'EXIT', _} = (catch my_list_to_integer("a")),
+ {'EXIT', _} = (catch my_list_to_integer("")),
+ ok.
+
+my_list_to_integer(X) ->
+ list_to_integer(X).
+
+%%--------------------------------------------------------------------
+
+test_float_to_list() ->
+ test_ftl("0.0e+0", 0.0),
+ test_ftl("2.5e+1", 25.0),
+ test_ftl("2.5e+0", 2.5),
+ test_ftl("2.5e-1", 0.25),
+ test_ftl("-3.5e+17", -350.0e15),
+ ok.
+
+test_ftl(Expect, Float) ->
+ %% No \n on the next line -- we want the line number from t_float_to_list.
+ Expect = remove_zeros(lists:reverse(float_to_list(Float)), []).
+
+%% Removes any non-significant zeros in a floating point number.
+%% Example: 2.500000e+01 -> 2.5e+1
+
+remove_zeros([$+, $e|Rest], [$0, X|Result]) ->
+ remove_zeros([$+, $e|Rest], [X|Result]);
+remove_zeros([$-, $e|Rest], [$0, X|Result]) ->
+ remove_zeros([$-, $e|Rest], [X|Result]);
+remove_zeros([$0, $.|Rest], [$e|Result]) ->
+ remove_zeros(Rest, [$., $0, $e|Result]);
+remove_zeros([$0|Rest], [$e|Result]) ->
+ remove_zeros(Rest, [$e|Result]);
+remove_zeros([Char|Rest], Result) ->
+ remove_zeros(Rest, [Char|Result]);
+remove_zeros([], Result) ->
+ Result.
+
+%%--------------------------------------------------------------------
+
+test_integer_to_list() ->
+ t_integer_to_list(0, 42, 32768, 268435455, 123456932798748738738).
+
+t_integer_to_list(I1, I2, I3, I4, BIG) ->
+ "0" = integer_to_list(I1),
+ "42" = integer_to_list(I2),
+ "-42" = integer_to_list(-I2),
+ "-42" = integer_to_list(-I2),
+ "32768" = integer_to_list(I3),
+ "268435455" = integer_to_list(I4),
+ "-268435455" = integer_to_list(-I4),
+ "123456932798748738738" = integer_to_list(BIG),
+ BigList = duplicate(2000, $1),
+ Big = list_to_integer(BigList),
+ BigList = integer_to_list(Big),
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_list_to_float() ->
+ ok = t_list_to_float_safe(),
+ ok = t_list_to_float_risky().
+
+t_list_to_float_safe() ->
+ 0.0 = my_list_to_float("0.0"),
+ 0.0 = my_list_to_float("-0.0"),
+ 0.5 = my_list_to_float("0.5"),
+ -0.5 = my_list_to_float("-0.5"),
+ 100.0 = my_list_to_float("1.0e2"),
+ 127.5 = my_list_to_float("127.5"),
+ -199.5 = my_list_to_float("-199.5"),
+ {'EXIT', _} = (catch my_list_to_float("0")),
+ {'EXIT', _} = (catch my_list_to_float("0..0")),
+ {'EXIT', _} = (catch my_list_to_float("0e12")),
+ {'EXIT', _} = (catch my_list_to_float("--0.0")),
+ ok.
+
+my_list_to_float(X) ->
+ list_to_float(X).
+
+%% This might crash the emulator. (Used to crash Erlang 4.4.1 on Unix.)
+
+t_list_to_float_risky() ->
+ Many_Ones = duplicate(25000, $1),
+ ok = case list_to_float("2." ++ Many_Ones) of
+ F when is_float(F), 0.0 < F, F =< 3.14 -> ok
+ end,
+ {'EXIT', _} = (catch list_to_float("2" ++ Many_Ones)),
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_list_to_integer() ->
+ ok = t_list_to_integer_small("0", "00", "-0", "1", "-1", "42", "-12",
+ "32768", "268435455", "-268435455"),
+ ok = t_list_to_integer_bignum("123456932798748738738666"),
+ ok.
+
+t_list_to_integer_small(S1, S2, S3, S4, S5, S6, S7, S8, S9, S10) ->
+ 0 = list_to_integer(S1),
+ 0 = list_to_integer(S2),
+ 0 = list_to_integer(S3),
+ 1 = list_to_integer(S4),
+ -1 = list_to_integer(S5),
+ 42 = list_to_integer(S6),
+ -12 = list_to_integer(S7),
+ 32768 = list_to_integer(S8),
+ 268435455 = list_to_integer(S9),
+ -268435455 = list_to_integer(S10),
+ ok.
+
+t_list_to_integer_bignum(S) ->
+ 123456932798748738738666 = list_to_integer(S),
+ case list_to_integer(duplicate(2000, $1)) of
+ I when is_integer(I), I > 123456932798748738738666 -> ok
+ end.
+
+%%--------------------------------------------------------------------
+
+test_round() ->
+ ok = t_round_small(0.0, 0.4, 0.5, -0.4, -0.5, 255.3, 255.6, -1033.3, -1033.6),
+ ok = t_round_big(4294967296.1, 4294967296.9),
+ ok.
+
+t_round_small(F1, F2, F3, F4, F5, F6, F7, F8, F9) ->
+ 0 = round(F1),
+ 0 = round(F2),
+ 1 = round(F3),
+ 0 = round(F4),
+ -1 = round(F5),
+ 255 = round(F6),
+ 256 = round(F7),
+ -1033 = round(F8),
+ -1034 = round(F9),
+ ok.
+
+t_round_big(B1, B2) ->
+ 4294967296 = round(B1),
+ 4294967297 = round(B2),
+ -4294967296 = round(-B1),
+ -4294967297 = round(-B2),
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_trunc() ->
+ t_trunc(0.0, 5.3333, -10.978987, 4294967305.7).
+
+t_trunc(F1, F2, F3, B) ->
+ 0 = trunc(F1),
+ 5 = trunc(F2),
+ -10 = trunc(F3),
+ %% Bignums.
+ 4294967305 = trunc(B),
+ -4294967305 = trunc(-B),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Auxiliary functions below
+
+duplicate(N, X) when is_integer(N), N >= 0 ->
+ duplicate(N, X, []).
+
+duplicate(0, _, L) -> L;
+duplicate(N, X, L) -> duplicate(N-1, X, [X|L]).
diff --git a/lib/hipe/test/basic_SUITE_data/basic_bignums.erl b/lib/hipe/test/basic_SUITE_data/basic_bignums.erl
new file mode 100644
index 0000000000..e3b523b3f5
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_bignums.erl
@@ -0,0 +1,143 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains code examples that test bignum arithmetic and matching.
+%%%-------------------------------------------------------------------
+-module(basic_bignums).
+
+-export([test/0, test_bsl/0]).
+
+test() ->
+ ok = test_ops(),
+ ok = test_big_fac(),
+ ok = test_int_overfl_32(),
+ ok = test_int_overfl_64(),
+ ok = test_int_overfl_32_guard(),
+ ok = test_int_overfl_64_guard(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Define some constants for the tests of arithmetic operators
+
+-define(X, 68719476736).
+-define(Y, 98765432101234).
+-define(Z, 4722366482869645213696).
+-define(W, 339254531512339254531512).
+
+-define(B1, 4398046511104).
+-define(B5, 1645504557321206042154969182557350504982735865633579863348609024).
+-define(B17, 86182066610968551542636378241108028056376767329454880514019834315878107616003372189510312530372009184902888961739623919010110377987011442493486117202360415845666384627768436296772219009176743399772868636439042064384).
+
+%%--------------------------------------------------------------------
+
+test_ops() ->
+ ok = test_mult(),
+ ok = test_div(),
+ ok = test_round(),
+ ok = test_trunc(),
+ ok = test_bsl(),
+ ok.
+
+test_mult() ->
+ ?Z = mult(?X, ?X),
+ ok.
+
+mult(X, Y) -> X * Y.
+
+test_div() ->
+ 4 = div_f(339254531512, ?X),
+ 0 = div_f(?Y, ?Y+1),
+ 64 = div_f(?B1, ?X),
+ ?X = div_f(?Z, ?X),
+ 1073741824 = div_f(?Z, ?B1),
+ ok.
+
+div_f(X, Y) -> X div Y.
+
+test_round() ->
+ 0 = round_f(?Z, ?W),
+ 1 = round_f(?Y, ?Y),
+ 71 = round_f(?W, ?Z),
+ 1437 = round_f(?Y, ?X),
+ 47813960 = round_f(?Z, ?Y),
+ 4936803183406 = round_f(?W, ?X),
+ ok.
+
+trunc_f(X, Y) -> round(X/Y).
+
+test_trunc() ->
+ 0 = trunc_f(?Z, ?W),
+ 1 = trunc_f(?Y, ?Y),
+ 72 = trunc_f(?W, ?Z),
+ 1437 = trunc_f(?Y, ?X),
+ 47813961 = trunc_f(?Z, ?Y),
+ 4936803183407 = trunc_f(?W, ?X),
+ ok.
+
+round_f(X, Y) -> trunc(X/Y).
+
+test_bsl() ->
+ ?B1 = bsl_f(1, 42),
+ ?B5 = n(5, fun erlang:'bsl'/2, 1, 42), % use the operator
+ ?B17 = n(17, fun bsl_f/2, 1, 42), % use the local function
+ ok.
+
+bsl_f(X, Y) -> X bsl Y.
+
+%% applies a binary function N times
+n(1, F, X, Y) -> F(X, Y);
+n(N, F, X, Y) when N > 1 -> n(N-1, F, F(X, Y), Y).
+
+%%--------------------------------------------------------------------
+
+-define(FAC42, 1405006117752879898543142606244511569936384000000000).
+
+test_big_fac() ->
+ ?FAC42 = fac(42),
+ ok.
+
+fac(0) -> 1;
+fac(N) -> N * fac(N-1).
+
+%%--------------------------------------------------------------------
+%% Tests for correct handling of integer overflow
+
+test_int_overfl_32() ->
+ 16#7FFFFFF = add(16#7FFFFFF, 0),
+ 16#8000000 = add(16#8000000, 0),
+ 16#8000001 = add(16#8000000, 1),
+ case add(16#7FFFFFF, 1) of
+ 16#8000000 -> ok;
+ -16#7FFFFFF -> error
+ end.
+
+test_int_overfl_64() ->
+ 16#7FFFFFFFFFFFFFF = add(16#7FFFFFFFFFFFFFF, 0),
+ 16#800000000000000 = add(16#800000000000000, 0),
+ 16#800000000000001 = add(16#800000000000000, 1),
+ case add(16#7FFFFFFFFFFFFFF, 1) of
+ 16#800000000000000 -> ok;
+ -16#7FFFFFFFFFFFFFF -> error
+ end.
+
+add(X, Y) -> X + Y.
+
+%%--------------------------------------------------------------------
+%% Tests for correct handling of integer overflow in guards
+
+test_int_overfl_32_guard() ->
+ ok = overfl_in_guard(16#7ffffff, 0),
+ ok = overfl_in_guard(16#7ffffff, 16#7ffffff),
+ ok.
+
+test_int_overfl_64_guard() ->
+ ok = overfl_in_guard(16#7ffffffffffffff, 0),
+ ok = overfl_in_guard(16#7ffffffffffffff, 16#7ffffffffffffff),
+ ok.
+
+overfl_in_guard(X, Y) ->
+ case ok of
+ V when X+Y > 12 -> V;
+ _ -> bad
+ end.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_boolean.erl b/lib/hipe/test/basic_SUITE_data/basic_boolean.erl
new file mode 100644
index 0000000000..e4a91ef5af
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_boolean.erl
@@ -0,0 +1,47 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Tests for correct translation of booleans and their primitives.
+%%%-------------------------------------------------------------------
+-module(basic_boolean).
+
+-export([test/0]).
+
+test() ->
+ ok = test_boolean_ops(false, true),
+ ok = test_orelse_redundant(),
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_boolean_ops(F, T) ->
+ true = T and T,
+ false = T and F,
+ false = F and T,
+ false = F and F,
+ true = T or T,
+ true = T or F,
+ true = F or T,
+ false = F or F,
+ true = T andalso T,
+ false = T andalso F,
+ false = F andalso T,
+ false = F andalso F,
+ true = T orelse T,
+ true = T orelse F,
+ true = F orelse T,
+ false = F orelse F,
+ ok.
+
+%%--------------------------------------------------------------------
+%% Redundant test in BEAM code will generate type warning.
+
+test_orelse_redundant() ->
+ true = test_orelse(true, true, true),
+ ok.
+
+test_orelse(A, B, C) ->
+ A andalso B orelse C.
+
+%%--------------------------------------------------------------------
diff --git a/lib/hipe/test/basic_SUITE_data/basic_bugs_beam.erl b/lib/hipe/test/basic_SUITE_data/basic_bugs_beam.erl
new file mode 100644
index 0000000000..964b0f423a
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_bugs_beam.erl
@@ -0,0 +1,138 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains code examples that exhibited bugs in the BEAM compiler.
+%%%-------------------------------------------------------------------
+-module(basic_bugs_beam).
+
+-export([test/0]).
+
+%% the following is needed for the test_weird_message
+-export([loop/1]).
+%% the following are needed for the test_catch_bug
+-behaviour(gen_server).
+-export([start_link/1]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+test() ->
+ ok = test_fp_basic_blocks(),
+ ok = test_weird_message(),
+ ok = test_catch_bug(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Test which shows that BEAM's splitting of basic blocks should take
+%% into account that arithmetic operations implemented as BIFs can
+%% also cause exceptions and thus calls to BIFs should end basic blocks.
+%%
+%% Investigated and fixed in the beginning of April 2004.
+%%--------------------------------------------------------------------
+
+test_fp_basic_blocks() ->
+ ok = t1(),
+ ok = t2().
+
+t1() ->
+ X = (catch bad_arith1(2.0, 1.7)),
+ case X of
+ {'EXIT', {badarith, _}} ->
+ ok;
+ _ ->
+ error
+ end.
+
+bad_arith1(X, Y) when is_float(X) ->
+ X1 = X * 1.7e+308,
+ X2 = X1 + 1.0,
+ Y1 = Y * 2,
+ {X2, Y1}.
+
+%% Similarly, it is not kosher to have anything that can fail inside
+%% the fp block since it will throw the exception before the fp
+%% exception and we will get the same problems.
+
+t2() ->
+ case catch bad_arith2(2.0, []) of
+ {'EXIT', {badarith, _}} ->
+ ok;
+ _ ->
+ error
+ end.
+
+bad_arith2(X, Y) when is_float(X) ->
+ X1 = X * 1.7e+308,
+ Y1 = element(1, Y),
+ {X1 + 1.0, Y1}.
+
+%%--------------------------------------------------------------------
+%% Sending 'test' to this process should return 'ok'. But:
+%%
+%% 1> MOD:test().
+%% Weird: received true
+%% timeout
+%%
+%% Surprisingly, the message has been bound to the value of 'ena'
+%% in the record! The problem was visible in the .S file.
+%%--------------------------------------------------------------------
+
+-record(state, {ena = true}).
+
+test_weird_message() ->
+ P = spawn_link(?MODULE, loop, [#state{}]),
+ P ! {msg, self()},
+ receive
+ What -> What
+ after 42 -> timeout
+ end.
+
+loop(S) ->
+ receive
+ _ when S#state.ena == false ->
+ io:format("Weird: ena is false\n");
+ % loop(S);
+ {msg, Pid} ->
+ Pid ! ok;
+ % loop(S);
+ Other ->
+ io:format("Weird: received ~p\n", [Other])
+ % loop(S)
+ end.
+
+%%--------------------------------------------------------------------
+%% This was posted on the Erlang mailing list as a question:
+%%
+%% Given the module below and the function call
+%% "catch_bug:start_link(foo)."
+%% from the Erlang shell, why does Erlang crash with "Catch not found"?
+%%
+%% The BEAM compiler was generating wrong code for this case;
+%% this was fixed in R9C-0. Native code generation was OK.
+%%--------------------------------------------------------------------
+
+test_catch_bug() ->
+ ignore = start_link(foo),
+ ok.
+
+start_link(Param) ->
+ gen_server:start_link(?MODULE, Param, []).
+
+init(Param) ->
+ process_flag(trap_exit, true),
+ (catch begin
+ dummy(Param),
+ (catch exit(bar))
+ end
+ ),
+ ignore.
+
+dummy(_) -> ok.
+
+%% gen_server callbacks below
+handle_call(_Call, _From, State) -> {noreply, State}.
+handle_cast(_Msg, State) -> {noreply, State}.
+handle_info(_Msg, State) -> {noreply, State}.
+terminate(_Reason, _State) -> ok.
+code_change(_OldVsn, State, _Extra) -> {ok, State}.
+
diff --git a/lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl b/lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl
new file mode 100644
index 0000000000..caa0e71d0b
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl
@@ -0,0 +1,463 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%----------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains code examples that exhibited bugs in the HiPE compiler.
+%%%----------------------------------------------------------------------
+-module(basic_bugs_hipe).
+
+-export([test/0]).
+
+test() ->
+ ok = test_ets_bifs(),
+ ok = test_szar_bug(),
+ ok = test_bit_shift(),
+ ok = test_match_big_list(),
+ ok = test_unsafe_bsl(),
+ ok = test_unsafe_bsr(),
+ ok = test_R12B5_seg_fault(),
+ ok = test_switch_neg_int(),
+ ok = test_icode_range_anal(),
+ ok.
+
+%%-----------------------------------------------------------------------
+%% From: Bjorn Gustavsson
+%%
+%% This code, if HiPE compiled, crashed like this (on SPARC)
+%%
+%% (gdb) where
+%% #0 fullsweep_heap (p=0x2c60dc, new_sz=610, objv=0xffbee8b4, nobj=3)
+%% at beam/ggc.c:1060
+%% #1 0x7ff24 in erts_garbage_collect (p=0x2c60dc, need=2, objv=0x1128fc, ...)
+%% at beam/ggc.c:1648
+%% #2 0xab6fc in hipe_mode_switch (p=0x2c60dc, cmd=704512, reg=0x1128fc)
+%% at hipe/hipe_mode_switch.c:180
+%% #3 0x8e27c in process_main () at beam/beam_emu.c:3314
+%% #4 0x31338 in erl_start (argc=9, argv=0xffbeed5c) at beam/erl_init.c:936
+%% #5 0x2d9f4 in main (argc=9, argv=0xffbeed5c) at sys/unix/erl_main.c:28
+%%
+%% A guess at what could be the problem: From R8, many ets BIFs trap
+%% to other ets BIFs with a *different* arity (i.e. they have more or
+%% less arguments). I have probably forgotten to mention that subtle
+%% change.
+%%-----------------------------------------------------------------------
+
+test_ets_bifs() ->
+ Seed = {1032, 15890, 22716},
+ put(random_seed, Seed),
+ do_random_test().
+
+do_random_test() ->
+ OrdSet = ets:new(xxx, [ordered_set]),
+ Set = ets:new(xxx, []),
+ do_n_times(fun() ->
+ Key = create_random_string(25),
+ Value = create_random_tuple(25),
+ ets:insert(OrdSet, {Key, Value}),
+ ets:insert(Set, {Key, Value})
+ end, 5000),
+ %% io:format("~nData inserted~n"),
+ do_n_times(fun() ->
+ I = random:uniform(25),
+ Key = create_random_string(I) ++ '_',
+ L1 = ets_match_object(OrdSet, {Key, '_'}),
+ L2 = lists:sort(ets_match_object(Set, {Key, '_'})),
+ case L1 == L2 of
+ false ->
+ %% io:format("~p != ~p~n", [L1, L2]),
+ exit({not_eq, L1, L2});
+ true ->
+ ok
+ end
+ end, 2000),
+ %% io:format("~nData matched~n"),
+ ets:match_delete(OrdSet, '_'),
+ ets:match_delete(Set, '_'),
+ ok.
+
+create_random_string(0) ->
+ [];
+create_random_string(OfLength) ->
+ C = case random:uniform(2) of
+ 1 -> (random:uniform($Z - $A + 1) - 1) + $A;
+ _ -> (random:uniform($z - $a + 1) - 1) + $a
+ end,
+ [C | create_random_string(OfLength - 1)].
+
+create_random_tuple(OfLength) ->
+ list_to_tuple([list_to_atom([X]) || X <- create_random_string(OfLength)]).
+
+ets_match_object(Tab,Expr) ->
+ case random:uniform(2) of
+ 1 -> ets:match_object(Tab,Expr);
+ _ -> match_object_chunked(Tab,Expr)
+ end.
+
+match_object_chunked(Tab,Expr) ->
+ match_object_chunked_collect(ets:match_object(Tab, Expr,
+ random:uniform(1999) + 1)).
+
+match_object_chunked_collect('$end_of_table') ->
+ [];
+match_object_chunked_collect({Results, Continuation}) ->
+ Results ++ match_object_chunked_collect(ets:match_object(Continuation)).
+
+do_n_times(_, 0) ->
+ ok;
+do_n_times(Fun, N) ->
+ Fun(),
+ case N rem 1000 of
+ 0 -> ok; %% WAS: io:format(".");
+ _ -> ok
+ end,
+ do_n_times(Fun, N - 1).
+
+%%-----------------------------------------------------------------------
+%% From: Jozsef Berces (PR/ECZ)
+%% Date: Feb 19, 2004
+%%
+%% Program which was added to the testsuite as a result of another bug
+%% report involving tuples as funs. Thanks God, these are no longer
+%% supported, but the following is a good test for testing calling
+%% native code funs from BEAM code (lists:map, lists:filter, ...).
+%%-----------------------------------------------------------------------
+
+test_szar_bug() ->
+ ["A","B","C"] = smartconcat([], "H'A, H'B, H'C"),
+ ok.
+
+smartconcat(B, L) ->
+ LL = tokenize(L, $,),
+ NewlineDel = fun (X) -> killcontrol(X) end,
+ StripFun = fun (X) -> string:strip(X) end,
+ LL2 = lists:map(NewlineDel, lists:map(StripFun, LL)),
+ EmptyDel = fun(X) ->
+ case string:len(X) of
+ 0 -> false;
+ _ -> true
+ end
+ end,
+ LL3 = lists:filter(EmptyDel, LL2),
+ HexFormat = fun(X, Acc) ->
+ case string:str(X, "H'") of
+ 1 ->
+ case checkhex(string:substr(X, 3)) of
+ {ok, Y} ->
+ {Y, Acc};
+ _ ->
+ {X, Acc + 1}
+ end;
+ _ ->
+ {X, Acc + 1}
+ end
+ end,
+ {LL4,_Ret} = lists:mapfoldl(HexFormat, 0, LL3),
+ lists:append(B, lists:sublist(LL4, lists:max([0, 25 - length(B)]))).
+
+checkhex(L) ->
+ checkhex(L, "").
+
+checkhex([H | T], N) when H >= $0, H =< $9 ->
+ checkhex(T, [H | N]);
+checkhex([H | T], N) when H >= $A, H =< $F ->
+ checkhex(T, [H | N]);
+checkhex([H | T], N) when H =< 32 ->
+ checkhex(T, N);
+checkhex([_ | _], _) ->
+ {error, ""};
+checkhex([], N) ->
+ {ok, lists:reverse(N)}.
+
+killcontrol([C | S]) when C < 32 ->
+ killcontrol(S);
+killcontrol([C | S]) ->
+ [C | killcontrol(S)];
+killcontrol([]) ->
+ [].
+
+tokenize(L, C) ->
+ tokenize(L, C, [], []).
+
+tokenize([C | T], C, A, B) ->
+ case A of
+ [] ->
+ tokenize(T, C, [], B);
+ _ ->
+ tokenize(T, C, [], [lists:reverse(A) | B])
+ end;
+tokenize([H | T], C, A, B) ->
+ tokenize(T, C, [H | A], B);
+tokenize(_, _, [], B) ->
+ lists:reverse(B);
+tokenize(_, _, A, B) ->
+ lists:reverse([lists:reverse(A) | B]).
+
+%%-----------------------------------------------------------------------
+%% From: Niclas Pehrsson
+%% Date: Apr 20, 2006
+%%
+%% We found something weird with the bit shifting in HiPE. It seems
+%% that bsr in some cases shifts the bits in the wrong way...
+%%
+%% Fixed about 10 mins afterwards; was a bug in constant propagation.
+%%-----------------------------------------------------------------------
+
+test_bit_shift() ->
+ 1 = plain_shift(), % 1
+ 6 = length_list_plus(), % 6
+ 0 = shift_length_list(), % 0
+ 1 = shift_length_list_plus(), % 1
+ 1 = shift_length_list_plus2(), % 1
+ 24 = shift_length_list_plus_bsl(), % 24
+ 1 = shift_fun(), % 1
+ %% {1, 6, 0, 1, 1, 24, 1} = {A, B, C, D, E, F, G},
+ ok.
+
+plain_shift() ->
+ 6 bsr 2.
+
+length_list() ->
+ length([0,0]).
+
+length_list_plus() ->
+ length([0,0]) + 4.
+
+shift_length_list() ->
+ length([0,0]) bsr 2.
+
+shift_length_list_plus() ->
+ (length([0,0]) + 4) bsr 2.
+
+shift_length_list_plus_bsl() ->
+ (length([0,0]) + 4) bsl 2.
+
+shift_length_list_plus2() ->
+ N = length([0,0]) + 4,
+ N bsr 2.
+
+shift_fun() ->
+ (length_list() + 4) bsr 2.
+
+%%-----------------------------------------------------------------------
+%% From: Igor Goryachev
+%% Date: June 15, 2006
+%%
+%% I have experienced a different behaviour and possibly a weird result
+%% while playing with matching a big list on x86 and x86_64 machines.
+%%-----------------------------------------------------------------------
+
+-define(BIG_LIST,
+ ["uid", "nickname", "n_family", "n_given", "email_pref",
+ "tel_home_number", "tel_cellular_number", "adr_home_country",
+ "adr_home_locality", "adr_home_region", "url", "gender", "bday",
+ "constitution", "height", "weight", "hair", "routine", "smoke",
+ "maritalstatus", "children", "independence", "school_number",
+ "school_locality", "school_title", "school_period", "org_orgname",
+ "title", "adr_work_locality", "photo_type", "photo_binval"]).
+
+test_match_big_list() ->
+ case create_tuple_with_big_const_list() of
+ {selected, ?BIG_LIST, _} -> ok;
+ _ -> weird
+ end.
+
+create_tuple_with_big_const_list() ->
+ {selected, ?BIG_LIST, [{"test"}]}.
+
+%%-----------------------------------------------------------------------
+%% In October 2006 the HiPE compiler acquired more type-driven
+%% optimisations of arithmetic operations. One of these, the
+%% transformation of bsl to a pure fixnum bsl fixnum -> fixnum version
+%% (unsafe_bsl), was incorrectly performed even when the result
+%% wouldn't be a fixnum. The error occurred for all backends, but the
+%% only place known to break was hipe_arm:imm_to_am1/2. Some
+%% immediates got broken on ARM, causing segmentation faults in
+%% compiler_tests when HiPE recompiled itself.
+%%-----------------------------------------------------------------------
+
+test_unsafe_bsl() ->
+ ok = bsl_check(bsl_test_cases()).
+
+bsl_test_cases() ->
+ [{16#FF, {16#FF, 0}},
+ {16#F000000F, {16#FF, 2}}].
+
+bsl_check([]) -> ok;
+bsl_check([{X, Y}|Rest]) ->
+ case imm_to_am1(X) of
+ Y -> bsl_check(Rest);
+ _ -> 'hipe_broke_bsl'
+ end.
+
+imm_to_am1(Imm) ->
+ imm_to_am1(Imm band 16#FFFFFFFF, 16).
+imm_to_am1(Imm, RotCnt) ->
+ if Imm >= 0, Imm =< 255 -> {Imm, RotCnt band 15};
+ true ->
+ NewRotCnt = RotCnt - 1,
+ if NewRotCnt =:= 0 -> []; % full circle, no joy
+ true ->
+ NewImm = (Imm bsr 2) bor ((Imm band 3) bsl 30),
+ imm_to_am1(NewImm, NewRotCnt)
+ end
+ end.
+
+%%-----------------------------------------------------------------------
+%% Another transformation, namely that of bsr to a pure fixnum bsr
+%% fixnum -> fixnum version (unsafe_bsr), failed to check for shifts
+%% larger than the number of bits in fixnums. Such shifts should
+%% return zero, but instead they became plain machine-level shift
+%% instructions. Machines often only consider the low-order bits of
+%% the shift count, so machine-level shifts larger than the word size
+%% do not match the Erlang semantics.
+%%-----------------------------------------------------------------------
+
+test_unsafe_bsr() ->
+ ok = bsr_check(bsr_test_cases()).
+
+bsr_test_cases() ->
+ [{16#FF, 4, 16#0F},
+ {16#FF, 64, 0}].
+
+bsr_check([]) -> ok;
+bsr_check([{X, Y, Z}|Rest]) ->
+ case do_bsr(X, Y) of
+ Z -> bsr_check(Rest);
+ _ -> 'hipe_broke_bsr'
+ end.
+
+do_bsr(X, Y) ->
+ (X band 16#FFFF) bsr (Y band 16#FFFF).
+
+%%-----------------------------------------------------------------------
+%% From: Sergey S, mid January 2009.
+%%
+%% While I was playing with +native option, I run into a bug in HiPE
+%% which leads to segmentation fault using +native and Erlang R12B-5.
+%%
+%% Eshell V5.6.5
+%% 1> crash:test().
+%% # Some message to be printed here each loop iteration
+%% Segmentation fault
+%%
+%% Diagnosed and fixed by Mikael Pettersson (22 Jan 2009):
+%%
+%% I've analysed the recently posted HiPE bug report on erlang-bugs
+%% <http://www.erlang.org/pipermail/erlang-bugs/2009-January/001162.html>.
+%% The segfault is caused by memory corruption, which in turn is caused
+%% by RTL removing an update of the HP (heap pointer) register due to
+%% what looks like broken liveness information.
+%%-----------------------------------------------------------------------
+
+test_R12B5_seg_fault() ->
+ _ = spawn(fun() -> init() end),
+ ok.
+
+init() ->
+ repeat(5, fun() -> void end),
+ receive after infinity -> ok end.
+
+repeat(0, _) ->
+ ok;
+repeat(N, Fun) ->
+ %% io:format("# Some message to be printed here each loop iteration\n"),
+ Fun(),
+ repeat(N - 1, Fun).
+
+%%-----------------------------------------------------------------------
+%% From: Jon Meredith
+%% Date: July 9, 2009
+%%
+%% Binary search key tables are sorted by the loader based on the
+%% runtime representations of the keys as unsigned words. However,
+%% the code generated for the binary search used signed comparisons.
+%% That worked for atoms and non-negative fixnums, but not for
+%% negative fixnums. Fixed by Mikael Pettersson July 10, 2009.
+%%-----------------------------------------------------------------------
+
+test_switch_neg_int() ->
+ ok = f(-80, 8).
+
+f(10, -1) -> ok;
+f(X, Y) ->
+ Y = g(X),
+ f(X + 10, Y - 1).
+
+g(X) -> % g(0) should be 0 but became -1
+ case X of
+ 0 -> 0;
+ -10 -> 1;
+ -20 -> 2;
+ -30 -> 3;
+ -40 -> 4;
+ -50 -> 5;
+ -60 -> 6;
+ -70 -> 7;
+ -80 -> 8;
+ _ -> -1
+ end.
+
+%%-----------------------------------------------------------------------
+%% From: Paul Guyot
+%% Date: Jan 31, 2011
+%%
+%% There is a bug in HiPE compilation with the comparison of floats
+%% with integers. This bug happens in functions f/1 and g/2 below.
+%% BEAM will evaluate f_eq(42) and f_eq(42.0) to true, while HiPE
+%% will evaluate them to false.
+%%
+%% The culprit was the Icode range analysis which was buggy. (On the
+%% other hand, HiPE properly evaluated these calls to true if passed
+%% the option 'no_icode_range'.) Fixed by Kostis Sagonas.
+%% --------------------------------------------------------------------
+
+test_icode_range_anal() ->
+ true = f_eq(42),
+ true = f_eq(42.0),
+ false = f_ne(42),
+ false = f_ne(42.0),
+ false = f_eq_ex(42),
+ false = f_eq_ex(42.0),
+ true = f_ne_ex(42),
+ true = f_ne_ex(42.0),
+ false = f_gt(42),
+ false = f_gt(42.0),
+ true = f_le(42),
+ true = f_le(42.0),
+ zero_test = g(0, test),
+ zero_test = g(0.0, test),
+ non_zero_test = g(42, test),
+ other = g(42, other),
+ ok.
+
+f_eq(X) ->
+ Y = X / 2,
+ Y == 21.
+
+f_ne(X) ->
+ Y = X / 2,
+ Y /= 21.
+
+f_eq_ex(X) ->
+ Y = X / 2,
+ Y =:= 21.
+
+f_ne_ex(X) ->
+ Y = X / 2,
+ Y =/= 21.
+
+f_gt(X) ->
+ Y = X / 2,
+ Y > 21.
+
+f_le(X) ->
+ Y = X / 2,
+ Y =< 21.
+
+g(X, Z) ->
+ Y = X / 2,
+ case Z of
+ test when Y == 0 -> zero_test;
+ test -> non_zero_test;
+ other -> other
+ end.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_comparisons.erl b/lib/hipe/test/basic_SUITE_data/basic_comparisons.erl
new file mode 100644
index 0000000000..8dab2cab1f
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_comparisons.erl
@@ -0,0 +1,157 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests for correct execution of comparison operators.
+%%%-------------------------------------------------------------------
+-module(basic_comparisons).
+
+-export([test/0]).
+
+test() ->
+ Ns = [0, 0.0, 42, 42.0, gazonk],
+ T1F4 = [true, false, false, false, false],
+ T2F3 = [true, true, false, false, false],
+ F1T4 = [false, true, true, true, true],
+ F2T3 = [false, false, true, true, true],
+ %% tests for calls
+ T1F4 = [eq_exact_call(0, N) || N <- Ns],
+ F1T4 = [ne_exact_call(0, N) || N <- Ns],
+ T2F3 = [eq_call(0, N) || N <- Ns],
+ F2T3 = [ne_call(0, N) || N <- Ns],
+ %% tests for guards
+ T1F4 = [eq_exact_guard(0, N) || N <- Ns],
+ F1T4 = [ne_exact_guard(0, N) || N <- Ns],
+ T2F3 = [eq_guard(0, N) || N <- Ns],
+ F2T3 = [ne_guard(0, N) || N <- Ns],
+ %% some more tests
+ ok = test_against_zero(),
+ ok = test_against_other_terms(),
+ ok = test_sofs_func(),
+ ok.
+
+test_against_zero() ->
+ Xs = [0, 1, 0.0],
+ [true, false, false] = [is_zero_int(X) || X <- Xs],
+ [true, false, true] = [is_zero_num(X) || X <- Xs],
+ [false, true, true] = [is_nonzero_int(X) || X <- Xs],
+ [false, true, false] = [is_nonzero_num(X) || X <- Xs],
+ ok.
+
+test_against_other_terms() ->
+ TTT = {true, true, true},
+ FFF = {false, false, false},
+ TTT = {is_foo_exact(foo), is_foo_term1(foo), is_foo_term2(foo)},
+ FFF = {is_foo_exact(bar), is_foo_term1(bar), is_foo_term2(bar)},
+ FFF = {is_nonfoo_exact(foo), is_nonfoo_term1(foo), is_nonfoo_term2(foo)},
+ TTT = {is_nonfoo_exact(bar), is_nonfoo_term1(bar), is_nonfoo_term2(bar)},
+ Tup = {a, {42}, [c]},
+ TTT = {is_tuple_skel(Tup), is_tuple_exact(Tup), is_tuple_term(Tup)},
+ BNi = <<42>>,
+ TTT = {is_bin_exact(BNi), is_bin_term1(BNi), is_bin_term2(BNi)},
+ BNf = <<42/float>>,
+ FFF = {is_bin_exact(BNf), is_bin_term1(BNf), is_bin_term2(BNf)},
+ ok.
+
+test_sofs_func() ->
+ L = [0, 0.0],
+ ok = sofs_func(L, L, L).
+
+%%--------------------------------------------------------------------
+%% Test for comparison operators used in body calls
+
+eq_exact_call(X, Y) -> X =:= Y.
+
+ne_exact_call(X, Y) -> X =/= Y.
+
+eq_call(X, Y) -> X == Y.
+
+ne_call(X, Y) -> X /= Y.
+
+%%--------------------------------------------------------------------
+%% Tests for comparison operators used as guards
+
+eq_exact_guard(X, Y) when X =:= Y -> true;
+eq_exact_guard(_, _) -> false.
+
+ne_exact_guard(X, Y) when X =/= Y -> true;
+ne_exact_guard(_, _) -> false.
+
+eq_guard(X, Y) when X == Y -> true;
+eq_guard(_, _) -> false.
+
+ne_guard(X, Y) when X /= Y -> true;
+ne_guard(_, _) -> false.
+
+%%--------------------------------------------------------------------
+
+is_zero_int(N) when N =:= 0 -> true;
+is_zero_int(_) -> false.
+
+is_nonzero_int(N) when N =/= 0 -> true;
+is_nonzero_int(_) -> false.
+
+is_zero_num(N) when N == 0 -> true;
+is_zero_num(_) -> false.
+
+is_nonzero_num(N) when N /= 0 -> true;
+is_nonzero_num(_) -> false.
+
+%%--------------------------------------------------------------------
+%% There should not really be any difference in the generated code
+%% for the following three functions.
+
+is_foo_exact(A) when A =:= foo -> true;
+is_foo_exact(_) -> false.
+
+is_foo_term1(A) when A == foo -> true;
+is_foo_term1(_) -> false.
+
+is_foo_term2(A) when foo == A -> true;
+is_foo_term2(_) -> false.
+
+%%--------------------------------------------------------------------
+%% Same for these cases
+
+is_nonfoo_exact(A) when A =/= foo -> true;
+is_nonfoo_exact(_) -> false.
+
+is_nonfoo_term1(A) when A /= foo -> true;
+is_nonfoo_term1(_) -> false.
+
+is_nonfoo_term2(A) when foo /= A -> true;
+is_nonfoo_term2(_) -> false.
+
+%%--------------------------------------------------------------------
+
+is_tuple_skel({A,{B},[C]}) when is_atom(A), is_integer(B), is_atom(C) -> true;
+is_tuple_skel(T) when is_tuple(T) -> false.
+
+is_tuple_exact(T) when T =:= {a,{42},[c]} -> true;
+is_tuple_exact(T) when is_tuple(T) -> false.
+
+is_tuple_term(T) when T == {a,{42.0},[c]} -> true;
+is_tuple_term(T) when is_tuple(T) -> false.
+
+%%--------------------------------------------------------------------
+%% But for binaries the treatment has to be different, due to the need
+%% for construction of the binary in the guard.
+
+is_bin_exact(B) when B =:= <<42>> -> true;
+is_bin_exact(_) -> false.
+
+is_bin_term1(B) when B == <<42>> -> true;
+is_bin_term1(_) -> false.
+
+is_bin_term2(B) when <<42>> == B -> true;
+is_bin_term2(_) -> false.
+
+%%--------------------------------------------------------------------
+%% a test from sofs.erl which failed at some point
+
+sofs_func([X | Ts], X0, L) when X /= X0 ->
+ sofs_func(Ts, X, L);
+sofs_func([X | _Ts], X0, _L) when X == X0 ->
+ ok;
+sofs_func([], _X0, L) ->
+ L.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_exceptions.erl b/lib/hipe/test/basic_SUITE_data/basic_exceptions.erl
new file mode 100644
index 0000000000..229a0516dc
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_exceptions.erl
@@ -0,0 +1,465 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests that raise exceptions and catch them.
+%%%-------------------------------------------------------------------
+-module(basic_exceptions).
+
+-export([test/0, test_catches/0]).
+
+%% functions used as arguments to spawn/3
+-export([bad_guy/2]).
+
+test() ->
+ ok = test_catch_exit(42),
+ ok = test_catch_throw(42),
+ ok = test_catch_element(),
+ ok = test_catch_crash(),
+ ok = test_catch_empty(),
+ ok = test_catch_merge(),
+ ok = test_catches_merged(),
+ ok = test_pending_errors(),
+ ok = test_bad_fun_call(),
+ ok = test_guard_bif(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Written in 2001 by Erik Johansson.
+
+test_catches() ->
+ ExitBar = {'EXIT', bar},
+ L1 = [ExitBar, ok, ExitBar, {ok, ExitBar}],
+ L1 = [t1(), t2(), t3(), t4()],
+ badarith = (catch element(1, element(2, t5(a, b)))),
+ L2 = [42, ExitBar, ExitBar, {no_exception, ok}],
+ L2 = [t5(21, 21), t6(), t7(), t8()],
+ ok.
+
+t1() ->
+ catch foo().
+
+t2() ->
+ V = (catch ok()),
+ s(),
+ V.
+
+t3() ->
+ V = (catch foo()),
+ V.
+
+t4() ->
+ V1 = ok(),
+ V2 = (catch foo()),
+ {V1, V2}.
+
+t5(A, B) ->
+ catch A + B.
+
+t6() ->
+ catch {no_exception, ok(), foo()}.
+
+t7() ->
+ catch {no_exception, foo(), ok()}.
+
+t8() ->
+ catch {no_exception, ok()}.
+
+foo() ->
+ s(),
+ exit(bar).
+
+ok() -> s(), ok.
+
+s() -> nada.
+
+%%--------------------------------------------------------------------
+
+test_catch_exit(N) ->
+ {'EXIT', N} = (catch exit(N)),
+ {'EXIT', 42} = (catch exit(42)),
+ 42 = try exit(N) catch exit:R1 -> R1 end,
+ 42 = try exit(42) catch exit:R2 -> R2 end,
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_catch_throw(N) ->
+ N = (catch throw(N)),
+ 42 = (catch throw(42)),
+ 42 = try throw(N) catch throw:R1 -> R1 end,
+ 42 = try throw(42) catch throw:R2 -> R2 end,
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_catch_element() ->
+ 'EXIT' = test_catch_element([]),
+ 'EXIT' = test_catch_element(42),
+ ok.
+
+test_catch_element(N) ->
+ element(1, catch element(N, {1,2,3,4,5,6,7,8,9,10,11})).
+
+%%--------------------------------------------------------------------
+
+-define(try_match(E),
+ catch ?MODULE:non_existing(),
+ {'EXIT', {{badmatch, nomatch}, _}} = (catch E = no_match())).
+
+test_catch_crash() ->
+ ?try_match(a),
+ ?try_match(42),
+ ?try_match({a, b, c}),
+ ?try_match([]),
+ ?try_match(1.0),
+ ok.
+
+no_match() -> nomatch.
+
+%% small_test() ->
+%% catch ?MODULE:non_existing(),
+%% io:format("Before\n",[]),
+%% hipe_bifs:show_nstack(self()),
+%% io:format("After\n",[]),
+%% garbage_collect().
+
+%%--------------------------------------------------------------------
+%% Tests whether the HiPE compiler optimizes catches in a way that
+%% does not result in an infinite loop.
+%%--------------------------------------------------------------------
+
+test_catch_empty() ->
+ badmatch().
+
+badmatch() ->
+ Big = ret_big(),
+ Float = ret_float(),
+ catch a = Big,
+ catch b = Float,
+ ok = case Big of Big -> ok end,
+ ok = case Float of Float -> ok end,
+ ok.
+
+ret_big() ->
+ 329847987298478924982978248748729829487298292982972978239874.
+
+ret_float() ->
+ 3.1415927.
+
+%%--------------------------------------------------------------------
+%% Test that shows how BEAM can merge catch-end blocks that belong to
+%% different catch-start instructions. Written by Richard Carlsson.
+%%--------------------------------------------------------------------
+
+test_catch_merge() ->
+ merge(get(whatever)).
+
+merge(foo=X) ->
+ catch f(X),
+ catch g(X);
+merge(X) ->
+ catch f(X),
+ catch g(X).
+
+f(_) -> ok.
+
+g(_) -> ok.
+
+%%--------------------------------------------------------------------
+%% Written by Tobias Lindahl.
+
+test_catches_merged() ->
+ {'EXIT', _} = merged_catches(foo),
+ {'EXIT', {badarith, _}} = merged_catches(bar),
+ {'EXIT', _} = merged_catches(baz),
+ ok.
+
+merged_catches(X) ->
+ case X of
+ foo -> catch fail1(0);
+ bar -> catch {catch(1 = X), fail2(0)};
+ baz -> catch fail3(0)
+ end.
+
+fail1(X) -> 1/X.
+
+fail2(X) -> 1/X.
+
+fail3(X) -> 1/X.
+
+%%--------------------------------------------------------------------
+%% Taken from exception_SUITE.erl
+%%--------------------------------------------------------------------
+
+test_pending_errors() ->
+ error_logger:tty(false), % disable printouts of error reports
+ pending_errors().
+
+%% Test various exceptions, in the presence of a previous error
+%% suppressed in a guard.
+pending_errors() ->
+ pending(e_badmatch, {badmatch, b}),
+ pending(x, function_clause),
+ pending(e_case, {case_clause, xxx}),
+ pending(e_if, if_clause),
+ %% pending(e_badarith, badarith),
+ %% pending(e_undef, undef),
+ pending(e_timeoutval, timeout_value),
+ %% pending(e_badarg, badarg),
+ %% pending(e_badarg_spawn, badarg),
+ ok.
+
+bad_guy(pe_badarith, Other) when Other+1 =:= 0 -> % badarith (suppressed)
+ ok;
+bad_guy(pe_badarg, Other) when length(Other) > 0 -> % badarg (suppressed)
+ ok;
+bad_guy(_, e_case) ->
+ case xxx() of
+ ok -> ok
+ end; % case_clause
+bad_guy(_, e_if) ->
+ B = b(),
+ if
+ a == B -> ok
+ end; % if_clause
+%% bad_guy(_, e_badarith) ->
+%% 1+b; % badarith
+bad_guy(_, e_undef) ->
+ non_existing_module:foo(); % undef
+bad_guy(_, e_timeoutval) ->
+ receive
+ after gazonk -> ok % timeout_value
+ end;
+bad_guy(_, e_badarg) ->
+ node(xxx); % badarg
+bad_guy(_, e_badarg_spawn) ->
+ spawn({}, {}, {}); % badarg
+bad_guy(_, e_badmatch) ->
+ a = b(). % badmatch
+
+xxx() -> xxx.
+
+b() -> b.
+
+pending(Arg, Expected) ->
+ pending(pe_badarith, Arg, Expected),
+ pending(pe_badarg, Arg, Expected).
+
+pending(First, Second, Expected) ->
+ pending_catched(First, Second, Expected),
+ pending_exit_message([First, Second], Expected).
+
+pending_catched(First, Second, Expected) ->
+ %% ok = io:format("Catching bad_guy(~p, ~p)\n", [First, Second]),
+ case catch bad_guy(First, Second) of
+ {'EXIT', Reason} ->
+ pending(Reason, bad_guy, [First, Second], Expected);
+ Other ->
+ exit({not_exit, Other})
+ end.
+
+pending_exit_message(Args, Expected) ->
+ %% ok = io:format("Trapping exits from spawn_link(~p, ~p, ~p)\n",
+ %% [?MODULE, bad_guy, Args]),
+ process_flag(trap_exit, true),
+ Pid = spawn_link(?MODULE, bad_guy, Args),
+ receive
+ {'EXIT', Pid, Reason} ->
+ pending(Reason, bad_guy, Args, Expected);
+ Other ->
+ exit({unexpected_message, Other})
+ after 10000 ->
+ exit(timeout)
+ end,
+ process_flag(trap_exit, false).
+
+%% pending({badarg, [{erlang,Bif,BifArgs},{?MODULE,Func,Arity}|_]},
+%% Func, Args, _Code)
+%% when atom(Bif), list(BifArgs), length(Args) =:= Arity ->
+%% ok;
+pending({badarg,Trace}, _, _, _) when is_list(Trace) ->
+ ok;
+%% pending({undef,[{non_existing_module,foo,[]}|_]}, _, _, _) ->
+%% ok;
+pending({undef,Trace}, _, _, _) when is_list(Trace) ->
+ ok;
+%% pending({function_clause,[{?MODULE,Func,Args}|_]}, Func, Args, _Code) ->
+%% ok;
+pending({function_clause,Trace}, _, _, _) when is_list(Trace) ->
+ ok;
+%% pending({Code,[{?MODULE,Func,Arity}|_]}, Func, Args, Code)
+%% when length(Args) =:= Arity ->
+%% ok;
+pending({Code,Trace}, _, _, Code) when is_list(Trace) ->
+ ok;
+pending(Reason, _Function, _Args, _Code) ->
+ exit({bad_exit_reason, Reason}).
+
+%%--------------------------------------------------------------------
+%% Taken from fun_SUITE.erl
+%%
+%% Checks correct exception throwing when calling a bad fun.
+%%--------------------------------------------------------------------
+
+test_bad_fun_call() ->
+ ok = bad_call_fc(42),
+ ok = bad_call_fc(xx),
+ ok = bad_call_fc({}),
+ ok = bad_call_fc({1}),
+ ok = bad_call_fc({1,2,3}),
+ ok = bad_call_fc({1,2,3}),
+ ok = bad_call_fc({1,2,3,4}),
+ ok = bad_call_fc({1,2,3,4,5,6}),
+ ok = bad_call_fc({1,2,3,4,5}),
+ ok = bad_call_fc({1,2}),
+ ok.
+
+bad_call_fc(Fun) ->
+ Args = [some, stupid, args],
+ Res = (catch Fun(Fun(Args))),
+ case Res of
+ {'EXIT', {{badfun, Fun} ,_Where}} ->
+ ok; %% = io:format("~p(~p) -> ~p\n", [Fun, Args, Res]);
+ Other ->
+ io:format("~p(~p) -> ~p\n", [Fun, Args, Res]),
+ exit({bad_result, Other})
+ end.
+
+%%--------------------------------------------------------------------
+%% Taken from guard_SUITE.erl
+%%
+%% Tests correct handling of exceptions by calling guard BIFs with
+%% nasty (but legal arguments).
+%%--------------------------------------------------------------------
+
+test_guard_bif() ->
+ Big = -237849247829874297658726487367328971246284736473821617265433,
+ Float = 387924.874,
+
+ %% Succeding use of guard bifs.
+
+ try_gbif('abs/1', Big, -Big),
+ try_gbif('float/1', Big, float(Big)),
+ try_gbif('trunc/1', Float, 387924.0),
+ try_gbif('round/1', Float, 387925.0),
+ try_gbif('length/1', [], 0),
+
+ try_gbif('length/1', [a], 1),
+ try_gbif('length/1', [a, b], 2),
+ try_gbif('length/1', lists:seq(0, 31), 32),
+
+ try_gbif('hd/1', [a], a),
+ try_gbif('hd/1', [a, b], a),
+
+ try_gbif('tl/1', [a], []),
+ try_gbif('tl/1', [a, b], [b]),
+ try_gbif('tl/1', [a, b, c], [b, c]),
+
+ try_gbif('size/1', {}, 0),
+ try_gbif('size/1', {a}, 1),
+ try_gbif('size/1', {a, b}, 2),
+ try_gbif('size/1', {a, b, c}, 3),
+ try_gbif('size/1', list_to_binary([]), 0),
+ try_gbif('size/1', list_to_binary([1]), 1),
+ try_gbif('size/1', list_to_binary([1, 2]), 2),
+ try_gbif('size/1', list_to_binary([1, 2, 3]), 3),
+
+ try_gbif('element/2', {x}, {1, x}),
+ try_gbif('element/2', {x, y}, {1, x}),
+ try_gbif('element/2', {x, y}, {2, y}),
+
+ try_gbif('self/0', 0, self()),
+ try_gbif('node/0', 0, node()),
+ try_gbif('node/1', self(), node()),
+
+ %% Failing use of guard bifs.
+
+ try_fail_gbif('abs/1', Big, 1),
+ try_fail_gbif('abs/1', [], 1),
+
+ try_fail_gbif('float/1', Big, 42),
+ try_fail_gbif('float/1', [], 42),
+
+ try_fail_gbif('trunc/1', Float, 0.0),
+ try_fail_gbif('trunc/1', [], 0.0),
+
+ try_fail_gbif('round/1', Float, 1.0),
+ try_fail_gbif('round/1', [], a),
+
+ try_fail_gbif('length/1', [], 1),
+ try_fail_gbif('length/1', [a], 0),
+ try_fail_gbif('length/1', a, 0),
+ try_fail_gbif('length/1', {a}, 0),
+
+ try_fail_gbif('hd/1', [], 0),
+ try_fail_gbif('hd/1', [a], x),
+ try_fail_gbif('hd/1', x, x),
+
+ try_fail_gbif('tl/1', [], 0),
+ try_fail_gbif('tl/1', [a], x),
+ try_fail_gbif('tl/1', x, x),
+
+ try_fail_gbif('size/1', {}, 1),
+ try_fail_gbif('size/1', [], 0),
+ try_fail_gbif('size/1', [a], 1),
+ try_fail_gbif('size/1', fun() -> 1 end, 0),
+ try_fail_gbif('size/1', fun() -> 1 end, 1),
+
+ try_fail_gbif('element/2', {}, {1, x}),
+ try_fail_gbif('element/2', {x}, {1, y}),
+ try_fail_gbif('element/2', [], {1, z}),
+
+ try_fail_gbif('self/0', 0, list_to_pid("<0.0.0>")),
+ try_fail_gbif('node/0', 0, xxxx),
+ try_fail_gbif('node/1', self(), xxx),
+ try_fail_gbif('node/1', yyy, xxx),
+ ok.
+
+try_gbif(Id, X, Y) ->
+ case guard_bif(Id, X, Y) of
+ {Id, X, Y} ->
+ %% io:format("guard_bif(~p, ~p, ~p) -- ok\n", [Id, X, Y]);
+ ok;
+ Other ->
+ ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n",
+ [Id, X, Y, Other]),
+ exit({bad_result,try_gbif})
+ end.
+
+try_fail_gbif(Id, X, Y) ->
+ case catch guard_bif(Id, X, Y) of
+ %% {'EXIT', {function_clause,[{?MODULE,guard_bif,[Id,X,Y]}|_]}} ->
+ {'EXIT', {function_clause,_}} -> % in HiPE, a trace is not generated
+ %% io:format("guard_bif(~p, ~p, ~p) -- ok\n", [Id,X,Y]);
+ ok;
+ Other ->
+ ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n",
+ [Id, X, Y, Other]),
+ exit({bad_result,try_fail_gbif})
+ end.
+
+guard_bif('abs/1', X, Y) when abs(X) == Y ->
+ {'abs/1', X, Y};
+guard_bif('float/1', X, Y) when float(X) == Y ->
+ {'float/1', X, Y};
+guard_bif('trunc/1', X, Y) when trunc(X) == Y ->
+ {'trunc/1', X, Y};
+guard_bif('round/1', X, Y) when round(X) == Y ->
+ {'round/1', X, Y};
+guard_bif('length/1', X, Y) when length(X) == Y ->
+ {'length/1', X, Y};
+guard_bif('hd/1', X, Y) when hd(X) == Y ->
+ {'hd/1', X, Y};
+guard_bif('tl/1', X, Y) when tl(X) == Y ->
+ {'tl/1', X, Y};
+guard_bif('size/1', X, Y) when size(X) == Y ->
+ {'size/1', X, Y};
+guard_bif('element/2', X, {Pos, Expected}) when element(Pos, X) == Expected ->
+ {'element/2', X, {Pos, Expected}};
+guard_bif('self/0', X, Y) when self() == Y ->
+ {'self/0', X, Y};
+guard_bif('node/0', X, Y) when node() == Y ->
+ {'node/0', X, Y};
+guard_bif('node/1', X, Y) when node(X) == Y ->
+ {'node/1', X, Y}.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_floats.erl b/lib/hipe/test/basic_SUITE_data/basic_floats.erl
new file mode 100644
index 0000000000..ce28f6e156
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_floats.erl
@@ -0,0 +1,250 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests that manipulate floating point numbers.
+%%%-------------------------------------------------------------------
+-module(basic_floats).
+
+-export([test/0]).
+-export([test_fmt_double_fpe_leak/0]). % suppress the unused warning
+
+test() ->
+ ok = test_arith_ops(),
+ ok = test_fp_ebb(),
+ ok = test_fp_phi(),
+ ok = test_big_bad_float(),
+ ok = test_catch_bad_fp_arith(),
+ ok = test_catch_fp_conv(),
+ ok = test_fp_with_fp_exceptions(),
+ %% ok = test_fmt_double_fpe_leak(), % this requires printing
+ ok = test_icode_type_crash(),
+ ok = test_icode_type_crash_2(),
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_arith_ops() ->
+ E = 2.5617,
+ 5.703200000000001 = add(E),
+ 0.5798000000000001 = sub(E),
+ 8.047580550000001 = mult(E),
+ -6.023e23 = negate(6.023e23),
+ ok.
+
+add(X) ->
+ 3.1415 + X.
+
+sub(X) ->
+ 3.1415 - X.
+
+mult(X) ->
+ 3.1415 * X.
+
+%% tests the translation of the fnegate BEAM instruction.
+negate(X) ->
+ - (X + 0.0).
+
+%%--------------------------------------------------------------------
+%% Test the construction of overlapping extended basic blocks where
+%% BEAM has constructed one and hipe_icode_fp constructs the other.
+%%--------------------------------------------------------------------
+
+test_fp_ebb() ->
+ 1.0 = foo(2 * math:pi()),
+ 1.0 = bar(2 * math:pi()),
+ ok.
+
+foo(X) ->
+ X / (2 * math:pi()).
+
+bar(X) ->
+ F = float_two(),
+ case F < 3.0 of
+ true -> (X * F) / ((2 * F) * math:pi());
+ false -> weird
+ end.
+
+float_two() ->
+ 2.0.
+
+%%--------------------------------------------------------------------
+
+test_fp_phi() ->
+ 10 = fp_phi(10, 100),
+ undefined = fp_phi(1.1e302, 0.000000001),
+ ok.
+
+fp_phi(A, B) ->
+ case catch A / B of
+ {'EXIT', _Reason} -> undefined;
+ _ -> round(100 * (A / B))
+ end.
+
+%%--------------------------------------------------------------------
+
+-define(BS, "93904329458954829589425849258998492384932849328493284932849328493284932389248329432932483294832949245827588578423578435783475834758375837580745807304258924584295924588459834958349589348589345934859384958349583945893458934859438593485995348594385943859438593458934589345938594385934859483958348934589435894859485943859438594594385938459438595034950439504395043950495043593485943758.0").
+
+test_big_bad_float() ->
+ ok = try f2l(?BS) catch error:badarg -> ok end,
+ ok = case catch f2l(?BS) of {'EXIT', {badarg, _}} -> ok end,
+ ok.
+
+f2l(F) ->
+ float_to_list(list_to_float(F)).
+
+%%--------------------------------------------------------------------
+%% Tests catching of floating point bad arithmetic.
+
+test_catch_bad_fp_arith() ->
+ 5.7 = f(2.56),
+ {'EXIT', {badarith, _}} = bad_arith(9.9),
+ ok.
+
+f(F) when is_float(F) -> F + 3.14.
+
+bad_arith(F) when is_float(F) ->
+ catch F * 1.70000e+308.
+
+%%--------------------------------------------------------------------
+%% Tests proper catching of exceptions due to illegal convertion of
+%% bignums to floating point numbers.
+
+test_catch_fp_conv() ->
+ F = 1.7e308, %% F is a number very close to a maximum float.
+ ok = big_arith(F),
+ ok = big_const_float(F),
+ ok.
+
+big_arith(F) ->
+ I = trunc(F),
+ {'EXIT', {badarith, _}} = big_int_arith(I),
+ ok.
+
+big_int_arith(I) when is_integer(I) ->
+ catch(3.0 + 2*I).
+
+big_const_float(F) ->
+ I = trunc(F),
+ badarith = try (1/(2*I)) catch error:Err -> Err end,
+ _ = 2/I,
+ {'EXIT', _} = (catch 4/(2*I)),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Forces floating point exceptions and tests that subsequent, legal,
+%% operations are calculated correctly.
+
+test_fp_with_fp_exceptions() ->
+ 0.0 = math:log(1.0),
+ badarith = try math:log(float_minus_one()) catch error:E1 -> E1 end,
+ 0.0 = math:log(1.0),
+ badarith = try math:log(float_zero()) catch error:E2 -> E2 end,
+ 0.0 = math:log(1.0),
+ %% An old-fashioned exception here just so as to test this case also
+ {'EXIT', _} = (catch fp_mult(3.23e133, 3.57e257)),
+ 0.0 = math:log(1.0),
+ badarith = try fp_div(5.0, 0.0) catch error:E3 -> E3 end,
+ 0.0 = math:log(1.0),
+ ok.
+
+fp_mult(X, Y) -> X * Y.
+
+fp_div(X, Y) -> X / Y.
+
+%% The following two function definitions appear here just to shut
+%% off 'expression will fail with a badarg' warnings from the compiler
+
+float_zero() -> 0.0.
+
+float_minus_one() -> -1.0.
+
+%%--------------------------------------------------------------------
+%% Test that erl_printf_format.c:fmt_double() does not leak pending FP
+%% exceptions to subsequent code. This used to break x87 FP code on
+%% 32-bit x86. Based on a problem report from Richard Carlsson.
+
+test_fmt_double_fpe_leak() ->
+ test_fmt_double_fpe_leak(float_zero(), int_two()),
+ ok.
+
+%% We need the specific sequence of erlang:display/1 on a float that
+%% triggers faulting ops in fmt_double() followed by a simple FP BIF.
+%% We also need to repeat this at least three times.
+test_fmt_double_fpe_leak(X, Y) ->
+ erlang:display(X), _ = math:log10(Y),
+ erlang:display(X), _ = math:log10(Y),
+ erlang:display(X), _ = math:log10(Y),
+ erlang:display(X), _ = math:log10(Y),
+ erlang:display(X),
+ math:log10(Y).
+
+int_two() -> 2.
+
+%%--------------------------------------------------------------------
+%% Contains code which confuses the icode_type analysis and results
+%% in a compiler crash. Stipped down from code sent by Paul Guyot.
+%% Compiles alright with the option 'no_icode_type' but that defeats
+%% the purpose of the test.
+
+test_icode_type_crash() ->
+ Fun = f(1, 2, 3),
+ 42.0 = Fun(),
+ ok.
+
+f(A, B, C) ->
+ fun () ->
+ X = case A of
+ 0 -> 1 / B;
+ _ -> A / C
+ end,
+ Y = case B of
+ a -> 1.0;
+ b -> 2.0;
+ _ -> 6.0
+ end,
+ Z = case C of
+ c -> 0.1 * X;
+ _ -> 7.0
+ end,
+ Y * Z
+ end.
+
+%%--------------------------------------------------------------------
+%% Contains another case that crashed hipe_icode_fp. This sample was
+%% sent by Mattias Jansson (25 Nov 2015). It compiled alright with the
+%% option 'no_icode_type' but that defeats the purpose of the test.
+%% Unfortunately, the execution of this code goes into an infinite
+%% loop, even if the map in the second argument of eat_what/2 gets the
+%% appropriate key-value pairs. Still, it is retained as a test
+%% because it exposed a different crash than test_icode_type_crash/0.
+
+test_icode_type_crash_2() ->
+ {'EXIT', {function_clause, _}} = (catch eat()),
+ ok.
+
+eat() ->
+ eat_what(1.0, #{}).
+
+eat_what(Factor, #{rat_type := LT} = Rat) ->
+ #{cheese := Cheese} = Rat,
+ UnitCheese = Cheese / 2,
+ RetA = case eat() of
+ {full, RetA1} ->
+ CheeseB2 = min(RetA1, UnitCheese) * Factor,
+ case eat() of
+ full -> {win, RetA1};
+ hungry -> {partial, RetA1 - CheeseB2}
+ end;
+ AOther -> AOther
+ end,
+ RetB = case eat() of
+ {full, RetB1} ->
+ CheeseA2 = min(RetB1, UnitCheese) * Factor,
+ rat:init(single, LT, CheeseA2),
+ case eat() of
+ full -> {full, RetB1};
+ hungry -> {hungry, RetB1 - CheeseA2}
+ end
+ end,
+ {RetA, RetB}.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_fun.erl b/lib/hipe/test/basic_SUITE_data/basic_fun.erl
new file mode 100644
index 0000000000..18ba7fdb3f
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_fun.erl
@@ -0,0 +1,124 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Tests for correct handling of funs.
+%%%-------------------------------------------------------------------
+-module(basic_fun).
+
+-export([test/0]).
+
+-export([dummy_foo/4, add1/1, test_fun03/0]).
+
+test() ->
+ ok = test_calls(),
+ ok = test_is_function(),
+ ok = test_is_function2(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Tests function and fun calls.
+
+test_calls() ->
+ ok = test_apply_call(?MODULE, dummy_foo),
+ ok = test_fun_call(fun dummy_foo/4),
+ ok = test_fun_call(fun ?MODULE:dummy_foo/4),
+ ok.
+
+test_apply_call(M, F) ->
+ M:F(bar, 42, foo, 17).
+
+test_fun_call(Fun) ->
+ Fun(bar, 42, foo, 17).
+
+dummy_foo(_, _, foo, _) -> ok.
+
+%%--------------------------------------------------------------------
+%% Tests handling of funs out of exported functions and 2-tuple funs.
+
+test_fun03() ->
+ MFPair = add1_as_2tuple(),
+ 4712 = do_call(add1_as_export(), 4711),
+ {badfun, MFPair} = try do_call(MFPair, 88) catch error:Err -> Err end,
+ true = do_guard(add1_as_export()),
+ false = do_guard(MFPair), % 2-tuples do not satisfy is_function/1
+ ok.
+
+do_call(F, X) -> F(X).
+
+do_guard(F) when is_function(F) -> true;
+do_guard(_) -> false.
+
+add1_as_export() -> fun ?MODULE:add1/1.
+
+add1_as_2tuple() -> {?MODULE, add1}.
+
+add1(X) -> X+1.
+
+%%--------------------------------------------------------------------
+%% Tests the is_function guard and BIF.
+
+test_is_function() ->
+ Fun = fun (X, foo) -> dummy_foo(X, mnesia_lib, foo, [X]) end,
+ ok = test_when_guard(Fun),
+ ok = test_if_guard(Fun),
+ ok.
+
+test_when_guard(X) when is_function(X) -> ok.
+
+test_if_guard(X) ->
+ if is_function(X) -> ok;
+ true -> weird
+ end.
+
+%%--------------------------------------------------------------------
+%% Tests the is_function2 guard and BIF.
+
+test_is_function2() ->
+ ok = test_guard(),
+ ok = test_guard2(),
+ ok = test_call(),
+ ok.
+
+test_guard() ->
+ zero_fun = test_f2(fun () -> ok end),
+ unary_fun = test_f2(fun(X) -> X end),
+ binary_fun = test_f2(fun (X, Y) -> {X, Y} end),
+ no_fun = test_f2(gazonk),
+ ok.
+
+test_f2(Fun) when is_function(Fun, 0) ->
+ zero_fun;
+test_f2(Fun) when is_function(Fun, 1) ->
+ unary_fun;
+test_f2(Fun) when is_function(Fun, 2) ->
+ binary_fun;
+test_f2(_) ->
+ no_fun.
+
+test_guard2() ->
+ zero_fun = test_f2_n(fun () -> ok end, 0),
+ unary_fun = test_f2_n(fun (X) -> X end, 1),
+ binary_fun = test_f2_n(fun (X, Y) -> {X, Y} end, 2),
+ no_fun = test_f2_n(gazonk, 0),
+ ok.
+
+test_f2_n(F, N) when is_function(F, N) ->
+ case N of
+ 0 -> zero_fun;
+ 1 -> unary_fun;
+ 2 -> binary_fun
+ end;
+test_f2_n(_, _) ->
+ no_fun.
+
+test_call() ->
+ true = test_fn2(fun (X, Y) -> {X,Y} end, 2),
+ false = test_fn2(fun (X, Y) -> {X,Y} end, 3),
+ false = test_fn2(gazonk, 2),
+ {'EXIT', {badarg, _TR1}} = (catch test_fn2(gazonk, gazonk)),
+ {'EXIT', {badarg, _TR2}} = (catch test_fn2(fun (X, Y) -> {X, Y} end, gazonk)),
+ ok.
+
+test_fn2(F, N) ->
+ is_function(F, N).
diff --git a/lib/hipe/test/basic_SUITE_data/basic_guards.erl b/lib/hipe/test/basic_SUITE_data/basic_guards.erl
new file mode 100644
index 0000000000..81eeed7c3b
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_guards.erl
@@ -0,0 +1,164 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests for correct handling of guards and guard BIFs.
+%%%-------------------------------------------------------------------
+-module(basic_guards).
+
+-export([test/0]).
+%% Prevent the inlining of the following functions
+-export([bad_arith/0, bad_tuple/0, is_strange_guard/0]).
+
+test() ->
+ ok = guard0(4.2),
+ ok = guard1([foo]),
+ ok = test_guard2(),
+ ok = test_guard3(),
+ ok = test_guard4(),
+ ok = test_is_boolean(),
+ ok = test_bad_guards(),
+ ok.
+
+%%--------------------------------------------------------------------
+
+guard0(X) when X /= 0, is_float(X) ->
+ ok.
+
+guard1(X) when is_atom(X) orelse is_float(X) ->
+ error1;
+guard1(X) when is_reference(hd(X)) ->
+ error2;
+guard1(X) when is_integer(hd(X)) ->
+ error3;
+guard1(X) when hd(X) == foo ->
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_guard2() ->
+ ok1 = guard2(true),
+ not_boolean = guard2(42),
+ ok2 = guard2(false),
+ ok.
+
+guard2(X) when X -> % gets transformed to: is_boolean(X), X =:= true
+ ok1;
+guard2(X) when X =:= false ->
+ ok2;
+guard2(_) ->
+ not_boolean.
+
+%%--------------------------------------------------------------------
+
+-define(is_foo(X), (is_atom(X) or (is_tuple(X) and (element(1, X) =:= 'foo')))).
+
+test_guard3() ->
+ no = f('foo'),
+ yes = f({'foo', 42}),
+ no = f(42),
+ ok.
+
+f(X) when ?is_foo(X) -> yes;
+f(_) -> no.
+
+%%--------------------------------------------------------------------
+
+-define(EXT_REF, <<131,114,0,3,100,0,19,114,101,102,95,116,101,115,116,95,98,117,103,64,103,111,114,98,97,103,2,0,0,0,125,0,0,0,0,0,0,0,0>>).
+
+test_guard4() ->
+ yes = is_ref(make_ref()),
+ no = is_ref(gazonk),
+ yes = is_ref(an_external_ref(?EXT_REF)),
+ ok.
+
+is_ref(Ref) when is_reference(Ref) -> yes;
+is_ref(_Ref) -> no.
+
+an_external_ref(Bin) ->
+ binary_to_term(Bin).
+
+%%--------------------------------------------------------------------
+
+test_is_boolean() ->
+ ok = is_boolean_in_if(),
+ ok = is_boolean_in_guard().
+
+is_boolean_in_if() ->
+ ok1 = tif(true),
+ ok2 = tif(false),
+ not_bool = tif(other),
+ ok.
+
+is_boolean_in_guard() ->
+ ok = tg(true),
+ ok = tg(false),
+ not_bool = tg(other),
+ ok.
+
+tif(V) ->
+ Yes = yes(), %% just to prevent the optimizer removing this
+ if
+ %% the following line generates an is_boolean instruction
+ V, Yes == yes ->
+ %% while the following one does not (?!)
+ %% Yes == yes, V ->
+ ok1;
+ not(not(not(V))) ->
+ ok2;
+ V ->
+ ok3;
+ true ->
+ not_bool
+ end.
+
+tg(V) when is_boolean(V) ->
+ ok;
+tg(_) ->
+ not_bool.
+
+yes() -> yes.
+
+%%--------------------------------------------------------------------
+%% original test by Bjorn G
+
+test_bad_guards() ->
+ ok = bad_arith(),
+ ok = bad_tuple(),
+ ok = is_strange_guard(),
+ ok.
+
+bad_arith() ->
+ 13 = bad_arith1(1, 12),
+ 42 = bad_arith1(1, infinity),
+ 42 = bad_arith1(infinity, 1),
+ 42 = bad_arith2(infinity, 1),
+ 42 = bad_arith3(inf),
+ 42 = bad_arith4(infinity, 1),
+ ok.
+
+bad_arith1(T1, T2) when (T1 + T2) < 17 -> T1 + T2;
+bad_arith1(_, _) -> 42.
+
+bad_arith2(T1, T2) when (T1 * T2) < 17 -> T1 * T2;
+bad_arith2(_, _) -> 42.
+
+bad_arith3(T) when (bnot T) < 17 -> T;
+bad_arith3(_) -> 42.
+
+bad_arith4(T1, T2) when (T1 bsr T2) < 10 -> T1 bsr T2;
+bad_arith4(_, _) -> 42.
+
+bad_tuple() ->
+ error = bad_tuple1(a),
+ error = bad_tuple1({a, b}),
+ x = bad_tuple1({x, b}),
+ y = bad_tuple1({a, b, y}),
+ ok.
+
+bad_tuple1(T) when element(1, T) =:= x -> x;
+bad_tuple1(T) when element(3, T) =:= y -> y;
+bad_tuple1(_) -> error.
+
+is_strange_guard() when is_tuple({1, bar, length([1, 2, 3, 4]), self()}) -> ok;
+is_strange_guard() -> error.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_inline_function.erl b/lib/hipe/test/basic_SUITE_data/basic_inline_function.erl
new file mode 100644
index 0000000000..4c08064670
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_inline_function.erl
@@ -0,0 +1,73 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests that depend on the compiler inliner being turned on.
+%%%-------------------------------------------------------------------
+-module(basic_inline_function).
+
+-export([test/0]).
+
+-compile({inline, [{to_objects, 3}]}).
+
+test() ->
+ ok = test_inline_match(),
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_inline_match() ->
+ bad_object = test1(a, {binary, foo, set}, c),
+ bad_object = test2(a, {binary, foo, set}, c),
+ bad_object = test3(a, {binary, foo, set}, c),
+ ok.
+
+%% Inlined
+test1(KeysObjs, C, Ts) ->
+ case catch to_objects(KeysObjs, C, Ts) of
+ {'EXIT', _} ->
+ bad_object;
+ ok ->
+ ok
+ end.
+
+%% "Inlined" by hand
+test2(KeysObjs, C, _Ts) ->
+ case catch (case C of
+ {binary, _, set} ->
+ <<_ObjSz0:32, _T/binary>> = KeysObjs;
+ _ -> ok
+ end) of
+ {'EXIT', _} ->
+ bad_object;
+ ok ->
+ ok
+ end.
+
+%% Not inlined
+test3(KeysObjs, C, Ts) ->
+ case catch fto_objects(KeysObjs, C, Ts) of
+ {'EXIT', _} ->
+ bad_object;
+ ok ->
+ ok
+ end.
+
+%% Inlined.
+to_objects(Bin, {binary, _, set}, _Ts) ->
+ <<_ObjSz0:32, _T/binary>> = Bin,
+ ok;
+to_objects(<<_ObjSz0:32, _T/binary>> ,_, _) ->
+ ok;
+to_objects(_Bin, _, _Ts) ->
+ ok.
+
+%% Not Inlined.
+fto_objects(Bin, {binary, _, set}, _Ts) ->
+ <<_ObjSz0:32, _T/binary>> = Bin,
+ ok;
+fto_objects(<<_ObjSz0:32, _T/binary>> ,_,_) ->
+ ok;
+fto_objects(_Bin, _, _Ts) ->
+ ok.
+
diff --git a/lib/hipe/test/basic_SUITE_data/basic_inline_module.erl b/lib/hipe/test/basic_SUITE_data/basic_inline_module.erl
new file mode 100644
index 0000000000..306c6a39ce
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_inline_module.erl
@@ -0,0 +1,31 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests that depend on the compiler inliner being turned on.
+%%%-------------------------------------------------------------------
+-module(basic_inline_module).
+
+-export([test/0]).
+
+-compile([inline]). %% necessary for these tests
+
+test() ->
+ ok = test_case_end_atom(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Tests whether the translation of a case_end instruction works even
+%% when an exception (no matching case pattern) is to be raised.
+
+test_case_end_atom() ->
+ {'EXIT',{{case_clause,some_atom},_Trace}} = (catch test_case_stm_inlining()),
+ ok.
+
+test_case_stm_inlining() ->
+ case some_atom() of
+ another_atom -> strange_result
+ end.
+
+some_atom() ->
+ some_atom.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_issues_beam.erl b/lib/hipe/test/basic_SUITE_data/basic_issues_beam.erl
new file mode 100644
index 0000000000..73367c5c45
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_issues_beam.erl
@@ -0,0 +1,326 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains code examples, mostly taken from the mailing list, that
+%%% crashed the BEAM compiler or gave an internal error at some point.
+%%%-------------------------------------------------------------------
+-module(basic_issues_beam).
+
+-export([test/0]).
+
+test() ->
+ ok = test_crash_R10_hinde(),
+ ok = test_error_R10_mander(),
+ ok = test_error_R11_bjorklund(),
+ ok = test_error_R11_rath(),
+ ok = test_error_R12_empty_bin_rec(),
+ ok = test_bug_R12_cornish(),
+ ok = test_crash_R12_morris(),
+ ok = test_error_R13_almeida(),
+ ok = test_error_R13B01_fisher(),
+ ok = test_error_R13B01_sawatari(),
+ ok = test_error_R13B01_whongo(),
+ ok = test_error_R16B03_norell(),
+ ok = test_error_try_wings(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Fisher R10 compiler crash
+%%--------------------------------------------------------------------
+
+-record(r, {a, b, c}).
+
+test_crash_R10_hinde() ->
+ rec_R10_hinde(#r{}).
+
+rec_R10_hinde(As) ->
+ case As of
+ A when A#r.b == ""; A#r.b == undefined -> ok;
+ _ -> error
+ end.
+
+%%--------------------------------------------------------------------
+%% From: Peter-Henry Mander
+%% Date: 27 Jan, 2005
+%%
+%% I managed to isolate a non-critical BEAM compilation error
+%% (internal error in v3_codegen) when compiling the following code:
+%%--------------------------------------------------------------------
+
+test_error_R10_mander() ->
+ try just_compile_me_R10() catch _:_ -> ok end.
+
+just_compile_me_R10() ->
+ URI_Before =
+ {absoluteURI,
+ {scheme, fun() -> nil end},
+ {hier_part,
+ {net_path,
+ {srvr,
+ {userinfo, nil},
+ fun() -> nil end},
+ nil},
+ {port, nil}}},
+ {absoluteURI,
+ {scheme, _},
+ {hier_part,
+ {net_path,
+ {srvr,
+ {userinfo, nil},
+ _HostportBefore},
+ nil},
+ {port, nil}}} = URI_Before,
+ %% ... some funky code ommitted, not relevant ...
+ {absoluteURI,
+ {scheme, _},
+ {hier_part,
+ {net_path,
+ {srvr,
+ {userinfo, nil},
+ HostportAfter},
+ nil},
+ {port, nil}}} = URI_Before,
+ %% NOTE: I intended to write URI_After instead of URI_Before
+ %% but the accident revealed that when you add the line below,
+ %% it causes internal error in v3_codegen on compilation
+ {hostport, {hostname, "HostName"}, {port, nil}} = HostportAfter,
+ ok.
+
+%%--------------------------------------------------------------------
+%% From: Martin Bjorklund
+%% Date: Aug 16, 2006
+%%
+%% I found this compiler bug in R10B-10 and R11B-0.
+%%
+%% Function -just_compile_me/0-fun-2-/1 refers to undefined label 18
+%% ./bjorklund_R11compiler_bug.erl:none: internal error in beam_clean;
+%% crash reason: {{case_clause,{'EXIT',{undefined_label,18}}},
+%% [{compile,'-select_passes/2-anonymous-2-',2},
+%% {compile,'-internal_comp/4-anonymous-1-',2},
+%% {compile,fold_comp,3},
+%% {compile,internal_comp,4},
+%% {compile,internal,3}]}
+%%--------------------------------------------------------------------
+
+test_error_R11_bjorklund() ->
+ just_compile_me_R11_bjorklund().
+
+just_compile_me_R11_bjorklund() ->
+ G = fun() -> ok end,
+ try
+ G() %% fun() -> ok end
+ after
+ fun({A, B}) -> A + B end
+ end.
+
+%%--------------------------------------------------------------------
+%% From: Tim Rath
+%% Date: Sep 13, 2006
+%% Subject: Compiler bug not quite fixed
+%%
+%%
+%% I saw a compiler bug posted to the list by Martin Bjorklund that
+%% appeared to be exactly the problem I'm seeing, and then noticed
+%% that this was fixed in R11B-1. Unfortunately, though R11B-1 appears
+%% to fix the code submitted by Martin, it does not fix my case.
+%%
+%% Function -just_compile_me/0-fun-2-/1 refers to undefined label 13
+%% ./rath_R11compiler_bug.erl:none: internal error in beam_clean;
+%% crash reason: {{case_clause,{'EXIT',{undefined_label,13}}},
+%% [{compile,'-select_passes/2-anonymous-2-',2},
+%% {compile,'-internal_comp/4-anonymous-1-',2},
+%% {compile,fold_comp,3},
+%% {compile,internal_comp,4},
+%% {compile,internal,3}]}
+%%--------------------------------------------------------------------
+
+test_error_R11_rath() ->
+ just_compile_me_R11_rath().
+
+just_compile_me_R11_rath() ->
+ A = {6},
+ try
+ io:fwrite("")
+ after
+ fun () ->
+ fun () -> {_} = A end
+ end
+ end.
+
+%%----------------------------------------------------------------------
+%% Program that crashed the R12B-0 compiler: internal error in v3_codegen
+%%----------------------------------------------------------------------
+
+-record(rec, {a = <<>> :: binary(), b = 42 :: integer()}).
+
+test_error_R12_empty_bin_rec() ->
+ 42 = test_empty_bin_rec(#rec{}),
+ ok.
+
+test_empty_bin_rec(R) ->
+ #rec{a = <<>>} = R,
+ R#rec.b.
+
+%%----------------------------------------------------------------------
+%% From: Simon Cornish
+%% Date: Jan 13, 2008
+%%
+%% The attached Erlang code demonstrates an R12B-0 bug with funs.
+%% Compile and evaluate the two die/1 calls for two different failure modes.
+%% It seems to me that the live register check for call_fun is off by one.
+%%----------------------------------------------------------------------
+
+-record(b, {c}).
+
+test_bug_R12_cornish() ->
+ {a2, a} = die(a),
+ {a2, {b, c}} = die({b, c}),
+ ok.
+
+die(A) ->
+ F = fun() -> {ok, A} end,
+ if A#b.c =:= [] -> one;
+ true ->
+ case F() of
+ {ok, A2} -> {a2, A2};
+ _ -> three
+ end
+ end.
+
+%%----------------------------------------------------------------------
+%% From: Hunter Morris
+%% Date: Nov 20, 2008
+%%
+%% The following code (tested with R12B-4 or R12B-5, vanilla compiler
+%% options) produces a compiler crash. It's nonsensical, and I realise
+%% that andalso can be quite evil, but it's a crash nonetheless.
+%%----------------------------------------------------------------------
+
+test_crash_R12_morris() ->
+ foo(42).
+
+foo(Bar) when (is_integer(Bar) andalso Bar =:= 0) ; Bar =:= 42 ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% From: Paulo Sergio Almeida
+%% Date: May 20, 2009
+%%
+%% The following code when compiled under R13B gives a compiler error.
+%% Function loop/1 refers to undefined label 6
+%% ./almeida_R13compiler_bug.erl:none: internal error in beam_peep;
+%% crash reason: {{case_clause,{'EXIT',{undefined_label,6}}},
+%% [{compile,'-select_passes/2-anonymous-2-',2},
+%% {compile,'-internal_comp/4-anonymous-1-',2},
+%%--------------------------------------------------------------------
+
+test_error_R13_almeida() ->
+ self() ! {backup, 42, false},
+ loop([]).
+
+loop(Tids) ->
+ receive
+ {backup, Tid, Dumping} ->
+ case Dumping of
+ false -> ok;
+ _ -> receive {logged, Tab, Tid} -> put({log, Tab}, Tid) end
+ end,
+ collect(Tid, Tids, [])
+ end.
+
+collect(_, _, _) -> ok.
+
+%%--------------------------------------------------------------------
+%% Fisher R13B01 compiler error
+%%--------------------------------------------------------------------
+
+test_error_R13B01_fisher() ->
+ perform_select({foo, "42"}).
+
+perform_select({Type, Keyval}) ->
+ try
+ if is_atom(Type) andalso length(Keyval) > 0 -> ok;
+ true -> ok
+ end
+ catch
+ _:_ -> fail
+ end.
+
+%%--------------------------------------------------------------------
+%% From: Mikage Sawatari
+%% Date: Jun 12, 2009
+%%
+%% I have the following compilation problem on Erlang R13B01.
+%% Compiler reports "Internal consistency check failed".
+%%--------------------------------------------------------------------
+
+test_error_R13B01_sawatari() ->
+ test_sawatari([1, null, 3], <<1, 2, 3>>).
+
+test_sawatari([], _Bin) -> ok;
+test_sawatari([H|T], Bin) ->
+ _ = case H of
+ null -> <<Bin/binary>>;
+ _ -> ok
+ end,
+ test_sawatari(T, Bin).
+
+%%--------------------------------------------------------------------
+
+test_error_R13B01_whongo() ->
+ S = "gazonk",
+ S = orgno_alphanum(S),
+ ok.
+
+orgno_alphanum(Cs) ->
+ [C || C <- Cs, ((C >= $0) andalso (C =< $9))
+ orelse ((C >= $a) andalso (C =< $z))
+ orelse ((C >= $A) andalso (C =< $Z))].
+
+%%--------------------------------------------------------------------
+%% I'm getting an Internal Consistency Check error when attempting to
+%% build Wings3D on Mac OS X 10.4.2 (Erlang OTP R10B-6):
+%%
+%% erlc -pa /ebin +warn_unused_vars -I/include -I ../e3d -W +debug_info
+%% '-Dwings_version="0.98.31"' -pa ../ebin -o../ebin wings_color.erl
+%% wings_color: function internal_rgb_to_hsv/3+97:
+%% Internal consistency check failed - please report this bug.
+%% Instruction: {test,is_eq_exact,{f,80},[{x,0},{atom,error}]}
+%% Error: {unsafe_instruction,{float_error_state,cleared}}:
+%%
+%% The problem is the interaction of the 'try' construct with the
+%% handling of FP exceptions.
+%%--------------------------------------------------------------------
+
+test_error_try_wings() ->
+ %% a call with a possible FP exception
+ {199.99999999999997, 0.045454545454545456, 44} = rgb_to_hsv(42, 43, 44),
+ ok.
+
+rgb_to_hsv(R, G, B) ->
+ Max = lists:max([R, G, B]),
+ Min = lists:min([R, G, B]),
+ V = Max,
+ {Hue, Sat} = try
+ {if Min == B -> (G-Min)/(R+G-2.0*Min);
+ Min == R -> (1.0+(B-Min)/(B+G-2.0*Min));
+ Min == G -> (2.0+(R-Min)/(B+R-2.0*Min))
+ end * 120, (Max-Min)/Max}
+ catch
+ error:badarith -> {undefined, 0.0}
+ end,
+ {Hue, Sat, V}.
+
+%%--------------------------------------------------------------------
+%% From: Ulf Norell
+%% Date: Feb 28, 2014
+%%
+%% This caused an internal error in v3_codegen
+%%--------------------------------------------------------------------
+
+test_error_R16B03_norell() ->
+ test_error_R16B03_norell(#r{}, gazonk).
+
+test_error_R16B03_norell(Rec, Tag) ->
+ is_record(Rec, Tag, 3) orelse ok.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_issues_hipe.erl b/lib/hipe/test/basic_SUITE_data/basic_issues_hipe.erl
new file mode 100644
index 0000000000..e71045bfe2
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_issues_hipe.erl
@@ -0,0 +1,153 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains code examples that exhibited crashes in the HiPE compiler.
+%%%-------------------------------------------------------------------
+-module(basic_issues_hipe).
+
+-export([test/0]).
+
+%% functions that need to be exported so that they are retained.
+-export([auth/4]).
+
+test() ->
+ ok = test_dominance_trees(),
+ ok = test_merged_const(),
+ ok = test_var_pair(),
+ ok = test_bif_fails(),
+ ok = test_find_catches(),
+ ok = test_heap_allocate_trim(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% This is taken from a file sent to us by Martin Bjorklund @ Nortel
+%% on 14th November 2004. The problem was in the SSA unconvert pass.
+%%
+%% No tests here; we simply check that the HiPE compiler does not go
+%% into an infinite loop when compiling strange functions like this.
+%%--------------------------------------------------------------------
+
+auth(_, A, B, C) ->
+ auth(A, B, C, []).
+
+%%--------------------------------------------------------------------
+%% Exposed a crash in the generation of dominance trees used in SSA.
+%%--------------------------------------------------------------------
+
+-record(state, {f}).
+
+test_dominance_trees() ->
+ {ok, true} = doit(true, #state{f = true}),
+ ok.
+
+doit(Foo, S) ->
+ Fee = case Foo of
+ Bar when Bar == S#state.f; Bar == [] -> true;
+ _ -> false
+ end,
+ {ok, Fee}.
+
+%%--------------------------------------------------------------------
+%% Checks that the merging of constants in the constant table uses the
+%% appropriate comparison function for this.
+%%--------------------------------------------------------------------
+
+test_merged_const() ->
+ Const1 = {'', 1.0000},
+ Const2 = {'', 1},
+ match(Const1, Const2).
+
+match(A, A) ->
+ error;
+match(_A, _B) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Checks that the HiPE compiler does not get confused by constant
+%% data structures similar to the internal compiler data structures.
+%%--------------------------------------------------------------------
+
+test_var_pair() ->
+ ok = var_pair([gazonk]).
+
+var_pair([_|_]) ->
+ var_pair({var, some_atom});
+var_pair(_) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% This module was causing the HiPE compiler to crash in January 2007.
+%% The culprit was an "optimization" of the BEAM compiler: postponing
+%% the save of x variables when BIFs cannot fail. This was fixed on
+%% February 1st, by making the HiPE compiler use the same functions
+%% as the BEAM compiler for deciding whether a BIF fails.
+%%--------------------------------------------------------------------
+
+test_bif_fails() ->
+ [42] = bif_fails_in_catch([42]),
+ true = bif_fails_in_try([42]),
+ ok.
+
+bif_fails_in_catch(X) ->
+ case catch get(gazonk) of
+ _ -> X
+ end.
+
+bif_fails_in_try(X) ->
+ try
+ true = X =/= []
+ catch
+ _ -> nil(X)
+ end.
+
+nil(_) -> [].
+
+%%--------------------------------------------------------------------
+%% Test that resulted in a native code compiler crash in the code of
+%% hipe_icode_exceptions:find_catches/1 when compiling find_catches/2.
+%%--------------------------------------------------------------------
+
+test_find_catches() ->
+ 42 = find_catches(a, false),
+ ok.
+
+find_catches(X, Y) ->
+ case X of
+ a when Y =:= true ->
+ catch id(X),
+ X;
+ b when Y =:= true ->
+ catch id(X),
+ X;
+ a ->
+ catch id(X),
+ 42;
+ b ->
+ catch id(X),
+ 42
+ end.
+
+id(X) -> X.
+
+%%--------------------------------------------------------------------
+%% Date: Dec 28, 2007
+%%
+%% This is a test adapted from the file sent to the Erlang mailing
+%% list by Eranga Udesh. The file did not compile because of problems
+%% with the heap_allocate instruction and stack trimming.
+%%--------------------------------------------------------------------
+
+test_heap_allocate_trim() ->
+ {abandon, 42} = get_next_retry(a, 42),
+ ok.
+
+get_next_retry(Error, Count) ->
+ case catch pair(retry_scheme, {Error, Count}) of
+ _ ->
+ case pair(Error, Count) of
+ _ -> {abandon, Count}
+ end
+ end.
+
+pair(A, B) -> {A, B}.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_lists.erl b/lib/hipe/test/basic_SUITE_data/basic_lists.erl
new file mode 100644
index 0000000000..264a7f86f6
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_lists.erl
@@ -0,0 +1,61 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests that manipulate and pattern match against lists
+%%% (perhaps by calling functions from the 'lists' module).
+%%%-------------------------------------------------------------------
+-module(basic_lists).
+
+-export([test/0]).
+
+test() ->
+ ok = test_length(),
+ ok = test_lists_key(),
+ ok = test_lists_and_strings(),
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_length() ->
+ Len = 42,
+ Lst = mklist(Len, []),
+ Len = iterate(100, Lst),
+ ok.
+
+mklist(0, L) -> L;
+mklist(X, L) -> mklist(X-1, [X|L]).
+
+iterate(0, L) -> len(L, 0);
+iterate(X, L) -> len(L, 0), iterate(X-1, L).
+
+len([_|X], L) -> len(X, L+1);
+len([], L) -> L.
+
+%%--------------------------------------------------------------------
+
+test_lists_key() ->
+ First = {x, 42.0},
+ Second = {y, -77},
+ Third = {z, [a, b, c], {5.0}},
+ List = [First, Second, Third],
+ {value, First} = key_search_find(42, 2, List),
+ ok.
+
+key_search_find(Key, Pos, List) ->
+ case lists:keyfind(Key, Pos, List) of
+ false ->
+ false = lists:keysearch(Key, Pos, List);
+ Tuple when is_tuple(Tuple) ->
+ {value, Tuple} = lists:keysearch(Key, Pos, List)
+ end.
+
+%%--------------------------------------------------------------------
+
+test_lists_and_strings() ->
+ LL = ["H'A", " H'B", " H'C"],
+ LL2 = lists:map(fun string:strip/1, LL),
+ HexFormat = fun(X, Acc) -> {string:substr(X, 3), Acc} end,
+ {LL3,_Ret} = lists:mapfoldl(HexFormat, 0, LL2),
+ ["A", "B", "C"] = lists:sublist(LL3, 42),
+ ok.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_module_info.erl b/lib/hipe/test/basic_SUITE_data/basic_module_info.erl
new file mode 100644
index 0000000000..cab48b10ba
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_module_info.erl
@@ -0,0 +1,32 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%% Date: Oct 25, 2003
+%%%
+%%% Tests whether calling module_info from the same module works.
+%%% This seems trivial, but the problem is that the module_info/[0,1]
+%%% functions that the BEAM file contains used to be dummy functions
+%%% containing crap. So, these functions could not be used for
+%%% compilation to native code and the functions that the BEAM loader
+%%% generates should have been used instead. This was a HiPE bug
+%%% reported by Dan Wallin.
+%%%-------------------------------------------------------------------
+-module(basic_module_info).
+
+-export([test/0]).
+
+test() ->
+ L = test_local_mi0_call(),
+ E = test_remote_mi1_call(),
+ {3, 3} = {L, E},
+ ok.
+
+test_local_mi0_call() ->
+ ModInfo = module_info(),
+ %% io:format("ok, ModInfo=~w\n", [ModInfo]),
+ {exports, FunList} = lists:keyfind(exports, 1, ModInfo),
+ length(FunList).
+
+test_remote_mi1_call() ->
+ FunList = ?MODULE:module_info(exports),
+ length(FunList).
diff --git a/lib/hipe/test/basic_SUITE_data/basic_pattern_match.erl b/lib/hipe/test/basic_SUITE_data/basic_pattern_match.erl
new file mode 100644
index 0000000000..93240354a7
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_pattern_match.erl
@@ -0,0 +1,46 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains code examples that test pattern matching against terms of
+%%% various types.
+%%%-------------------------------------------------------------------
+-module(basic_pattern_match).
+
+-export([test/0]).
+
+test() ->
+ ok = test_hello_world(),
+ ok = test_list_plus_plus_match(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Trivial test to test pattern matching compilation with atoms, the
+%% correct handling of all sorts of alphanumeric types in Erlang, and
+%% conversions between them.
+
+test_hello_world() ->
+ String = gimme(string),
+ String = atom_to_list(gimme(atom)),
+ String = binary_to_list(gimme(binary)),
+ true = (list_to_atom(String) =:= gimme(atom)),
+ true = (list_to_binary(String) =:= gimme(binary)),
+ ok.
+
+gimme(string) ->
+ "hello world";
+gimme(atom) ->
+ 'hello world';
+gimme(binary) ->
+ <<"hello world">>.
+
+%%--------------------------------------------------------------------
+%% Makes sure that pattern matching expressions involving ++ work OK.
+%% The third expression caused a problem in the Erlang shell of R11B-5.
+%% It worked OK in both interpreted and compiled code.
+
+test_list_plus_plus_match() ->
+ ok = (fun("X" ++ _) -> ok end)("X"),
+ ok = (fun([$X | _]) -> ok end)("X"),
+ ok = (fun([$X] ++ _) -> ok end)("X"),
+ ok.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_random.erl b/lib/hipe/test/basic_SUITE_data/basic_random.erl
new file mode 100644
index 0000000000..783947bd31
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_random.erl
@@ -0,0 +1,238 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% A test for list handling created using the 'random' module.
+%%%-------------------------------------------------------------------
+-module(basic_random).
+
+-export([test/0]).
+
+%% It can be used as a benchmark by playing with the following defines
+-define(N, 1000).
+-define(Iter, 500).
+
+test() ->
+ ok = random(?N).
+
+random(N) ->
+ random(N, ?Iter).
+
+random(N, Iter) ->
+ random:seed(1, 2, 3),
+ t(ranlist(N, [], N*100), Iter).
+
+ranlist(0, L, _N) -> L;
+ranlist(N, L, N0) -> ranlist(N-1, [random:uniform(N0)+300 | L], N0).
+
+t(_, 0) -> ok;
+t(L, Iter) ->
+ %% io:format("Sort starting~n"),
+ sort(L),
+ t(L, Iter-1).
+
+sort([X, Y | L]) when X =< Y ->
+ split_1(X, Y, L, [], []);
+sort([X, Y | L]) ->
+ split_2(X, Y, L, [], []);
+sort(L) ->
+ L.
+
+%% Ascending.
+split_1(X, Y, [Z | L], R, Rs) when Z >= Y ->
+ split_1(Y, Z, L, [X | R], Rs);
+split_1(X, Y, [Z | L], R, Rs) when Z >= X ->
+ split_1(Z, Y, L, [X | R], Rs);
+split_1(X, Y, [Z | L], [], Rs) ->
+ split_1(X, Y, L, [Z], Rs);
+split_1(X, Y, [Z | L], R, Rs) ->
+ split_1_1(X, Y, L, R, Rs, Z);
+split_1(X, Y, [], R, Rs) ->
+ rmergel([[Y, X | R] | Rs], []).
+
+%% One out-of-order element, S.
+split_1_1(X, Y, [Z | L], R, Rs, S) when Z >= Y ->
+ split_1_1(Y, Z, L, [X | R], Rs, S);
+split_1_1(X, Y, [Z | L], R, Rs, S) when Z >= X ->
+ split_1_1(Z, Y, L, [X | R], Rs, S);
+split_1_1(X, Y, [Z | L], R, Rs, S) when S =< Z ->
+ split_1(S, Z, L, [], [[Y, X | R] | Rs]);
+split_1_1(X, Y, [Z | L], R, Rs, S) ->
+ split_1(Z, S, L, [], [[Y, X | R] | Rs]);
+split_1_1(X, Y, [], R, Rs, S) ->
+ rmergel([[S], [Y, X | R] | Rs], []).
+
+%% Descending.
+split_2(X, Y, [Z | L], R, Rs) when Z =< Y ->
+ split_2(Y, Z, L, [X | R], Rs);
+split_2(X, Y, [Z | L], R, Rs) when Z =< X ->
+ split_2(Z, Y, L, [X | R], Rs);
+split_2(X, Y, [Z | L], [], Rs) ->
+ split_2(X, Y, L, [Z], Rs);
+split_2(X, Y, [Z | L], R, Rs) ->
+ split_2_1(X, Y, L, R, Rs, Z);
+split_2(X, Y, [], R, Rs) ->
+ mergel([[Y, X | R] | Rs], []).
+
+split_2_1(X, Y, [Z | L], R, Rs, S) when Z =< Y ->
+ split_2_1(Y, Z, L, [X | R], Rs, S);
+split_2_1(X, Y, [Z | L], R, Rs, S) when Z =< X ->
+ split_2_1(Z, Y, L, [X | R], Rs, S);
+split_2_1(X, Y, [Z | L], R, Rs, S) when S > Z ->
+ split_2(S, Z, L, [], [[Y, X | R] | Rs]);
+split_2_1(X, Y, [Z | L], R, Rs, S) ->
+ split_2(Z, S, L, [], [[Y, X | R] | Rs]);
+split_2_1(X, Y, [], R, Rs, S) ->
+ mergel([[S], [Y, X | R] | Rs], []).
+
+mergel([[] | L], Acc) ->
+ mergel(L, Acc);
+mergel([A, [H2 | T2], [H3 | T3] | L], Acc) ->
+ mergel(L, [merge3_1(A, [], H2, T2, H3, T3) | Acc]);
+mergel([A, [H | T]], Acc) ->
+ rmergel([merge2_1(A, H, T, []) | Acc], []);
+mergel([L], []) ->
+ L;
+mergel([L], Acc) ->
+ rmergel([lists:reverse(L, []) | Acc], []);
+mergel([], []) ->
+ [];
+mergel([], Acc) ->
+ rmergel(Acc, []);
+mergel([A, [] | L], Acc) ->
+ mergel([A | L], Acc);
+mergel([A, B, [] | L], Acc) ->
+ mergel([A, B | L], Acc).
+
+rmergel([A, [H2 | T2], [H3 | T3] | L], Acc) ->
+ rmergel(L, [rmerge3_1(A, [], H2, T2, H3, T3) | Acc]);
+rmergel([A, [H | T]], Acc) ->
+ mergel([rmerge2_1(A, H, T, []) | Acc], []);
+rmergel([L], Acc) ->
+ mergel([lists:reverse(L, []) | Acc], []);
+rmergel([], Acc) ->
+ mergel(Acc, []).
+
+%% Take L1 apart.
+merge3_1([H1 | T1], M, H2, T2, H3, T3) when H1 =< H2 ->
+ merge3_12(T1, H1, H2, T2, H3, T3, M);
+merge3_1([H1 | T1], M, H2, T2, H3, T3) ->
+ merge3_21(T1, H1, H2, T2, H3, T3, M);
+merge3_1(_nil, M, H2, T2, H3, T3) when H2 =< H3 ->
+ merge2_1(T2, H3, T3, [H2 | M]);
+merge3_1(_nil, M, H2, T2, H3, T3) ->
+ merge2_1(T3, H2, T2, [H3 | M]).
+
+%% Take L2 apart.
+merge3_2(T1, H1, M, [H2 | T2], H3, T3) when H1 =< H2 ->
+ merge3_12(T1, H1, H2, T2, H3, T3, M);
+merge3_2(T1, H1, M, [H2 | T2], H3, T3) ->
+ merge3_21(T1, H1, H2, T2, H3, T3, M);
+merge3_2(T1, H1, M, _nil, H3, T3) when H1 =< H3 ->
+ merge2_1(T1, H3, T3, [H1 | M]);
+merge3_2(T1, H1, M, _nil, H3, T3) ->
+ merge2_1(T3, H1, T1, [H3 | M]).
+
+%% H1 <= H2. Inlined.
+merge3_12(T1, H1, H2, T2, H3, T3, M) when H3 < H1 ->
+ merge3_12_3(T1, H1, H2, T2, [H3 | M], T3);
+merge3_12(T1, H1, H2, T2, H3, T3, M) ->
+ merge3_1(T1, [H1 | M], H2, T2, H3, T3).
+
+%% H1 <= H2, take L3 apart.
+merge3_12_3(T1, H1, H2, T2, M, [H3 | T3]) when H3 < H1 ->
+ merge3_12_3(T1, H1, H2, T2, [H3 | M], T3);
+merge3_12_3(T1, H1, H2, T2, M, [H3 | T3]) ->
+ merge3_1(T1, [H1 | M], H2, T2, H3, T3);
+merge3_12_3(T1, H1, H2, T2, M, _nil) ->
+ merge2_1(T1, H2, T2, [H1 | M]).
+
+%% H1 > H2. Inlined.
+merge3_21(T1, H1, H2, T2, H3, T3, M) when H3 < H2 ->
+ merge3_21_3(T1, H1, H2, T2, [H3 | M], T3);
+merge3_21(T1, H1, H2, T2, H3, T3, M) ->
+ merge3_2(T1, H1, [H2 | M], T2, H3, T3).
+
+%% H1 > H2, take L3 apart.
+merge3_21_3(T1, H1, H2, T2, M, [H3 | T3]) when H3 < H2 ->
+ merge3_21_3(T1, H1, H2, T2, [H3 | M], T3);
+merge3_21_3(T1, H1, H2, T2, M, [H3 | T3]) ->
+ merge3_2(T1, H1, [H2 | M], T2, H3, T3);
+merge3_21_3(T1, H1, H2, T2, M, _nil) ->
+ merge2_1(T2, H1, T1, [H2 | M]).
+
+%% Take L1 apart.
+rmerge3_1([H1 | T1], M, H2, T2, H3, T3) when H1 > H2 ->
+ rmerge3_12(T1, H1, H2, T2, H3, T3, M);
+rmerge3_1([H1 | T1], M, H2, T2, H3, T3) ->
+ rmerge3_21(T1, H1, H2, T2, H3, T3, M);
+rmerge3_1(_nil, M, H2, T2, H3, T3) when H2 > H3 ->
+ rmerge2_1(T2, H3, T3, [H2 | M]);
+rmerge3_1(_nil, M, H2, T2, H3, T3) ->
+ rmerge2_1(T3, H2, T2, [H3 | M]).
+
+%% Take L2 apart.
+rmerge3_2(T1, H1, M, [H2 | T2], H3, T3) when H1 > H2 ->
+ rmerge3_12(T1, H1, H2, T2, H3, T3, M);
+rmerge3_2(T1, H1, M, [H2 | T2], H3, T3) ->
+ rmerge3_21(T1, H1, H2, T2, H3, T3, M);
+rmerge3_2(T1, H1, M, _nil, H3, T3) when H1 > H3 ->
+ rmerge2_1(T1, H3, T3, [H1 | M]);
+rmerge3_2(T1, H1, M, _nil, H3, T3) ->
+ rmerge2_1(T3, H1, T1, [H3 | M]).
+
+%% H1 > H2. Inlined.
+rmerge3_12(T1, H1, H2, T2, H3, T3, M) when H3 >= H1 ->
+ rmerge3_12_3(T1, H1, H2, T2, [H3 | M], T3);
+rmerge3_12(T1, H1, H2, T2, H3, T3, M) ->
+ rmerge3_1(T1, [H1 | M], H2, T2, H3, T3).
+
+%% H1 > H2, take L3 apart.
+rmerge3_12_3(T1, H1, H2, T2, M, [H3 | T3]) when H3 >= H1 ->
+ rmerge3_12_3(T1, H1, H2, T2, [H3 | M], T3);
+rmerge3_12_3(T1, H1, H2, T2, M, [H3 | T3]) ->
+ rmerge3_1(T1, [H1 | M], H2, T2, H3, T3);
+rmerge3_12_3(T1, H1, H2, T2, M, _nil) ->
+ rmerge2_1(T1, H2, T2, [H1 | M]).
+
+%% H1 =< H2. Inlined.
+rmerge3_21(T1, H1, H2, T2, H3, T3, M) when H3 >= H2 ->
+ rmerge3_21_3(T1, H1, H2, T2, [H3 | M], T3);
+rmerge3_21(T1, H1, H2, T2, H3, T3, M) ->
+ rmerge3_2(T1, H1, [H2 | M], T2, H3, T3).
+
+%% H1 =< H2, take L3 apart.
+rmerge3_21_3(T1, H1, H2, T2, M, [H3 | T3]) when H3 >= H2 ->
+ rmerge3_21_3(T1, H1, H2, T2, [H3 | M], T3);
+rmerge3_21_3(T1, H1, H2, T2, M, [H3 | T3]) ->
+ rmerge3_2(T1, H1, [H2 | M], T2, H3, T3);
+rmerge3_21_3(T1, H1, H2, T2, M, _nil) ->
+ rmerge2_1(T2, H1, T1, [H2 | M]).
+
+merge2_1([H1 | T1], H2, T2, M) when H2 < H1 ->
+ merge2_2(T1, H1, T2, [H2 | M]);
+merge2_1([H1 | T1], H2, T2, M) ->
+ merge2_1(T1, H2, T2, [H1 | M]);
+merge2_1(_nil, H2, T2, M) ->
+ lists:reverse(T2, [H2 | M]).
+
+merge2_2(T1, H1, [H2 | T2], M) when H1 < H2 ->
+ merge2_1(T1, H2, T2, [H1 | M]);
+merge2_2(T1, H1, [H2 | T2], M) ->
+ merge2_2(T1, H1, T2, [H2 | M]);
+merge2_2(T1, H1, _nil, M) ->
+ lists:reverse(T1, [H1 | M]).
+
+rmerge2_1([H1 | T1], H2, T2, M) when H2 >= H1 ->
+ rmerge2_2(T1, H1, T2, [H2 | M]);
+rmerge2_1([H1 | T1], H2, T2, M) ->
+ rmerge2_1(T1, H2, T2, [H1 | M]);
+rmerge2_1(_nil, H2, T2, M) ->
+ lists:reverse(T2, [H2 | M]).
+
+rmerge2_2(T1, H1, [H2 | T2], M) when H1 >= H2 ->
+ rmerge2_1(T1, H2, T2, [H1 | M]);
+rmerge2_2(T1, H1, [H2 | T2], M) ->
+ rmerge2_2(T1, H1, T2, [H2 | M]);
+rmerge2_2(T1, H1, _nil, M) ->
+ lists:reverse(T1, [H1 | M]).
diff --git a/lib/hipe/test/basic_SUITE_data/basic_receive.erl b/lib/hipe/test/basic_SUITE_data/basic_receive.erl
new file mode 100644
index 0000000000..5f865d7b7a
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_receive.erl
@@ -0,0 +1,56 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains code examples that test correct handling of receives.
+%%%-------------------------------------------------------------------
+-module(basic_receive).
+
+-export([test/0]).
+
+test() ->
+ ok = test_wait_timeout(),
+ ok = test_double_timeout(),
+ ok = test_reschedule(),
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_wait_timeout() ->
+ receive after 42 -> ok end.
+
+%%--------------------------------------------------------------------
+
+test_double_timeout() ->
+ self() ! foo,
+ self() ! another_foo,
+ receive
+ non_existent -> weird
+ after 0 -> timeout
+ end,
+ receive
+ foo -> ok
+ after 1000 -> timeout
+ end.
+
+%%--------------------------------------------------------------------
+%% Check that RESCHEDULE returns from BIFs work.
+
+test_reschedule() ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ First = self(),
+ Second = spawn(fun() -> doit(First) end),
+ receive
+ Second -> ok
+ end,
+ receive
+ after 42 -> ok
+ end,
+ erts_debug:set_internal_state(hipe_test_reschedule_resume, Second),
+ ok.
+
+doit(First) ->
+ First ! self(),
+ erts_debug:set_internal_state(hipe_test_reschedule_suspend, 1).
+
+%%--------------------------------------------------------------------
diff --git a/lib/hipe/test/basic_SUITE_data/basic_records.erl b/lib/hipe/test/basic_SUITE_data/basic_records.erl
new file mode 100644
index 0000000000..cbb451196c
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_records.erl
@@ -0,0 +1,28 @@
+%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests that manipulate and pattern match against records.
+%%%-------------------------------------------------------------------
+-module(basic_records).
+
+-export([test/0]).
+
+test() ->
+ ok = test_rec1(),
+ ok.
+
+%%--------------------------------------------------------------------
+
+-record(r, {ra}).
+-record(s, {sa, sb, sc, sd}).
+
+test_rec1() ->
+ R = #r{},
+ S = #s{},
+ S1 = S#s{sc=R, sd=1},
+ R1 = S1#s.sc,
+ undefined = R1#r.ra,
+ ok.
+
+%%--------------------------------------------------------------------
diff --git a/lib/hipe/test/basic_SUITE_data/basic_strength_reduce.erl b/lib/hipe/test/basic_SUITE_data/basic_strength_reduce.erl
new file mode 100644
index 0000000000..0f94320a33
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_strength_reduce.erl
@@ -0,0 +1,65 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Tests the strength reduction component of the HiPE compiler.
+%%%-------------------------------------------------------------------
+-module(basic_strength_reduce).
+
+-export([test/0]).
+%% These functions are exported so as to not remove them by inlining
+-export([crash_0/1, crash_1/1, crash_2/1, crash_3/1, bug_div_2N/1]).
+
+test() ->
+ ok = test_strength_reduce1(),
+ ok.
+
+%%--------------------------------------------------------------------
+
+test_strength_reduce1() ->
+ ok = crash_0(0),
+ ok = crash_1(42),
+ ok = crash_2(42),
+ ok = crash_3(42),
+ 5 = 42 bsr 3 = bug_div_2N(42),
+ -6 = -42 bsr 3 = bug_div_2N(-42) - 1,
+ ok.
+
+%% This is a crash report by Peter Wang (10 July 2007) triggering an
+%% R11B-5 crash: strength reduction could not handle calls with no
+%% destination
+crash_0(A) ->
+ case A of
+ 0 ->
+ A div 8,
+ ok
+ end.
+
+%% The above was simplified to the following which showed another
+%% crash, this time on RTL
+crash_1(A) when is_integer(A), A >= 0 ->
+ A div 8,
+ ok.
+
+%% A similar crash like the first one, but in a different place in the
+%% code, was triggered by the following code
+crash_2(A) when is_integer(A), A >= 0 ->
+ A div 1,
+ ok.
+
+%% A crash similar to the first one happened in the following code
+crash_3(A) ->
+ case A of
+ 42 ->
+ A * 0,
+ ok
+ end.
+
+%% Strength reduction for div/2 and rem/2 with a power of 2
+%% should be performed only for non-negative integers
+bug_div_2N(X) when is_integer(X), X >= 0 ->
+ X div 8;
+bug_div_2N(X) when is_integer(X), X < 0 ->
+ X div 8.
+
+%%--------------------------------------------------------------------
diff --git a/lib/hipe/test/basic_SUITE_data/basic_switches.erl b/lib/hipe/test/basic_SUITE_data/basic_switches.erl
new file mode 100644
index 0000000000..0a7ae5b8b7
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_switches.erl
@@ -0,0 +1,52 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests for pattern matching switches.
+%%%-------------------------------------------------------------------
+-module(basic_switches).
+
+-export([test/0]).
+
+test() ->
+ ok = test_switch_mix(),
+ ok.
+
+%%---------------------------------------------------------------------
+
+-define(BIG1, 21323233222132323322).
+-define(BIG2, 4242424242424242424242424242424242).
+
+test_switch_mix() ->
+ small1 = t(42),
+ small2 = t(17),
+ big1 = t(?BIG1),
+ big2 = t(?BIG2),
+ atom = t(foo),
+ pid = t(self()),
+ float = t(4.2),
+ ok.
+
+t(V) ->
+ S = self(),
+ case V of
+ 42 -> small1;
+ 17 -> small2;
+ ?BIG1 -> big1;
+ ?BIG2 -> big2;
+ 1 -> no;
+ 2 -> no;
+ 3 -> no;
+ 4 -> no;
+ 5 -> no;
+ 6 -> no;
+ 7 -> no;
+ 8 -> no;
+ foo -> atom;
+ 9 -> no;
+ 4.2 -> float;
+ S -> pid;
+ _ -> no
+ end.
+
+%%---------------------------------------------------------------------
diff --git a/lib/hipe/test/basic_SUITE_data/basic_tail_rec.erl b/lib/hipe/test/basic_SUITE_data/basic_tail_rec.erl
new file mode 100644
index 0000000000..0124f13df6
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_tail_rec.erl
@@ -0,0 +1,39 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests that check that tail recursion optimization occurs.
+%%%-------------------------------------------------------------------
+-module(basic_tail_rec).
+
+-export([test/0]).
+-export([app0/2]). %% used in an apply/3 call
+
+test() ->
+ ok = test_app_tail(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Written by Mikael Pettersson: check that apply is tail recursive.
+
+%% Increased the following quantity from 20 to 30 so that the test
+%% remains valid even with the naive register allocator. - Kostis
+-define(SIZE_INCREASE, 30).
+
+test_app_tail() ->
+ Inc = start(400),
+ %% io:format("Inc ~w\n", [Inc]),
+ case Inc > ?SIZE_INCREASE of
+ true ->
+ {error, "apply/3 is not tail recursive in native code"};
+ false ->
+ ok
+ end.
+
+start(N) ->
+ app0(N, hipe_bifs:nstack_used_size()).
+
+app0(0, Size0) ->
+ hipe_bifs:nstack_used_size() - Size0;
+app0(N, Size) ->
+ apply(?MODULE, app0, [N-1, Size]).
diff --git a/lib/hipe/test/basic_SUITE_data/basic_tuples.erl b/lib/hipe/test/basic_SUITE_data/basic_tuples.erl
new file mode 100644
index 0000000000..94c187e364
--- /dev/null
+++ b/lib/hipe/test/basic_SUITE_data/basic_tuples.erl
@@ -0,0 +1,177 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Contains tests that manipulate and pattern match against tuples.
+%%%-------------------------------------------------------------------
+-module(basic_tuples).
+
+-export([test/0]).
+
+test() ->
+ Num = 4711,
+ ok = test_match({}, {1}, {1,2}, {1,2,3}, {1,2,3,4}, {1,2,3,4,5},
+ {1,2,3,4,5,6}, {1,2,3,4,5,6,7}, {1,2,3,4,5,6,7,8}),
+ ok = test_size({}, {a}, {{a},{b}}, {a,{b},c}),
+ ok = test_element({}, {a}, {a,b}, Num),
+ ok = test_setelement({}, {1}, {1,2}, 3, [1,2]),
+ ok = test_tuple_to_list({}, {a}, {a,b}, {a,b,c}, {a,b,c,d}, Num),
+ ok = test_list_to_tuple([], [a], [a,b], [a,b,c], [a,b,c,d], Num),
+ ok = test_tuple_with_case(),
+ ok = test_tuple_in_guard({a, b}, {a, b, c}),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Tests matching of tuples
+
+test_match(T0, T1, T2, T3, T4, T5, T6, T7, T8) ->
+ {} = T0,
+ {1} = T1,
+ {1, 2} = T2,
+ {1, 2, 3} = T3,
+ {1, 2, 3, 4} = T4,
+ {1, 2, 3, 4, 5} = T5,
+ {1, 2, 3, 4, 5, 6} = T6,
+ T6 = {1, 2, 3, 4, 5, 6},
+ T7 = {1, 2, 3, 4, 5, 6, 7},
+ {1, 2, 3, 4, 5, 6, 7, 8} = T8,
+ ok.
+
+%%--------------------------------------------------------------------
+%% Tests the size/1 and tuple_size/1 BIFs.
+
+test_size(T0, T1, T2, T3) ->
+ [0, 1, 2, 3] = [size(T) || T <- [T0, T1, T2, T3]],
+ [0, 1, 2, 3] = [tuple_size(T) || T <- [T0, T1, T2, T3]],
+ ok.
+
+%%--------------------------------------------------------------------
+%% Tests element/2.
+
+test_element(T0, T1, T2, N) ->
+ a = element(1, T1),
+ a = element(1, T2),
+ %% indirect calls to element/2
+ List = lists:seq(1, N),
+ Tuple = list_to_tuple(List),
+ ok = get_elements(List, Tuple, 1),
+ %% some cases that throw exceptions
+ {'EXIT', _} = (catch my_element(0, T2)),
+ {'EXIT', _} = (catch my_element(3, T2)),
+ {'EXIT', _} = (catch my_element(1, T0)),
+ {'EXIT', _} = (catch my_element(1, List)),
+ {'EXIT', _} = (catch my_element(1, N)),
+ {'EXIT', _} = (catch my_element(1.5, T2)),
+ ok.
+
+my_element(Pos, Term) ->
+ element(Pos, Term).
+
+get_elements([Element|Rest], Tuple, Pos) ->
+ Element = element(Pos, Tuple),
+ get_elements(Rest, Tuple, Pos + 1);
+get_elements([], _Tuple, _Pos) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Tests set_element/3.
+
+test_setelement(T0, T1, Pair, Three, L) ->
+ {x} = setelement(1, T1, x),
+ {x, 2} = setelement(1, Pair, x),
+ {1, x} = setelement(2, Pair, x),
+ %% indirect calls to setelement/3
+ Tuple = list_to_tuple(lists:duplicate(2048, x)),
+ NewTuple = set_all_elements(Tuple, 1),
+ NewTuple = list_to_tuple(lists:seq(1+7, 2048+7)),
+ %% the following cases were rewritten to use the Three
+ %% variable in this weird way so as to silence the compiler
+ {'EXIT', _} = (catch setelement(Three - Three, Pair, x)),
+ {'EXIT', _} = (catch setelement(Three, Pair, x)),
+ {'EXIT', _} = (catch setelement(Three div Three, T0, x)),
+ {'EXIT', _} = (catch setelement(Three div Three, L, x)),
+ {'EXIT', _} = (catch setelement(Three / 2, Pair, x)),
+ ok.
+
+set_all_elements(Tuple, Pos) when Pos =< tuple_size(Tuple) ->
+ set_all_elements(setelement(Pos, Tuple, Pos+7), Pos+1);
+set_all_elements(Tuple, Pos) when Pos > tuple_size(Tuple) ->
+ Tuple.
+
+%%--------------------------------------------------------------------
+%% Tests tuple_to_list/1.
+
+test_tuple_to_list(T0, T1, T2, T3, T4, Size) ->
+ [] = tuple_to_list(T0),
+ [a] = tuple_to_list(T1),
+ [a, b] = tuple_to_list(T2),
+ [a, b, c] = tuple_to_list(T3),
+ [a, b, c, d] = tuple_to_list(T4),
+ [a, b, c, d] = tuple_to_list(T4),
+ %% test a big tuple
+ List = lists:seq(1, Size),
+ Tuple = list_to_tuple(List),
+ Size = tuple_size(Tuple),
+ List = tuple_to_list(Tuple),
+ %% some cases that should result in errors
+ {'EXIT', _} = (catch my_tuple_to_list(element(2, T3))),
+ {'EXIT', _} = (catch my_tuple_to_list(Size)),
+ ok.
+
+my_tuple_to_list(X) ->
+ tuple_to_list(X).
+
+%%--------------------------------------------------------------------
+%% Tests list_to_tuple/1.
+
+test_list_to_tuple(L0, L1, L2, L3, L4, Size) ->
+ {} = list_to_tuple(L0),
+ {a} = list_to_tuple(L1),
+ {a, b} = list_to_tuple(L2),
+ {a, b, c} = list_to_tuple(L3),
+ {a, b, c, d} = list_to_tuple(L4),
+ {a, b, c, d, e} = list_to_tuple(L4++[e]),
+ %% test list_to_tuple with a big list
+ Tuple = list_to_tuple(lists:seq(1, Size)),
+ Size = tuple_size(Tuple),
+ %% some cases that should result in errors
+ {'EXIT', _} = (catch my_list_to_tuple({a,b})),
+ {'EXIT', _} = (catch my_list_to_tuple([hd(L1)|hd(L2)])),
+ ok.
+
+my_list_to_tuple(X) ->
+ list_to_tuple(X).
+
+%%--------------------------------------------------------------------
+%% Tests that a case nested inside a tuple is ok.
+%% (This was known to crash earlier versions of BEAM.)
+
+test_tuple_with_case() ->
+ {reply, true} = tuple_with_case(),
+ ok.
+
+tuple_with_case() ->
+ %% The following comments apply to the BEAM compiler.
+ void(), % Reset var count.
+ {reply, % Compiler will choose {x,1} for tuple.
+ case void() of % Call will reset var count.
+ {'EXIT', Reason} -> % Case will return in {x,1} (first free),
+ {error, Reason}; % but the tuple will be build in {x,1},
+ _ -> % so case value is lost and a circular
+ true % data element is built.
+ end}.
+
+void() -> ok.
+
+%%--------------------------------------------------------------------
+%% Test to build a tuple in a guard.
+
+test_tuple_in_guard(T2, T3) ->
+ %% T2 = {a, b}; T3 = {a, b, c}
+ ok = if T2 == {element(1, T3), element(2, T3)} -> ok;
+ true -> other
+ end,
+ ok = if T3 == {element(1, T3), element(2, T3), element(3, T3)} -> ok;
+ true -> other
+ end,
+ ok.
diff --git a/lib/hipe/test/bs_SUITE_data/bs_add.erl b/lib/hipe/test/bs_SUITE_data/bs_add.erl
index af5a3b2f23..4b92e6b413 100644
--- a/lib/hipe/test/bs_SUITE_data/bs_add.erl
+++ b/lib/hipe/test/bs_SUITE_data/bs_add.erl
@@ -2,7 +2,7 @@
%%-------------------------------------------------------------------------
%% The guard in f/3 revealed a problem in the translation of the 'bs_add'
%% BEAM instruction to Icode. The fail label was not properly translated.
-%% Fixed 3/2/2011.
+%% Fixed 3/2/2011. Then in 2015 we found another issue: g/2. Also fixed.
%%-------------------------------------------------------------------------
-module(bs_add).
@@ -10,9 +10,17 @@
test() ->
42 = f(<<12345:16>>, 4711, <<42>>),
+ true = g(<<1:13>>, 3), %% was handled OK, but
+ false = g(<<>>, gurka), %% this one leaked badarith
ok.
f(Bin, A, B) when <<A:9, B:7/binary>> == Bin ->
gazonk;
f(Bin, _, _) when is_binary(Bin) ->
42.
+
+%% Complex way of testing (bit_size(Bin) + Len) rem 8 =:= 0
+g(Bin, Len) when is_binary(<<Bin/binary-unit:1, 123:Len>>) ->
+ true;
+g(_, _) ->
+ false.
diff --git a/lib/hipe/test/bs_SUITE_data/bs_construct.erl b/lib/hipe/test/bs_SUITE_data/bs_construct.erl
index 9cc9ac848c..b9e7d93570 100644
--- a/lib/hipe/test/bs_SUITE_data/bs_construct.erl
+++ b/lib/hipe/test/bs_SUITE_data/bs_construct.erl
@@ -13,6 +13,12 @@ test() ->
ok = bs5(),
16#10000008 = bit_size(large_bin(1, 2, 3, 4)),
ok = bad_ones(),
+ ok = zero_width(),
+ ok = not_used(),
+ ok = bad_append(),
+ ok = system_limit(),
+ ok = bad_floats(),
+ ok = huge_binaries(),
ok.
%%--------------------------------------------------------------------
@@ -126,3 +132,174 @@ bad_ones() ->
Bin123 = <<1,2,3>>,
?FAIL(<<Bin123/float>>),
ok.
+
+%%--------------------------------------------------------------------
+%% Taken from the emulator bs_construct_SUITE - seg faulted till 18.1
+
+zero_width() ->
+ Z = id(0),
+ Small = id(42),
+ Big = id(1 bsl 128), % puts stuff on the heap
+ <<>> = <<Small:Z>>,
+ <<>> = <<Small:0>>,
+ <<>> = <<Big:Z>>,
+ <<>> = <<Big:0>>,
+ ok.
+
+id(X) -> X.
+
+%%--------------------------------------------------------------------
+%% Taken from bs_construct_SUITE. The test checks that constructed
+%% binaries that are not used would still give a `badarg' exception.
+%% Problem was that in native code one of them gave `badarith'.
+
+not_used() ->
+ ok = not_used1(3, <<"dum">>),
+ {'EXIT',{badarg,_}} = (catch not_used1(42, "dum_string")),
+ {'EXIT',{badarg,_}} = (catch not_used2(666, -2)),
+ {'EXIT',{badarg,_}} = (catch not_used2(666, "bad_size")), % this one
+ {'EXIT',{badarg,_}} = (catch not_used3(666)),
+ ok.
+
+not_used1(I, BinString) ->
+ <<I:32,BinString/binary>>,
+ ok.
+
+not_used2(I, Sz) ->
+ <<I:Sz>>,
+ ok.
+
+not_used3(I) ->
+ <<I:(-8)>>,
+ ok.
+
+%%--------------------------------------------------------------------
+%% Taken from bs_construct_SUITE.
+
+bad_append() ->
+ do_bad_append(<<127:1>>, fun append_unit_3/1),
+ do_bad_append(<<127:2>>, fun append_unit_3/1),
+ do_bad_append(<<127:17>>, fun append_unit_3/1),
+
+ do_bad_append(<<127:3>>, fun append_unit_4/1),
+ do_bad_append(<<127:5>>, fun append_unit_4/1),
+ do_bad_append(<<127:7>>, fun append_unit_4/1),
+ do_bad_append(<<127:199>>, fun append_unit_4/1),
+
+ do_bad_append(<<127:7>>, fun append_unit_8/1),
+ do_bad_append(<<127:9>>, fun append_unit_8/1),
+
+ do_bad_append(<<0:8>>, fun append_unit_16/1),
+ do_bad_append(<<0:15>>, fun append_unit_16/1),
+ do_bad_append(<<0:17>>, fun append_unit_16/1),
+ ok.
+
+do_bad_append(Bin0, Appender) ->
+ {'EXIT',{badarg,_}} = (catch Appender(Bin0)),
+
+ Bin1 = id(<<0:3,Bin0/bitstring>>),
+ <<_:3,Bin2/bitstring>> = Bin1,
+ {'EXIT',{badarg,_}} = (catch Appender(Bin2)),
+
+ %% Create a writable binary.
+ Empty = id(<<>>),
+ Bin3 = <<Empty/bitstring,Bin0/bitstring>>,
+ {'EXIT',{badarg,_}} = (catch Appender(Bin3)),
+ ok.
+
+append_unit_3(Bin) ->
+ <<Bin/binary-unit:3,0:1>>.
+
+append_unit_4(Bin) ->
+ <<Bin/binary-unit:4,0:1>>.
+
+append_unit_8(Bin) ->
+ <<Bin/binary,0:1>>.
+
+append_unit_16(Bin) ->
+ <<Bin/binary-unit:16,0:1>>.
+
+%%--------------------------------------------------------------------
+%% Taken from bs_construct_SUITE.
+
+system_limit() ->
+ WordSize = erlang:system_info(wordsize),
+ BitsPerWord = WordSize * 8,
+ {'EXIT',{system_limit,_}} =
+ (catch <<0:(id(0)),42:(id(1 bsl BitsPerWord))>>),
+ {'EXIT',{system_limit,_}} =
+ (catch <<42:(id(1 bsl BitsPerWord)),0:(id(0))>>),
+ {'EXIT',{system_limit,_}} =
+ (catch <<(id(<<>>))/binary,0:(id(1 bsl 100))>>),
+
+ %% Would fail to load.
+ {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 67)>>),
+ {'EXIT',{system_limit,_}} = (catch <<0:((1 bsl 64)+1)>>),
+ case WordSize of
+ 4 ->
+ system_limit_32();
+ 8 ->
+ ok
+ end.
+
+system_limit_32() ->
+ {'EXIT',{badarg,_}} = (catch <<42:(-1)>>),
+ {'EXIT',{badarg,_}} = (catch <<42:(id(-1))>>),
+ {'EXIT',{badarg,_}} = (catch <<42:(id(-389739873536870912))/unit:8>>),
+ {'EXIT',{system_limit,_}} = (catch <<42:536870912/unit:8>>),
+ {'EXIT',{system_limit,_}} = (catch <<42:(id(536870912))/unit:8>>),
+ {'EXIT',{system_limit,_}} = (catch <<0:(id(8)),42:536870912/unit:8>>),
+ {'EXIT',{system_limit,_}} = (catch <<0:(id(8)),42:(id(536870912))/unit:8>>),
+
+ %% The size would be silently truncated, resulting in a crash.
+ {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 35)>>),
+ {'EXIT',{system_limit,_}} = (catch <<0:((1 bsl 32)+1)>>),
+
+ %% Would fail to load.
+ {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 43)>>),
+ {'EXIT',{system_limit,_}} = (catch <<0:((1 bsl 40)+1)>>),
+ ok.
+
+%%--------------------------------------------------------------------
+
+bad_floats() ->
+ WordSize = erlang:system_info(wordsize),
+ BitsPerWord = WordSize * 8,
+ {'EXIT',{badarg,_}} = (catch <<3.14:(id(33))/float>>),
+ {'EXIT',{badarg,_}} = (catch <<3.14:(id(64 bor 32))/float>>),
+ {'EXIT',{badarg,_}} = (catch <<3.14:(id((1 bsl 28) bor 32))/float>>),
+ {'EXIT',{system_limit,_}} = (catch <<3.14:(id(1 bsl BitsPerWord))/float>>),
+ ok.
+
+%%--------------------------------------------------------------------
+%% A bug in the implementation of binaries compared sizes in bits with sizes in
+%% bytes, causing <<0:(id((1 bsl 31)-1))>> to fail to construct with
+%% 'system_limit'.
+%% <<0:(id((1 bsl 32)-1))>> was succeeding because the comparison was
+%% (incorrectly) signed.
+
+huge_binaries() ->
+ AlmostIllegal = id(<<0:(id((1 bsl 32)-8))>>),
+ case erlang:system_info(wordsize) of
+ 4 -> huge_binaries_32(AlmostIllegal);
+ 8 -> ok
+ end,
+ garbage_collect(),
+ id(<<0:(id((1 bsl 31)-1))>>),
+ id(<<0:(id((1 bsl 30)-1))>>),
+ garbage_collect(),
+ ok.
+
+huge_binaries_32(AlmostIllegal) ->
+ %% Attempt construction of too large binary using bs_init/1 (which takes the
+ %% number of bytes as an argument, which should be compared to the maximum
+ %% size in bytes).
+ {'EXIT',{system_limit,_}} = (catch <<0:32,AlmostIllegal/binary>>),
+ %% Attempt construction of too large binary using bs_init/1 with a size in
+ %% bytes that has the msb set (and would be negative if it was signed).
+ {'EXIT',{system_limit,_}} =
+ (catch <<0:8, AlmostIllegal/binary, AlmostIllegal/binary,
+ AlmostIllegal/binary, AlmostIllegal/binary,
+ AlmostIllegal/binary, AlmostIllegal/binary,
+ AlmostIllegal/binary, AlmostIllegal/binary>>),
+ ok.
diff --git a/lib/hipe/test/bs_SUITE_data/bs_match.erl b/lib/hipe/test/bs_SUITE_data/bs_match.erl
index 8194d878b8..b241ea8d35 100644
--- a/lib/hipe/test/bs_SUITE_data/bs_match.erl
+++ b/lib/hipe/test/bs_SUITE_data/bs_match.erl
@@ -1,8 +1,8 @@
%%% -*- erlang-indent-level: 2 -*-
%%%-------------------------------------------------------------------
%%% File : bs_match.erl
-%%% Author : Per Gustafsson <[email protected]>
-%%% Purpose : Performs simple matching and construction of binaries
+%%% Authors : Per Gustafsson <[email protected]>, Kostis Sagonas <[email protected]>
+%%% Purpose : Tests matching and construction of binaries
%%% TODO : Add binary and float tests
%%% Created : 20 Feb 2004
%%%-------------------------------------------------------------------
@@ -12,7 +12,8 @@
test() ->
Funs = [fun test_aligned/0, fun test_unaligned/0,
- fun test_zero_tail/0, fun test_integer_matching/0],
+ fun test_zero_tail/0, fun test_integer_matching/0,
+ fun test_writable_bin/0, fun test_match_huge_bin/0],
lists:foreach(fun (F) -> ok = F() end, Funs).
%%-------------------------------------------------------------------
@@ -173,3 +174,116 @@ test_dynamic_integer_matching(N) ->
<<12:N/integer, 0:S>> = <<12:N/integer, 0:S>>,
<<12:N/integer-little, 0:S>> = <<12:N/integer-little, 0:S>>,
ok.
+
+%%-------------------------------------------------------------------
+%% Test writable bin -- added by Sverker Eriksson
+
+test_writable_bin() ->
+ test_writable_bin(<<>>, 0),
+ ok.
+
+test_writable_bin(Bin, 128) ->
+ Bin;
+test_writable_bin(Bin0, N) when N < 128 ->
+ Bin1 = <<Bin0/binary, N>>,
+ <<_/utf8, _/binary>> = Bin1,
+ test_writable_bin(Bin1, N+1).
+
+%%-------------------------------------------------------------------
+%% Test matching with a huge bin -- taken from bs_match_bin_SUITE
+
+test_match_huge_bin() ->
+ Bin = <<0:(1 bsl 27),13:8>>,
+ skip_huge_bin_1(1 bsl 27, Bin),
+ 16777216 = match_huge_bin_1(1 bsl 27, Bin),
+ %% Test overflowing the size of a binary field.
+ nomatch = overflow_huge_bin_skip_32(Bin),
+ nomatch = overflow_huge_bin_32(Bin),
+ nomatch = overflow_huge_bin_skip_64(Bin),
+ nomatch = overflow_huge_bin_64(Bin),
+ %% Size in variable
+ ok = overflow_huge_bin(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ok = overflow_huge_bin_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ok.
+
+overflow_huge_bin(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/binary-unit:8,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<NewBin:Sz/binary-unit:8,0,_/binary>> ->
+ {error,Sz,size(NewBin)};
+ _ ->
+ overflow_huge_bin(Bin, Sizes)
+ end
+ end;
+overflow_huge_bin(_, []) -> ok.
+
+overflow_huge_bin_unit128(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/binary-unit:128,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<NewBin:Sz/binary-unit:128,0,_/binary>> ->
+ {error,Sz,size(NewBin)};
+ _ ->
+ overflow_huge_bin_unit128(Bin, Sizes)
+ end
+ end;
+overflow_huge_bin_unit128(_, []) -> ok.
+
+skip_huge_bin_1(I, Bin) ->
+ <<_:I/binary-unit:1,13>> = Bin,
+ ok.
+
+match_huge_bin_1(I, Bin) ->
+ case Bin of
+ <<Val:I/binary-unit:1,13>> -> size(Val);
+ _ -> nomatch
+ end.
+
+overflow_huge_bin_skip_32(<<_:4294967296/binary,0,_/binary>>) -> 1; % 1 bsl 32
+overflow_huge_bin_skip_32(<<_:33554432/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 25
+overflow_huge_bin_skip_32(<<_:67108864/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 26
+overflow_huge_bin_skip_32(<<_:134217728/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 27
+overflow_huge_bin_skip_32(<<_:268435456/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 28
+overflow_huge_bin_skip_32(<<_:536870912/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 29
+overflow_huge_bin_skip_32(<<_:1073741824/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 30
+overflow_huge_bin_skip_32(<<_:2147483648/binary-unit:8,0,_/binary>>) -> 8; % 1 bsl 31
+overflow_huge_bin_skip_32(_) -> nomatch.
+
+overflow_huge_bin_32(<<Bin:4294967296/binary,_/binary>>) -> {1,Bin}; % 1 bsl 32
+overflow_huge_bin_32(<<Bin:33554432/binary-unit:128,0,_/binary>>) -> {2,Bin}; % 1 bsl 25
+overflow_huge_bin_32(<<Bin:67108864/binary-unit:128,0,_/binary>>) -> {3,Bin}; % 1 bsl 26
+overflow_huge_bin_32(<<Bin:134217728/binary-unit:128,0,_/binary>>) -> {4,Bin}; % 1 bsl 27
+overflow_huge_bin_32(<<Bin:268435456/binary-unit:128,0,_/binary>>) -> {5,Bin}; % 1 bsl 28
+overflow_huge_bin_32(<<Bin:536870912/binary-unit:128,0,_/binary>>) -> {6,Bin}; % 1 bsl 29
+overflow_huge_bin_32(<<Bin:1073741824/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 30
+overflow_huge_bin_32(<<Bin:2147483648/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 31
+overflow_huge_bin_32(_) -> nomatch.
+
+overflow_huge_bin_skip_64(<<_:18446744073709551616/binary,0,_/binary>>) -> 1; % 1 bsl 64
+overflow_huge_bin_skip_64(<<_:144115188075855872/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 57
+overflow_huge_bin_skip_64(<<_:288230376151711744/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 58
+overflow_huge_bin_skip_64(<<_:576460752303423488/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 59
+overflow_huge_bin_skip_64(<<_:1152921504606846976/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 60
+overflow_huge_bin_skip_64(<<_:2305843009213693952/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 61
+overflow_huge_bin_skip_64(<<_:4611686018427387904/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 62
+overflow_huge_bin_skip_64(<<_:9223372036854775808/binary-unit:8,_/binary>>) -> 8; % 1 bsl 63
+overflow_huge_bin_skip_64(_) -> nomatch.
+
+overflow_huge_bin_64(<<Bin:18446744073709551616/binary,_/binary>>) -> {1,Bin}; % 1 bsl 64
+overflow_huge_bin_64(<<Bin:144115188075855872/binary-unit:128,0,_/binary>>) -> {2,Bin}; % 1 bsl 57
+overflow_huge_bin_64(<<Bin:288230376151711744/binary-unit:128,0,_/binary>>) -> {3,Bin}; % 1 bsl 58
+overflow_huge_bin_64(<<Bin:576460752303423488/binary-unit:128,0,_/binary>>) -> {4,Bin}; % 1 bsl 59
+overflow_huge_bin_64(<<Bin:1152921504606846976/binary-unit:128,0,_/binary>>) -> {5,Bin}; % 1 bsl 60
+overflow_huge_bin_64(<<Bin:2305843009213693952/binary-unit:128,0,_/binary>>) -> {6,Bin}; % 1 bsl 61
+overflow_huge_bin_64(<<Bin:4611686018427387904/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 62
+overflow_huge_bin_64(<<Bin:9223372036854775808/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 63
+overflow_huge_bin_64(_) -> nomatch.
+
+id(I) -> I.
diff --git a/lib/hipe/test/bs_SUITE_data/bs_match_compiler.erl b/lib/hipe/test/bs_SUITE_data/bs_match_compiler.erl
new file mode 100644
index 0000000000..4cb48ff57e
--- /dev/null
+++ b/lib/hipe/test/bs_SUITE_data/bs_match_compiler.erl
@@ -0,0 +1,1235 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%-------------------------------------------------------------------
+%%% File : bs_match_compiler.erl
+%%%
+%%%-------------------------------------------------------------------
+-module(bs_match_compiler).
+-compile(nowarn_shadow_vars).
+
+-export([test/0]).
+-export([exported_id/1, exported_id/2]). %% needed by a test
+
+test() ->
+ Funs = [fun fun_shadow/0, fun int_float/0, fun otp_5269/0, fun null_fields/0,
+ fun wiger/0, fun bin_tail/0, fun save_restore/0,
+ fun partitioned_bs_match/0, fun function_clause/0, fun unit/0,
+ fun shared_sub_bins/0, fun bin_and_float/0, fun dec_subidentifiers/0,
+ fun skip_optional_tag/0, fun wfbm/0, fun degenerated_match/0,
+ fun bs_sum/0, fun coverage/0, fun multiple_uses/0, fun zero_label/0,
+ fun followed_by_catch/0, fun matching_meets_construction/0,
+ fun simon/0, fun matching_and_andalso/0,
+ fun otp_7188/0, fun otp_7233/0, fun otp_7240/0, fun otp_7498/0,
+ fun match_string/0, fun zero_width/0, fun bad_size/0, fun haystack/0,
+ fun cover_beam_bool/0, fun matched_out_size/0, fun follow_fail_br/0,
+ fun no_partition/0, fun calling_a_binary/0, fun binary_in_map/0,
+ fun match_string_opt/0, fun map_and_binary/0,
+ fun unsafe_branch_caching/0],
+ lists:foreach(fun (F) -> ok = F() end, Funs).
+
+
+%%--------------------------------------------------------------------
+%% OTP-5270
+
+fun_shadow() ->
+ 7 = fun_shadow_1(),
+ 7 = fun_shadow_2(8),
+ 7 = fun_shadow_3(),
+ no = fun_shadow_4(8),
+ ok.
+
+fun_shadow_1() ->
+ L = 8,
+ F = fun(<<L:L,B:L>>) -> B end,
+ F(<<16:8, 7:16>>).
+
+fun_shadow_2(L) ->
+ F = fun(<<L:L,B:L>>) -> B end,
+ F(<<16:8, 7:16>>).
+
+fun_shadow_3() ->
+ L = 8,
+ F = fun(<<L:L,B:L,L:L>>) -> B end,
+ F(<<16:8, 7:16,16:16>>).
+
+fun_shadow_4(L) ->
+ F = fun(<<L:L,B:L,L:L>>) -> B;
+ (_) -> no end,
+ F(<<16:8, 7:16,15:16>>).
+
+%%--------------------------------------------------------------------
+%% OTP-5323
+
+int_float() ->
+ <<103133.0:64/float>> = <<103133:64/float>>,
+ <<103133:64/float>> = <<103133:64/float>>,
+ ok.
+
+%%--------------------------------------------------------------------
+%% Stolen from erl_eval_SUITE and modified.
+%% OTP-5269. Bugs in the bit syntax.
+
+otp_5269() ->
+ check(fun() -> L = 8, F = fun(<<A:L,B:A>>) -> B end, F(<<16:8, 7:16>>) end, 7),
+ check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end, 7),
+ check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end, 32),
+ check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end, [32]),
+ check(fun() -> [X || <<A:8, B:A>> <- [<<16:8,19:16>>],
+ <<X:8>> <- [<<B:8>>]] end,
+ [19]),
+ check(fun() -> A = 4, B = 28, _ = bit_size(<<13:(A+(X=B))>>), X end, 28),
+ check(fun() ->
+ <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>,
+ {Size,B,Rest}
+ end, {2,<<"AB">>,<<"CD">>}),
+ check(fun() -> X = 32, [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end,
+ %% "binsize variable" ^
+ [1,2]),
+ check(fun() ->
+ (fun (<<A:1/binary, B:8/integer, _C:B/binary>>) ->
+ case A of
+ B -> wrong;
+ _ -> ok
+ end
+ end)(<<1,2,3,4>>) end,
+ ok),
+ ok.
+
+%%--------------------------------------------------------------------
+
+null_fields() ->
+ check(fun() ->
+ W = id(0),
+ F = fun(<<_:W>>) -> tail;
+ (<<>>) -> empty
+ end,
+ F(<<>>)
+ end, tail),
+ check(fun() ->
+ F = fun(<<_/binary>>) -> tail;
+ (<<>>) -> empty
+ end,
+ F(<<>>)
+ end, tail),
+ ok.
+
+%%--------------------------------------------------------------------
+
+wiger() ->
+ ok1 = wcheck(<<3>>),
+ ok2 = wcheck(<<1,2,3>>),
+ ok3 = wcheck(<<4>>),
+ {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>),
+ {error,<<>>} = wcheck(<<>>),
+ ok.
+
+wcheck(<<A>>) when A==3->
+ ok1;
+wcheck(<<_,_:2/binary>>) ->
+ ok2;
+wcheck(<<_>>) ->
+ ok3;
+wcheck(Other) ->
+ {error,Other}.
+
+%%--------------------------------------------------------------------
+
+bin_tail() ->
+ S = <<"abcde">>,
+ $a = bin_tail_c(S, 0),
+ $c = bin_tail_c(S, 2),
+ $e = bin_tail_c(S, 4),
+ {'EXIT',_} = (catch bin_tail_c(S, 5)),
+ {'EXIT',_} = (catch bin_tail_c_var(S, 5)),
+
+ $a = bin_tail_d(S, 0),
+ $b = bin_tail_d(S, 8),
+ $d = bin_tail_d(S, 3*8),
+ {'EXIT',_} = (catch bin_tail_d_dead(S, 1)),
+ {'EXIT',_} = (catch bin_tail_d_dead(S, 9)),
+ {'EXIT',_} = (catch bin_tail_d_dead(S, 5*8)),
+ {'EXIT',_} = (catch bin_tail_d_var(S, 1)),
+
+ ok = bin_tail_e(<<2:2,0:1,1:5>>),
+ ok = bin_tail_e(<<2:2,1:1,1:5,42:64>>),
+ error = bin_tail_e(<<3:2,1:1,1:5,42:64>>),
+ error = bin_tail_e(<<>>),
+ ok.
+
+bin_tail_c(Bin, Offset) ->
+ Res = bin_tail_c_dead(Bin, Offset),
+ <<_:Offset/binary,_,Tail/binary>> = Bin,
+ {Res,Tail} = bin_tail_c_var(Bin, Offset),
+ Res.
+
+bin_tail_c_dead(Bin, Offset) ->
+ <<_:Offset/binary,C,_/binary>> = Bin,
+ C.
+
+bin_tail_c_var(Bin, Offset) ->
+ <<_:Offset/binary,C,Tail/binary>> = Bin,
+ {C,Tail}.
+
+bin_tail_d(Bin, BitOffset) ->
+ Res = bin_tail_d_dead(Bin, BitOffset),
+ <<_:BitOffset,_:8,Tail/binary>> = Bin,
+ {Res,Tail} = bin_tail_d_var(Bin, BitOffset),
+ Res.
+
+bin_tail_d_dead(Bin, BitOffset) ->
+ <<_:BitOffset,C,_/binary>> = Bin,
+ C.
+
+bin_tail_d_var(Bin, BitOffset) ->
+ <<_:BitOffset,C,Tail/binary>> = Bin,
+ {C,Tail}.
+
+bin_tail_e(Bin) ->
+ case bin_tail_e_dead(Bin) of
+ ok ->
+ <<_,Tail/binary>> = Bin,
+ Tail = bin_tail_e_var(Bin),
+ ok;
+ error ->
+ bin_tail_e_var(Bin)
+ end.
+
+bin_tail_e_dead(Bin) ->
+ case Bin of
+ %% The binary is aligned at the end; neither the bs_skip_bits2 nor
+ %% bs_test_tail2 instructions are needed.
+ <<2:2,_:1,1:5,_/binary>> -> ok;
+ _ -> error
+ end.
+
+bin_tail_e_var(Bin) ->
+ case Bin of
+ %% The binary is aligned at the end; neither the bs_skip_bits2 nor
+ %% bs_test_tail2 instructions are needed.
+ <<2:2,_:1,1:5,Tail/binary>> -> Tail;
+ _ -> error
+ end.
+
+%%--------------------------------------------------------------------
+
+save_restore() ->
+ 0 = save_restore_1(<<0:2,42:6>>),
+ {1,3456} = save_restore_1(<<1:2,3456:14>>),
+ {2,7981234} = save_restore_1(<<2:2,7981234:30>>),
+ {3,763967493838} = save_restore_1(<<0:2,763967493838:62>>),
+
+ A = <<" x">>,
+ B = <<".x">>,
+ C = <<"-x">>,
+
+ {" ",<<"x">>} = lll(A),
+ {" ",<<"x">>} = mmm(A),
+ {" ",<<"x">>} = nnn(A),
+ {" ",<<"x">>} = ooo(A),
+
+ {".",<<"x">>} = lll(B),
+ {".",<<"x">>} = mmm(B),
+ {".",<<"x">>} = nnn(B),
+ {".",<<"x">>} = ooo(B),
+
+ {"-",<<"x">>} = lll(C),
+ {"-",<<"x">>} = mmm(C),
+ {"-",<<"x">>} = nnn(C),
+ {"-",<<"x">>} = ooo(C),
+
+ Bin = <<-1:64>>,
+ case bad_float_unpack_match(Bin) of
+ -1 -> ok;
+ _Other -> bad_return_value_probably_NaN
+ end.
+
+save_restore_1(Bin) ->
+ case Bin of
+ <<0:2,_:6>> -> 0;
+ <<1:2,A:14>> -> {1,A};
+ <<2:2,A:30>> -> {2,A};
+ <<A:64>> -> {3,A}
+ end.
+
+lll(<<Char, Tail/binary>>) -> {[Char],Tail}.
+
+mmm(<<$.,$.,$., Tail/binary>>) -> Tail;
+mmm(<<$\s,$-,$\s, Tail/binary>>) -> Tail;
+mmm(<<Char, Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail!
+
+nnn(<<"...", Tail/binary>>) -> Tail;
+nnn(<<" - ", Tail/binary>>) -> Tail;
+nnn(<<Char, Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail!
+
+ooo(<<" - ", Tail/binary>>) -> Tail;
+ooo(<<Char, Tail/binary>>) -> {[Char],Tail}.
+
+bad_float_unpack_match(<<F:64/float>>) -> F;
+bad_float_unpack_match(<<I:64/integer-signed>>) -> I.
+
+%%--------------------------------------------------------------------
+
+partitioned_bs_match() ->
+ <<1,2,3>> = partitioned_bs_match(blurf, <<42,1,2,3>>),
+ error = partitioned_bs_match(10, <<7,8,15,13>>),
+ error = partitioned_bs_match(100, {a,tuple,is,'not',a,binary}),
+ ok = partitioned_bs_match(0, <<>>),
+ fc(partitioned_bs_match, [-1,blurf],
+ catch partitioned_bs_match(-1, blurf)),
+ fc(partitioned_bs_match, [-1,<<1,2,3>>],
+ catch partitioned_bs_match(-1, <<1,2,3>>)),
+ {17,<<1,2,3>>} = partitioned_bs_match_2(1, <<17,1,2,3>>),
+ {7,<<1,2,3>>} = partitioned_bs_match_2(7, <<17,1,2,3>>),
+
+ fc(partitioned_bs_match_2, [4,<<0:17>>],
+ catch partitioned_bs_match_2(4, <<0:17>>)),
+
+ anything = partitioned_bs_match_3(anything, <<42>>),
+ ok = partitioned_bs_match_3(1, 2),
+ ok.
+
+partitioned_bs_match(_, <<42:8,T/binary>>) -> T;
+partitioned_bs_match(N, _) when N > 0 -> error;
+partitioned_bs_match(_, <<>>) -> ok.
+
+partitioned_bs_match_2(1, <<B:8,T/binary>>) -> {B,T};
+partitioned_bs_match_2(Len, <<_:8,T/binary>>) -> {Len,T}.
+
+partitioned_bs_match_3(Var, <<_>>) -> Var;
+partitioned_bs_match_3(1, 2) -> ok.
+
+%%--------------------------------------------------------------------
+
+function_clause() ->
+ ok = function_clause_1(<<0,7,0,7,42>>),
+ fc(function_clause_1, [<<0,1,2,3>>],
+ catch function_clause_1(<<0,1,2,3>>)),
+ fc(function_clause_1, [<<0,1,2,3>>],
+ catch function_clause_1(<<0,7,0,1,2,3>>)),
+
+ ok = function_clause_2(<<0,7,0,7,42>>),
+ ok = function_clause_2(<<255>>),
+ ok = function_clause_2(<<13:4>>),
+ fc(function_clause_2, [<<0,1,2,3>>],
+ catch function_clause_2(<<0,1,2,3>>)),
+ fc(function_clause_2, [<<0,1,2,3>>],
+ catch function_clause_2(<<0,7,0,1,2,3>>)),
+ ok.
+
+function_clause_1(<<0:8,7:8,T/binary>>) ->
+ function_clause_1(T);
+function_clause_1(<<_:8>>) ->
+ ok.
+
+function_clause_2(<<0:8,7:8,T/binary>>) ->
+ function_clause_2(T);
+function_clause_2(<<_:8>>) ->
+ ok;
+function_clause_2(<<_:4>>) ->
+ ok.
+
+%%--------------------------------------------------------------------
+
+unit() ->
+ 42 = peek1(<<42>>),
+ 43 = peek1(<<43,1,2>>),
+ 43 = peek1(<<43,1,2,(-1):1>>),
+ 43 = peek1(<<43,1,2,(-1):2>>),
+ 43 = peek1(<<43,1,2,(-1):7>>),
+
+ 99 = peek8(<<99>>),
+ 100 = peek8(<<100,101>>),
+ fc(peek8, [<<100,101,0:1>>], catch peek8(<<100,101,0:1>>)),
+
+ 37484 = peek16(<<37484:16>>),
+ 37489 = peek16(<<37489:16,5566:16>>),
+ fc(peek16, [<<8>>], catch peek16(<<8>>)),
+ fc(peek16, [<<42:15>>], catch peek16(<<42:15>>)),
+ fc(peek16, [<<1,2,3,4,5>>], catch peek16(<<1,2,3,4,5>>)),
+
+ 127 = peek7(<<127:7>>),
+ 100 = peek7(<<100:7,19:7>>),
+ fc(peek7, [<<1,2>>], catch peek7(<<1,2>>)),
+ ok.
+
+peek1(<<B:8,_/bitstring>>) -> B.
+
+peek7(<<B:7,_/binary-unit:7>>) -> B.
+
+peek8(<<B:8,_/binary>>) -> B.
+
+peek16(<<B:16,_/binary-unit:16>>) -> B.
+
+%%--------------------------------------------------------------------
+
+shared_sub_bins() ->
+ {15,[<<>>,<<5>>,<<4,5>>,<<3,4,5>>,<<2,3,4,5>>]} = sum(<<1,2,3,4,5>>, [], 0),
+ ok.
+
+sum(<<B,T/binary>>, Acc, Sum) ->
+ sum(T, [T|Acc], Sum+B);
+sum(<<>>, Last, Sum) -> {Sum,Last}.
+
+%%--------------------------------------------------------------------
+
+bin_and_float() ->
+ 14.0 = bin_and_float(<<1.0/float,2.0/float,3.0/float>>, 0.0),
+ ok.
+
+bin_and_float(<<X/float,Y/float,Z/float,T/binary>>, Sum) when is_float(X),
+ is_float(Y),
+ is_float(Z) ->
+ bin_and_float(T, Sum+X*X+Y*Y+Z*Z);
+bin_and_float(<<>>, Sum) -> Sum.
+
+%%--------------------------------------------------------------------
+
+dec_subidentifiers() ->
+ {[],<<1,2,3>>} =
+ do_dec_subidentifiers(<<1:1,42:7,1:1,99:7,1,2,3>>, 0, [], 2),
+ {[5389],<<1,2,3>>} =
+ do_dec_subidentifiers(<<1:1,42:7,0:1,13:7,1,2,3>>, 0, [], 2),
+ {[3,2,1],not_a_binary} = dec_subidentifiers(not_a_binary, any, [1,2,3], 0),
+ ok.
+
+do_dec_subidentifiers(Buffer, Av, Al, Len) ->
+ Res = dec_subidentifiers(Buffer, Av, Al, Len),
+ Res = dec_subidentifiers2(Buffer, Av, Al, Len),
+ Res = dec_subidentifiers4(Buffer, Av, Al, Len),
+ Res = dec_subidentifiers3(Buffer, Av, Al, Len).
+
+dec_subidentifiers(Buffer, _Av, Al, 0) ->
+ {lists:reverse(Al),Buffer};
+dec_subidentifiers(<<1:1,H:7,T/binary>>, Av, Al, Len) ->
+ dec_subidentifiers(T, (Av bsl 7) bor H, Al, Len-1);
+dec_subidentifiers(<<H,T/binary>>, Av, Al, Len) ->
+ dec_subidentifiers(T, 0, [((Av bsl 7) bor H)|Al], Len-1).
+
+dec_subidentifiers2(<<Buffer/binary>>, _Av, Al, 0) ->
+ {lists:reverse(Al),Buffer};
+dec_subidentifiers2(<<1:1,H:7,T/binary>>, Av, Al, Len) ->
+ dec_subidentifiers2(T, (Av bsl 7) bor H, Al, Len-1);
+dec_subidentifiers2(<<H,T/binary>>, Av, Al, Len) ->
+ dec_subidentifiers2(T, 0, [((Av bsl 7) bor H)|Al], Len-1).
+
+dec_subidentifiers3(Buffer, _Av, Al, 0) when is_binary(Buffer) ->
+ {lists:reverse(Al),Buffer};
+dec_subidentifiers3(<<1:1,H:7,T/binary>>, Av, Al, Len) ->
+ dec_subidentifiers3(T, (Av bsl 7) bor H, Al, Len-1);
+dec_subidentifiers3(<<H,T/binary>>, Av, Al, Len) ->
+ dec_subidentifiers3(T, 0, [((Av bsl 7) bor H)|Al], Len-1).
+
+dec_subidentifiers4(<<1:1,H:7,T/binary>>, Av, Al, Len) when Len =/= 0 ->
+ dec_subidentifiers4(T, (Av bsl 7) bor H, Al, Len-1);
+dec_subidentifiers4(<<H,T/binary>>, Av, Al, Len) when Len =/= 0 ->
+ dec_subidentifiers4(T, 0, [((Av bsl 7) bor H)|Al], Len-1);
+dec_subidentifiers4(Buffer, _Av, Al, 0) ->
+ {lists:reverse(Al),Buffer}.
+
+%%--------------------------------------------------------------------
+
+skip_optional_tag() ->
+ {ok,<<>>} = skip_optional_tag(<<42>>, <<42>>),
+ {ok,<<>>} = skip_optional_tag(<<42,1>>, <<42,1>>),
+ {ok,<<1,2,3>>} = skip_optional_tag(<<42>>, <<42,1,2,3>>),
+ missing = skip_optional_tag(<<2:3>>, blurf),
+ ok.
+
+skip_optional_tag(<<>>, Binary) ->
+ {ok,Binary};
+skip_optional_tag(<<Tag,RestTag/binary>>, <<Tag,Rest/binary>>) ->
+ skip_optional_tag(RestTag, Rest);
+skip_optional_tag(_, _) -> missing.
+
+%%--------------------------------------------------------------------
+
+-define(DATELEN, 16).
+
+wfbm() ->
+ %% check_for_dot_or_space and get_tail is from wfbm4 by Steve Vinoski,
+ %% with modifications.
+ {nomatch,0} = check_for_dot_or_space(<<" ">>),
+ {nomatch,0} = check_for_dot_or_space(<<" abc">>),
+ {ok,<<"abcde">>} = check_for_dot_or_space(<<"abcde 34555">>),
+ {nomatch,0} = check_for_dot_or_space(<<".gurka">>),
+ {nomatch,1} = check_for_dot_or_space(<<"g.urka">>),
+ nomatch = get_tail(<<>>),
+ {ok,<<"2007/10/23/blurf">>} = get_tail(<<"200x/2007/10/23/blurf ">>),
+ {skip,?DATELEN+5} = get_tail(<<"200x/2007/10/23/blurf.">>),
+ nomatch = get_tail(<<"200y.2007.10.23.blurf ">>),
+ {'EXIT',_} = (catch get_tail({no,binary,at,all})),
+ {'EXIT',_} = (catch get_tail(no_binary)),
+ ok.
+
+check_for_dot_or_space(Bin) ->
+ check_for_dot_or_space(Bin, 0).
+
+check_for_dot_or_space(<<$\s, _/binary>>, 0) ->
+ {nomatch,0};
+check_for_dot_or_space(Bin, Len) ->
+ case Bin of
+ <<Front:Len/binary, $\s, _/binary>> ->
+ {ok,Front};
+ <<_:Len/binary, $., _/binary>> ->
+ {nomatch,Len};
+ _ ->
+ check_for_dot_or_space(Bin, Len+1)
+ end.
+
+get_tail(<<>>) ->
+ nomatch;
+get_tail(Bin) ->
+ <<Front:?DATELEN/binary, Tail/binary>> = Bin,
+ case Front of
+ <<_:3/binary,"x/",Y:4/binary,$/,M:2/binary,$/,D:2/binary,$/>> ->
+ case check_for_dot_or_space(Tail) of
+ {ok,Match} ->
+ {ok,<<Y/binary,$/,M/binary,$/,D/binary,$/, Match/binary>>};
+ {nomatch,Skip} -> {skip,?DATELEN + Skip}
+ end;
+ _ -> nomatch
+ end.
+
+%%--------------------------------------------------------------------
+
+degenerated_match() ->
+ error = degenerated_match_1(<<>>),
+ 1 = degenerated_match_1(<<1:1>>),
+ 2 = degenerated_match_1(<<42,43>>),
+
+ error = degenerated_match_2(<<>>),
+ no_split = degenerated_match_2(<<1,2>>),
+ {<<1,2,3,4>>,<<5>>} = degenerated_match_2(<<1,2,3,4,5>>),
+ ok.
+
+degenerated_match_1(<<>>) -> error;
+degenerated_match_1(Bin) -> byte_size(Bin).
+
+degenerated_match_2(<<>>) -> error;
+degenerated_match_2(Bin) ->
+ case byte_size(Bin) > 4 of
+ true -> split_binary(Bin, 4);
+ false -> no_split
+ end.
+
+%%--------------------------------------------------------------------
+
+bs_sum() ->
+ 0 = bs_sum_1([]),
+ 0 = bs_sum_1(<<>>),
+ 42 = bs_sum_1([42]),
+ 1 = bs_sum_1(<<1>>),
+ 10 = bs_sum_1([1,2,3,4]),
+ 15 = bs_sum_1(<<1,2,3,4,5>>),
+ 21 = bs_sum_1([1,2,3|<<4,5,6>>]),
+ 15 = bs_sum_1([1,2,3|{4,5}]),
+ 6 = bs_sum_1([1,2,3|zero]),
+ 6 = bs_sum_1([1,2,3|0]),
+ 7 = bs_sum_1([1,2,3|one]),
+
+ fc(catch bs_sum_1({too,big,tuple})),
+ fc(catch bs_sum_1([1,2,3|{too,big,tuple}])),
+
+ [] = sneaky_alias(<<>>),
+ [559,387655] = sneaky_alias(id(<<559:32,387655:32>>)),
+ fc(sneaky_alias, [<<1>>], catch sneaky_alias(id(<<1>>))),
+ fc(sneaky_alias, [[1,2,3,4]], catch sneaky_alias(lists:seq(1, 4))),
+ ok.
+
+bs_sum_1(<<H,T/binary>>) -> H+bs_sum_1(T);
+bs_sum_1([H|T]) -> H+bs_sum_1(T);
+bs_sum_1({A,B}=_Tuple=_AliasForNoGoodReason) -> A+B;
+bs_sum_1(0) -> 0;
+bs_sum_1(zero=_Zero) -> 0;
+bs_sum_1(one) -> 1;
+bs_sum_1([]) -> 0;
+bs_sum_1(<<>>) -> 0.
+
+sneaky_alias(<<>>=L) -> binary_to_list(L);
+sneaky_alias(<<From:32,L/binary>>) -> [From|sneaky_alias(L)].
+
+%%--------------------------------------------------------------------
+
+coverage() ->
+ 0 = coverage_fold(fun(B, A) -> A+B end, 0, <<>>),
+ 6 = coverage_fold(fun(B, A) -> A+B end, 0, <<1,2,3>>),
+ fc(catch coverage_fold(fun(B, A) -> A+B end, 0, [a,b,c])),
+
+ {<<42.0:64/float>>,float} = coverage_build(<<>>, <<42>>, float),
+ {<<>>,not_a_tuple} = coverage_build(<<>>, <<>>, not_a_tuple),
+ {<<16#76,"abc",16#A9,"abc">>,{x,42,43}} =
+ coverage_build(<<>>, <<16#7,16#A>>, {x,y,z}),
+
+ [<<2>>,<<1>>] = coverage_bc(<<1,2>>, []),
+
+ {x,<<"abc">>,z} = coverage_setelement(<<2,"abc">>, {x,y,z}),
+
+ [42] = coverage_apply(<<42>>, [exported_id]),
+ 42 = coverage_external(<<42>>),
+
+ do_coverage_bin_to_term_list([]),
+ do_coverage_bin_to_term_list([lists:seq(0, 10),{a,b,c},<<23:42>>]),
+ fc(coverage_bin_to_term_list, [<<0,0,0,7>>],
+ catch do_coverage_bin_to_term_list_1(<<7:32>>)),
+
+ <<>> = coverage_per_key(<<4:32>>),
+ <<$a,$b,$c>> = coverage_per_key(<<7:32,"abc">>),
+
+ ok.
+
+coverage_fold(Fun, Acc, <<H,T/binary>>) ->
+ IdFun = fun id/1,
+ coverage_fold(Fun, Fun(IdFun(H), IdFun(Acc)), T);
+coverage_fold(Fun, Acc, <<>>) when is_function(Fun, 2) -> Acc.
+
+coverage_build(Acc0, <<H,T/binary>>, float) ->
+ Float = id(<<H:64/float>>),
+ Acc = <<Acc0/binary,Float/binary>>,
+ coverage_build(Acc, T, float);
+coverage_build(Acc0, <<H,T/binary>>, Tuple0) ->
+ Str = id(<<H:(id(4)),(H-1):4,"abc">>),
+ Acc = id(<<Acc0/bitstring,Str/bitstring>>),
+ Tuple = setelement(2, setelement(3, Tuple0, 43), 42),
+ if
+ byte_size(Acc) > 0 ->
+ coverage_build(Acc, T, Tuple)
+ end;
+coverage_build(Acc, <<>>, Tuple) -> {Acc,Tuple}.
+
+coverage_bc(<<H,T/binary>>, Acc) ->
+ B = << <<C:8>> || C <- [H] >>,
+ coverage_bc(T, [B|Acc]);
+coverage_bc(<<>>, Acc) -> Acc.
+
+coverage_setelement(<<H,T1/binary>>, Tuple) when element(1, Tuple) =:= x ->
+ setelement(H, Tuple, T1).
+
+coverage_apply(<<H,T/binary>>, [F|Fs]) ->
+ [?MODULE:F(H)|coverage_apply(T, Fs)];
+coverage_apply(<<>>, []) -> [].
+
+coverage_external(<<H,T/binary>>) ->
+ ?MODULE:exported_id(T, T),
+ H.
+
+exported_id(I) -> id(I).
+
+exported_id(_, _) -> ok.
+
+do_coverage_bin_to_term_list(L) ->
+ Bin = << <<(begin BinTerm = term_to_binary(Term),
+ <<(byte_size(BinTerm)):32,BinTerm/binary>> end)/binary>> ||
+ Term <- L >>,
+ L = do_coverage_bin_to_term_list_1(Bin),
+ L = do_coverage_bin_to_term_list_1(<<Bin/binary,7:32,"garbage">>),
+ L = do_coverage_bin_to_term_list_1(<<7:32,"garbage",Bin/binary>>).
+
+do_coverage_bin_to_term_list_1(Bin) ->
+ Res = coverage_bin_to_term_list(Bin),
+ Res = coverage_bin_to_term_list(Bin, []),
+ Res = coverage_bin_to_term_list_catch(Bin),
+ Res = coverage_bin_to_term_list_catch(Bin, []).
+
+coverage_bin_to_term_list(<<Sz:32,BinTerm:Sz/binary,T/binary>>) ->
+ try binary_to_term(BinTerm) of
+ Term -> [Term|coverage_bin_to_term_list(T)]
+ catch
+ error:badarg -> coverage_bin_to_term_list(T)
+ end;
+coverage_bin_to_term_list(<<>>) -> [].
+
+coverage_bin_to_term_list(<<Sz:32,BinTerm:Sz/binary,T/binary>>, Acc) ->
+ try binary_to_term(BinTerm) of
+ Term -> coverage_bin_to_term_list(T, [Term|Acc])
+ catch
+ error:badarg -> coverage_bin_to_term_list(T, Acc)
+ end;
+coverage_bin_to_term_list(<<>>, Acc) -> lists:reverse(Acc).
+
+coverage_bin_to_term_list_catch(<<Sz:32,BinTerm:Sz/binary,T/binary>>) ->
+ case catch binary_to_term(BinTerm) of
+ {'EXIT',_} -> coverage_bin_to_term_list_catch(T);
+ Term -> [Term|coverage_bin_to_term_list_catch(T)]
+ end;
+coverage_bin_to_term_list_catch(<<>>) -> [].
+
+coverage_bin_to_term_list_catch(<<Sz:32,BinTerm:Sz/binary,T/binary>>, Acc) ->
+ case catch binary_to_term(BinTerm) of
+ {'EXIT',_} -> coverage_bin_to_term_list_catch(T, Acc);
+ Term -> coverage_bin_to_term_list_catch(T, [Term|Acc])
+ end;
+coverage_bin_to_term_list_catch(<<>>, Acc) -> lists:reverse(Acc).
+
+coverage_per_key(<<BinSize:32,Bin/binary>> = B) ->
+ true = (byte_size(B) =:= BinSize),
+ Bin.
+
+%%--------------------------------------------------------------------
+
+multiple_uses() ->
+ {344,62879,345,<<245,159,1,89>>} = multiple_uses_1(<<1,88,245,159,1,89>>),
+ true = multiple_uses_2(<<0,0,197,18>>),
+ <<42,43>> = multiple_uses_3(<<0,0,42,43>>, fun id/1),
+ ok.
+
+multiple_uses_1(<<X:16,Tail/binary>>) ->
+ %% NOT OPTIMIZED: sub binary is matched or used in more than one place
+ {Y,Z} = multiple_uses_match(Tail),
+ {X,Y,Z,Tail}.
+
+multiple_uses_2(<<_:16,Tail/binary>>) ->
+ %% NOT OPTIMIZED: sub binary is matched or used in more than one place
+ multiple_uses_cmp(Tail, Tail).
+
+multiple_uses_3(<<_:16,Tail/binary>>, Fun) ->
+ %% NOT OPTIMIZED: sub binary is used or returned
+ Fun(Tail).
+
+multiple_uses_match(<<Y:16,Z:16>>) -> {Y,Z}.
+
+multiple_uses_cmp(<<Y:16>>, <<Y:16>>) -> true;
+multiple_uses_cmp(<<_:16>>, <<_:16>>) -> false.
+
+%%--------------------------------------------------------------------
+
+zero_label() ->
+ <<"nosemouth">> = read_pols(<<"FACE","nose","mouth">>),
+ <<"CE">> = read_pols(<<"noFACE">>),
+ ok.
+
+read_pols(Data) ->
+ <<PolygonType:4/binary,Rest/binary>> = Data,
+ %% Intentional warning.
+ _ = (PolygonType == <<"FACE">>) or (PolygonType == <<"PTCH">>),
+ Rest.
+
+%%--------------------------------------------------------------------
+
+followed_by_catch() ->
+ ok = handle(<<0,1,2,3,4,5>>).
+
+-record(rec,{field}).
+handle(<<>>) -> ok;
+handle(Msg) ->
+ <<_DataLen:16, Rest/binary>> = Msg,
+ case catch fooX:func() of
+ [X] ->
+ X#rec.field;
+ _ ->
+ ok
+ end,
+ handle(Rest).
+
+%%--------------------------------------------------------------------
+
+matching_meets_construction() ->
+ Bin = id(<<"abc">>),
+ Len = id(2),
+ Tail0 = id(<<1,2,3,4,5>>),
+ <<_:Len/binary,Tail/binary>> = Tail0,
+ Res = <<Tail/binary,Bin/binary>>,
+ <<3,4,5,"abc">> = Res,
+ {'EXIT',{badarg,_}} = (catch matching_meets_construction_1(<<"Abc">>)),
+ {'EXIT',{badarg,_}} = (catch matching_meets_construction_2(<<"Abc">>)),
+ <<"Bbc">> = matching_meets_construction_3(<<"Abc">>),
+ <<1,2>> = encode_octet_string(<<1,2,3>>, 2),
+ ok.
+
+matching_meets_construction_1(<<"A",H/binary>>) -> <<"B",H>>.
+
+matching_meets_construction_2(<<"A",H/binary>>) -> <<"B",H/float>>.
+
+matching_meets_construction_3(<<"A",H/binary>>) -> <<"B",H/binary>>.
+
+encode_octet_string(<<OctetString/binary>>, Len) ->
+ <<OctetString:Len/binary-unit:8>>.
+
+%%--------------------------------------------------------------------
+
+simon() ->
+ one = simon(blurf, <<>>),
+ two = simon(0, <<42>>),
+ fc(simon, [17,<<1>>], catch simon(17, <<1>>)),
+ fc(simon, [0,<<1,2,3>>], catch simon(0, <<1,2,3>>)),
+
+ one = simon2(blurf, <<9>>),
+ two = simon2(0, <<9,1>>),
+ fc(simon2, [0,<<9,10,11>>], catch simon2(0, <<9,10,11>>)),
+ ok.
+
+simon(_, <<>>) -> one;
+simon(0, <<_>>) -> two.
+
+simon2(_, <<9>>) -> one;
+simon2(0, <<_:16>>) -> two.
+
+%%--------------------------------------------------------------------
+%% OTP-7113: Crash in v3_codegen.
+
+matching_and_andalso() ->
+ ok = matching_and_andalso_1(<<1,2,3>>, 3),
+ {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, -8)),
+ {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, blurf)),
+ {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, 19)),
+
+ {"abc",<<"xyz">>} = matching_and_andalso_2("abc", <<"-xyz">>),
+ {"abc",<<"">>} = matching_and_andalso_2("abc", <<($a-1)>>),
+ {"abc",<<"">>} = matching_and_andalso_2("abc", <<($z+1)>>),
+ {"abc",<<"">>} = matching_and_andalso_2("abc", <<($A-1)>>),
+ {"abc",<<"">>} = matching_and_andalso_2("abc", <<($Z+1)>>),
+ error = matching_and_andalso_2([], <<>>),
+ error = matching_and_andalso_2([], <<$A>>),
+ error = matching_and_andalso_2([], <<$Z>>),
+ error = matching_and_andalso_2([], <<$a>>),
+ error = matching_and_andalso_2([], <<$z>>),
+ ok.
+
+matching_and_andalso_1(<<Bitmap/binary>>, K)
+ when is_integer(K) andalso size(Bitmap) >= K andalso 0 < K -> ok.
+
+matching_and_andalso_2(Datetime, <<H,T/binary>>)
+ when not ((H >= $a) andalso (H =< $z)) andalso
+ not ((H >= $A) andalso (H =< $Z)) ->
+ {Datetime,T};
+matching_and_andalso_2(_, _) -> error.
+
+%%--------------------------------------------------------------------
+%% Thanks to Tomas Stejskal.
+
+otp_7188() ->
+ MP3 = <<84,65,71,68,117,154,105,232,107,121,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,68,97,110,105,101,108,32,76,
+ 97,110,100,97,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,
+ 101,115,116,32,79,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,50,48,48,48,50,48,48,48,32,45,32,66,101,115,
+ 116,32,79,102,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+ 32,32,12>>,
+ {ok,{"ID3v1",
+ [{title,<<68,117,154,105,232,107,121>>},
+ {artist,<<"Daniel Landa">>},
+ {album,<<"Best Of">>}]}} = parse_v1_or_v11_tag(MP3),
+ ok.
+
+parse_v1_or_v11_tag(<<"TAG", Title:30/binary,
+ Artist:30/binary, Album:30/binary,
+ _Year:4/binary, _Comment:28/binary,
+ 0:8, Track:8, _Genre:8>>) ->
+ {ok,
+ {"ID3v1.1",
+ [{track, Track}, {title, trim(Title)},
+ {artist, trim(Artist)}, {album, trim(Album)}]}};
+parse_v1_or_v11_tag(<<"TAG", Title:30/binary,
+ Artist:30/binary, Album:30/binary,
+ _Year:4/binary, _Comment:30/binary,
+ _Genre:8>>) ->
+ {ok,
+ {"ID3v1",
+ [{title, trim(Title)},
+ {artist, trim(Artist)},
+ {album, trim(Album)}]}};
+parse_v1_or_v11_tag(_) ->
+ error.
+
+trim(Bin) ->
+ list_to_binary(trim_blanks(binary_to_list(Bin))).
+
+trim_blanks(L) ->
+ lists:reverse(skip_blanks_and_zero(lists:reverse(L))).
+
+skip_blanks_and_zero([$\s|T]) ->
+ skip_blanks_and_zero(T);
+skip_blanks_and_zero([0|T]) ->
+ skip_blanks_and_zero(T);
+skip_blanks_and_zero(L) ->
+ L.
+
+%%--------------------------------------------------------------------
+%% OTP-7233. Record and binary matching optimizations clashed.
+%% Thanks to Vladimir Klebansky.
+
+-record(rec_otp_7233, {key, val}).
+
+otp_7233() ->
+ otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[{"xxxxxxxx",42}]}),
+ [<<"XXabcde">>,{"xxxxxxxx",42}] = get(io_format),
+ erase(io_format),
+ otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[]}),
+ undefined = get(io_format),
+ ok.
+
+otp_7233_1(Rec) ->
+ <<K:2/binary,_Rest:5/binary>> = Rec#rec_otp_7233.key,
+ case K of
+ <<"XX">> ->
+ Value = Rec#rec_otp_7233.val,
+ case lists:keysearch("xxxxxxxx", 1, Value) of
+ {value,T} -> put(io_format, [Rec#rec_otp_7233.key,T]);
+ false -> ok
+ end;
+ _ -> ok
+ end.
+
+%%--------------------------------------------------------------------
+
+otp_7240() ->
+ a = otp_7240_a(0, <<>>),
+ b = otp_7240_a(1, 2),
+
+ a = otp_7240_b(anything, <<>>),
+ b = otp_7240_b(1, {x,y}),
+
+ a = otp_7240_c(anything, <<>>),
+ b = otp_7240_c(1, <<2>>),
+
+ a = otp_7240_d(anything, <<>>),
+ b = otp_7240_d(again, <<2>>),
+
+ a = otp_7240_e(anything, <<>>),
+ b = otp_7240_e(1, 41),
+
+ a = otp_7240_f(anything, <<>>),
+ b = otp_7240_f(1, {}),
+
+ ok.
+
+otp_7240_a(_, <<>>) -> a;
+otp_7240_a(1, 2) -> b.
+
+otp_7240_b(_, <<>>) -> a;
+otp_7240_b(1, {_,_}) -> b.
+
+otp_7240_c(_, <<>>) -> a;
+otp_7240_c(1, <<2>>) -> b.
+
+otp_7240_d(_, <<>>) -> a;
+otp_7240_d(_, <<2>>) -> b.
+
+otp_7240_e(_, <<>>) -> a;
+otp_7240_e(1, B) when B < 42 -> b.
+
+otp_7240_f(_, <<>>) -> a;
+otp_7240_f(1, B) when is_tuple(B) -> b.
+
+%%--------------------------------------------------------------------
+
+otp_7498() ->
+ <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 0),
+ <<2,3>> = otp_7498_foo(<<1,2,3>>, 1),
+ <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 2),
+
+ <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 0),
+ <<2,3>> = otp_7498_bar(<<1,2,3>>, 1),
+ <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 2),
+ <<>> = otp_7498_bar(<<>>, 2),
+ <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 3),
+ ok.
+
+otp_7498_foo(Bin, 0) ->
+ otp_7498_foo(Bin, 42);
+otp_7498_foo(<<_A, Rest/bitstring>>, 1) ->
+ otp_7498_foo(Rest, 43);
+otp_7498_foo(Bin, _I) ->
+ Bin.
+
+otp_7498_bar(Bin, 0) ->
+ otp_7498_bar(Bin, 42);
+otp_7498_bar(<<_A, Rest/bitstring>>, 1) ->
+ otp_7498_bar(Rest, 43);
+otp_7498_bar(<<>>, 2) ->
+ otp_7498_bar(<<>>, 44);
+otp_7498_bar(Bin, _I) ->
+ Bin.
+
+%%--------------------------------------------------------------------
+
+match_string() ->
+ %% To make sure that native endian really is handled correctly
+ %% (i.e. that the compiler does not attempt to use bs_match_string/4
+ %% instructions for native segments), running this test is not enough.
+ %% Either examine the generated for do_match_string_native/1 or
+ %% check the coverage for the v3_kernel module.
+ case erlang:system_info(endian) of
+ little ->
+ do_match_string_native(<<$a,0,$b,0>>);
+ big ->
+ do_match_string_native(<<0,$a,0,$b>>)
+ end,
+ do_match_string_big(<<0,$a,0,$b>>),
+ do_match_string_little(<<$a,0,$b,0>>),
+
+ do_match_string_big_signed(<<255,255>>),
+ do_match_string_little_signed(<<255,255>>),
+
+ plain = no_match_string_opt(<<"abc">>),
+ strange = no_match_string_opt(<<$a:9,$b:9,$c:9>>),
+ ok.
+
+do_match_string_native(<<$a:16/native,$b:16/native>>) -> ok.
+
+do_match_string_big(<<$a:16/big,$b:16/big>>) -> ok.
+
+do_match_string_little(<<$a:16/little,$b:16/little>>) -> ok.
+
+do_match_string_big_signed(<<(-1):16/signed>>) -> ok.
+
+do_match_string_little_signed(<<(-1):16/little-signed>>) -> ok.
+
+no_match_string_opt(<<"abc">>) -> plain;
+no_match_string_opt(<<$a:9,$b:9,$c:9>>) -> strange.
+
+%%--------------------------------------------------------------------
+%% OTP-7591: A zero-width segment in matching would crash the compiler.
+
+zero_width() ->
+ <<Len:16/little, Str:Len/binary, 0:0>> = <<2, 0, $h, $i, 0:0>>,
+ 2 = Len,
+ Str = <<"hi">>,
+ %% Match sure that values that cannot fit in a segment will not match.
+ case id(<<0:8>>) of
+ <<256:8>> -> error;
+ _ -> ok
+ end.
+
+%%--------------------------------------------------------------------
+%% OTP_7650: A invalid size for binary segments could crash the compiler.
+
+bad_size() ->
+ Tuple = {a,b,c},
+ {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Tuple>> = id(<<>>)),
+ Binary = <<1,2,3>>,
+ {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Binary>> = id(<<>>)),
+ ok.
+
+%%--------------------------------------------------------------------
+
+haystack() ->
+ <<0:10/unit:8>> = haystack_1(<<0:10/unit:8>>),
+ [<<0:10/unit:8>>,
+ <<0:20/unit:8>>] = haystack_2(<<1:8192>>),
+ ok.
+
+%% Used to crash the compiler.
+haystack_1(Haystack) ->
+ Subs = [10],
+ [begin
+ <<B:Y/binary>> = Haystack,
+ B
+ end || Y <- Subs],
+ Haystack.
+
+%% There would be an incorrect badmatch exception.
+haystack_2(Haystack) ->
+ Subs = [{687,10},{369,20}],
+ [begin
+ <<_:X/binary,B:Y/binary,_/binary>> = Haystack,
+ B
+ end || {X,Y} <- Subs].
+
+fc({'EXIT',{function_clause,_}}) -> ok.
+
+fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Args,_}|_]}}) -> ok;
+fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Arity,_}|_]}})
+ when length(Args) =:= Arity ->
+ true = test_server:is_native(?MODULE).
+
+%%--------------------------------------------------------------------
+%% Cover the clause handling bs_context to binary in
+%% beam_block:initialized_regs/2.
+cover_beam_bool() ->
+ ok = do_cover_beam_bool(<<>>, 3),
+ <<19>> = do_cover_beam_bool(<<19>>, 2),
+ <<42>> = do_cover_beam_bool(<<42>>, 1),
+ <<17>> = do_cover_beam_bool(<<13,17>>, 0),
+ ok.
+
+do_cover_beam_bool(Bin, X) when X > 0 ->
+ if
+ X =:= 1; X =:= 2 ->
+ Bin;
+ true ->
+ ok
+ end;
+do_cover_beam_bool(<<_,Bin/binary>>, X) ->
+ do_cover_beam_bool(Bin, X+1).
+
+%%--------------------------------------------------------------------
+
+matched_out_size() ->
+ {253,16#DEADBEEF} = mos_int(<<8,253,16#DEADBEEF:32>>),
+ {6,16#BEEFDEAD} = mos_int(<<3,6:3,16#BEEFDEAD:32>>),
+ {53,16#CAFEDEADBEEFCAFE} = mos_int(<<16,53:16,16#CAFEDEADBEEFCAFE:64>>),
+ {23,16#CAFEDEADBEEFCAFE} = mos_int(<<5,23:5,16#CAFEDEADBEEFCAFE:64>>),
+
+ {<<1,2,3>>,4} = mos_bin(<<3,1,2,3,4,3>>),
+ {<<1,2,3,7>>,19,42} = mos_bin(<<4,1,2,3,7,19,4,42>>),
+ <<1,2,3,7>> = mos_bin(<<4,1,2,3,7,"abcdefghij">>),
+ ok.
+
+mos_int(<<L,I:L,X:32>>) ->
+ {I,X};
+mos_int(<<L,I:L,X:64>>) ->
+ {I,X}.
+
+mos_bin(<<L,Bin:L/binary,X:8,L>>) ->
+ L = byte_size(Bin),
+ {Bin,X};
+mos_bin(<<L,Bin:L/binary,X:8,L,Y:8>>) ->
+ L = byte_size(Bin),
+ {Bin,X,Y};
+mos_bin(<<L,Bin:L/binary,"abcdefghij">>) ->
+ L = byte_size(Bin),
+ Bin.
+
+%%--------------------------------------------------------------------
+
+follow_fail_br() ->
+ 42 = ffb_1(<<0,1>>, <<0>>),
+ 8 = ffb_1(<<0,1>>, [a]),
+ 42 = ffb_2(<<0,1>>, <<0>>, 17),
+ 8 = ffb_2(<<0,1>>, [a], 0),
+ ok.
+
+ffb_1(<<_,T/bitstring>>, List) ->
+ case List of
+ <<_>> ->
+ 42;
+ [_|_] ->
+ %% The fail branch of the bs_start_match2 instruction pointing
+ %% to here would be ignored, making the compiler incorrectly
+ %% assume that the delayed sub-binary optimization was safe.
+ bit_size(T)
+ end.
+
+ffb_2(<<_,T/bitstring>>, List, A) ->
+ case List of
+ <<_>> when A =:= 17 -> 42;
+ [_|_] -> bit_size(T)
+ end.
+
+%%--------------------------------------------------------------------
+
+no_partition() ->
+ one = no_partition_1(<<"string">>, a1),
+ {two,<<"string">>} = no_partition_1(<<"string">>, a2),
+ {two,<<>>} = no_partition_1(<<>>, a2),
+ {two,a} = no_partition_1(a, a2),
+ three = no_partition_1(undefined, a3),
+ {four,a,[]} = no_partition_1([a], a4),
+ {five,a,b} = no_partition_1({a,b}, a5),
+
+ one = no_partition_2(<<"string">>, a1),
+ two = no_partition_2(<<"string">>, a2),
+ two = no_partition_2(<<>>, a2),
+ two = no_partition_2(a, a2),
+ three = no_partition_2(undefined, a3),
+ four = no_partition_2(42, a4),
+ five = no_partition_2([], a5),
+ six = no_partition_2(42.0, a6),
+ ok.
+
+no_partition_1(<<"string">>, a1) -> one;
+no_partition_1(V, a2) -> {two,V};
+no_partition_1(undefined, a3) -> three;
+no_partition_1([H|T], a4) -> {four,H,T};
+no_partition_1({A,B}, a5) -> {five,A,B}.
+
+no_partition_2(<<"string">>, a1) -> one;
+no_partition_2(_, a2) -> two;
+no_partition_2(undefined, a3) -> three;
+no_partition_2(42, a4) -> four;
+no_partition_2([], a5) -> five;
+no_partition_2(42.0, a6) -> six.
+
+%%--------------------------------------------------------------------
+
+calling_a_binary() ->
+ [] = call_binary(<<>>, []),
+ {'EXIT',{badarg,_}} = (catch call_binary(<<1>>, [])),
+ {'EXIT',{badarg,_}} = (catch call_binary(<<1,2,3>>, [])),
+ ok.
+
+call_binary(<<>>, Acc) ->
+ Acc;
+call_binary(<<H,T/bits>>, Acc) ->
+ T(<<Acc/binary,H>>).
+
+%%--------------------------------------------------------------------
+
+binary_in_map() ->
+ ok = match_binary_in_map(#{key => <<42:8>>}),
+ {'EXIT',{{badmatch,#{key := 1}},_}} =
+ (catch match_binary_in_map(#{key => 1})),
+ {'EXIT',{{badmatch,#{key := <<1023:16>>}},_}} =
+ (catch match_binary_in_map(#{key => <<1023:16>>})),
+ {'EXIT',{{badmatch,#{key := <<1:8>>}},_}} =
+ (catch match_binary_in_map(#{key => <<1:8>>})),
+ {'EXIT',{{badmatch,not_a_map},_}} =
+ (catch match_binary_in_map(not_a_map)),
+ ok.
+
+match_binary_in_map(Map) ->
+ case 8 of
+ N ->
+ #{key := <<42:N>>} = Map,
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+
+match_string_opt() ->
+ {x,<<1,2,3>>,{<<1>>,{v,<<1,2,3>>}}} = match_string_opt({<<1>>,{v,<<1,2,3>>}}),
+ ok.
+
+match_string_opt({<<1>>,{v,V}}=T) ->
+ {x,V,T}.
+
+%%--------------------------------------------------------------------
+%% If 'bin_opt_info' was given the warning would lack filename and
+%% line number.
+
+map_and_binary() ->
+ {<<"10">>,<<"37">>,<<"am">>} = do_map_and_binary(<<"10:37am">>),
+ Map1 = #{time => "noon"},
+ {ok,Map1} = do_map_and_binary(Map1),
+ Map2 = #{hour => 8, min => 42},
+ {8,42,Map2} = do_map_and_binary(Map2),
+ ok.
+
+do_map_and_binary(<<Hour:2/bytes, $:, Min:2/bytes, Rest/binary>>) ->
+ {Hour, Min, Rest};
+do_map_and_binary(#{time := _} = T) ->
+ {ok, T};
+do_map_and_binary(#{hour := Hour, min := Min} = T) ->
+ {Hour, Min, T}.
+
+%%--------------------------------------------------------------------
+%% Unsafe caching of branch outcomes in beam_bsm would cause the
+%% delayed creation of sub-binaries optimization to be applied even
+%% when it was unsafe.
+
+unsafe_branch_caching() ->
+ <<>> = do_unsafe_branch_caching(<<42,1>>),
+ <<>> = do_unsafe_branch_caching(<<42,2>>),
+ <<>> = do_unsafe_branch_caching(<<42,3>>),
+ <<17,18>> = do_unsafe_branch_caching(<<42,3,17,18>>),
+ <<>> = do_unsafe_branch_caching(<<1,3,42,2>>),
+ ok.
+
+do_unsafe_branch_caching(<<Code/integer, Bin/binary>>) ->
+ <<C1/integer, B1/binary>> = Bin,
+ case C1 of
+ X when X =:= 1 orelse X =:= 2 ->
+ Bin2 = <<>>;
+ _ ->
+ Bin2 = B1
+ end,
+ case Code of
+ 1 -> do_unsafe_branch_caching(Bin2);
+ _ -> Bin2
+ end.
+
+%%--------------------------------------------------------------------
+
+check(F, R) ->
+ R = F().
+
+id(I) -> I.
diff --git a/lib/hipe/test/bs_SUITE_data/bs_split.erl b/lib/hipe/test/bs_SUITE_data/bs_split.erl
index 2e52308a77..617543f789 100644
--- a/lib/hipe/test/bs_SUITE_data/bs_split.erl
+++ b/lib/hipe/test/bs_SUITE_data/bs_split.erl
@@ -26,13 +26,13 @@ bs1(L, B, Pos, Sz1, Sz2) ->
<<B1:Sz1/binary, B2:Sz2/binary>> = B,
bs2(L, B, Pos, B1, B2).
-bs2(L, B, Pos, B1, B2)->
+bs2(L, B, Pos, B1, B2) ->
B1 = list_to_binary(lists:sublist(L, 1, Pos)),
bs3(L, B, Pos, B2).
bs3(L, B, Pos, B2) ->
B2 = list_to_binary(lists:nthtail(Pos, L)),
- byte_split(L, B, Pos-1).
+ byte_split(L, B, Pos - 1).
%%--------------------------------------------------------------------
@@ -56,14 +56,14 @@ bit_split_binary2(_Action, _Bin, [], _Bef) -> ok.
bit_split_binary3(Action, Bin, List, Bef, Aft) when Bef =< Aft ->
Action(Bin, List, Bef, (Aft-Bef) div 8 * 8),
- bit_split_binary3(Action, Bin, List, Bef, Aft-8);
+ bit_split_binary3(Action, Bin, List, Bef, Aft - 8);
bit_split_binary3(_, _, _, _, _) -> ok.
make_bin_from_list(_List, 0) ->
mkbin([]);
make_bin_from_list(List, N) ->
list_to_binary([make_int(List, 8, 0),
- make_bin_from_list(lists:nthtail(8, List), N-8)]).
+ make_bin_from_list(lists:nthtail(8, List), N - 8)]).
make_int(_List, 0, Acc) -> Acc;
make_int([H|T], N, Acc) -> make_int(T, N-1, Acc bsl 1 bor H).
@@ -101,5 +101,5 @@ z_split(B, N) ->
<<_:N/binary>> ->
[B];
_ ->
- z_split(B, N+1)
+ z_split(B, N + 1)
end.
diff --git a/lib/hipe/test/bs_SUITE_data/bs_utf.erl b/lib/hipe/test/bs_SUITE_data/bs_utf.erl
index f50ae08964..368ad0cd20 100644
--- a/lib/hipe/test/bs_SUITE_data/bs_utf.erl
+++ b/lib/hipe/test/bs_SUITE_data/bs_utf.erl
@@ -1,18 +1,356 @@
%% -*- erlang-indent-level: 2 -*-
%%-------------------------------------------------------------------
-%% Purpose: test support for UTF datatypes in binaries - INCOMPLETE
+%% Purpose: test support for UTF datatypes in binaries
+%%
+%% Most of it taken from emulator/test/bs_utf_SUITE.erl
%%-------------------------------------------------------------------
-module(bs_utf).
-export([test/0]).
+-include_lib("common_test/include/ct.hrl").
+
test() ->
+ ok = utf8_cm65(),
+ ok = utf8_roundtrip(),
+ ok = utf16_roundtrip(),
+ ok = utf32_roundtrip(),
+ %% The following were problematic for the LLVM backend
+ ok = utf8_illegal_sequences(),
+ ok = utf16_illegal_sequences(),
+ ok = utf32_illegal_sequences(),
+ ok.
+
+%%-------------------------------------------------------------------
+%% A test with construction and matching
+
+utf8_cm65() ->
<<65>> = b65utf8(),
ok = m(<<65>>).
+b65utf8() ->
+ <<65/utf8>>.
+
m(<<65/utf8>>) ->
ok.
-b65utf8() ->
- <<65/utf8>>.
+%%-------------------------------------------------------------------
+
+utf8_roundtrip() ->
+ ok = utf8_roundtrip(0, 16#D7FF),
+ ok = utf8_roundtrip(16#E000, 16#10FFFF),
+ ok.
+
+utf8_roundtrip(First, Last) when First =< Last ->
+ Bin = int_to_utf8(First),
+ Bin = id(<<First/utf8>>),
+ Bin = id(<<(id(<<>>))/binary,First/utf8>>),
+ Unaligned = id(<<3:2,First/utf8>>),
+ <<_:2,Bin/binary>> = Unaligned,
+ <<First/utf8>> = Bin,
+ <<First/utf8>> = make_unaligned(Bin),
+ utf8_roundtrip(First+1, Last);
+utf8_roundtrip(_, _) ->
+ ok.
+
+%%-------------------------------------------------------------------
+
+utf16_roundtrip() ->
+ Big = fun utf16_big_roundtrip/1,
+ Little = fun utf16_little_roundtrip/1,
+ PidRefs = [spawn_monitor(fun() -> do_utf16_roundtrip(Fun) end) ||
+ Fun <- [Big,Little]],
+ [receive {'DOWN', Ref, process, Pid, Reason} -> normal=Reason end ||
+ {Pid, Ref} <- PidRefs],
+ ok.
+
+do_utf16_roundtrip(Fun) ->
+ do_utf16_roundtrip(0, 16#D7FF, Fun),
+ do_utf16_roundtrip(16#E000, 16#10FFFF, Fun).
+
+do_utf16_roundtrip(First, Last, Fun) when First =< Last ->
+ Fun(First),
+ do_utf16_roundtrip(First+1, Last, Fun);
+do_utf16_roundtrip(_, _, _) -> ok.
+
+utf16_big_roundtrip(Char) ->
+ Bin = id(<<Char/utf16>>),
+ Bin = id(<<(id(<<>>))/binary,Char/utf16>>),
+ Unaligned = id(<<3:2,Char/utf16>>),
+ <<_:2,Bin/binary>> = Unaligned,
+ <<Char/utf16>> = Bin,
+ <<Char/utf16>> = make_unaligned(Bin),
+ ok.
+
+utf16_little_roundtrip(Char) ->
+ Bin = id(<<Char/little-utf16>>),
+ Bin = id(<<(id(<<>>))/binary,Char/little-utf16>>),
+ Unaligned = id(<<3:2,Char/little-utf16>>),
+ <<_:2,Bin/binary>> = Unaligned,
+ <<Char/little-utf16>> = Bin,
+ <<Char/little-utf16>> = make_unaligned(Bin),
+ ok.
+
+%%-------------------------------------------------------------------
+
+utf32_roundtrip() ->
+ Big = fun utf32_big_roundtrip/1,
+ Little = fun utf32_little_roundtrip/1,
+ PidRefs = [spawn_monitor(fun() -> do_utf32_roundtrip(Fun) end) ||
+ Fun <- [Big,Little]],
+ [receive {'DOWN', Ref, process, Pid, Reason} -> normal=Reason end ||
+ {Pid, Ref} <- PidRefs],
+ ok.
+
+do_utf32_roundtrip(Fun) ->
+ do_utf32_roundtrip(0, 16#D7FF, Fun),
+ do_utf32_roundtrip(16#E000, 16#10FFFF, Fun).
+
+do_utf32_roundtrip(First, Last, Fun) when First =< Last ->
+ Fun(First),
+ do_utf32_roundtrip(First+1, Last, Fun);
+do_utf32_roundtrip(_, _, _) -> ok.
+
+utf32_big_roundtrip(Char) ->
+ Bin = id(<<Char/utf32>>),
+ Bin = id(<<(id(<<>>))/binary,Char/utf32>>),
+ Unaligned = id(<<3:2,Char/utf32>>),
+ <<_:2,Bin/binary>> = Unaligned,
+ <<Char/utf32>> = Bin,
+ <<Char/utf32>> = make_unaligned(Bin),
+ ok.
+
+utf32_little_roundtrip(Char) ->
+ Bin = id(<<Char/little-utf32>>),
+ Bin = id(<<(id(<<>>))/binary,Char/little-utf32>>),
+ Unaligned = id(<<3:2,Char/little-utf32>>),
+ <<_:2,Bin/binary>> = Unaligned,
+ <<Char/little-utf32>> = Bin,
+ <<Char/little-utf32>> = make_unaligned(Bin),
+ ok.
+
+%%-------------------------------------------------------------------
+
+utf8_illegal_sequences() ->
+ fail_range(16#10FFFF+1, 16#10FFFF+512), % Too large.
+ fail_range(16#D800, 16#DFFF), % Reserved for UTF-16.
+
+ %% Illegal first character.
+ [fail(<<I,16#8F,16#8F,16#8F>>) || I <- lists:seq(16#80, 16#BF)],
+
+ %% Short sequences.
+ short_sequences(16#80, 16#10FFFF),
+
+ %% Overlong sequences. (Using more bytes than necessary
+ %% is not allowed.)
+ overlong(0, 127, 2),
+ overlong(128, 16#7FF, 3),
+ overlong(16#800, 16#FFFF, 4),
+ ok.
+
+fail_range(Char, End) when Char =< End ->
+ {'EXIT', _} = (catch <<Char/utf8>>),
+ Bin = int_to_utf8(Char),
+ fail(Bin),
+ fail_range(Char+1, End);
+fail_range(_, _) -> ok.
+
+short_sequences(Char, End) ->
+ Step = (End - Char) div erlang:system_info(schedulers) + 1,
+ PidRefs = short_sequences_1(Char, Step, End),
+ [receive {'DOWN', Ref, process, Pid, Reason} -> normal=Reason end ||
+ {Pid, Ref} <- PidRefs],
+ ok.
+
+short_sequences_1(Char, Step, End) when Char =< End ->
+ CharEnd = lists:min([Char+Step-1,End]),
+ [spawn_monitor(fun() ->
+ %% io:format("~p - ~p\n", [Char, CharEnd]),
+ do_short_sequences(Char, CharEnd)
+ end)|short_sequences_1(Char+Step, Step, End)];
+short_sequences_1(_, _, _) -> [].
+
+do_short_sequences(Char, End) when Char =< End ->
+ short_sequence(Char),
+ do_short_sequences(Char+1, End);
+do_short_sequences(_, _) -> ok.
+
+short_sequence(I) ->
+ case int_to_utf8(I) of
+ <<S0:3/binary,_:8>> ->
+ <<S1:2/binary,R1:8>> = S0,
+ <<S2:1/binary,_:8>> = S1,
+ fail(S0),
+ fail(S1),
+ fail(S2),
+ fail(<<S2/binary,16#7F,R1,R1>>),
+ fail(<<S1/binary,16#7F,R1>>),
+ fail(<<S0/binary,16#7F>>);
+ <<S0:2/binary,_:8>> ->
+ <<S1:1/binary,R1:8>> = S0,
+ fail(S0),
+ fail(S1),
+ fail(<<S0/binary,16#7F>>),
+ fail(<<S1/binary,16#7F>>),
+ fail(<<S1/binary,16#7F,R1>>);
+ <<S:1/binary,_:8>> ->
+ fail(S),
+ fail(<<S/binary,16#7F>>)
+ end.
+
+overlong(Char, Last, NumBytes) when Char =< Last ->
+ overlong(Char, NumBytes),
+ overlong(Char+1, Last, NumBytes);
+overlong(_, _, _) -> ok.
+
+overlong(Char, NumBytes) when NumBytes < 5 ->
+ case int_to_utf8(Char, NumBytes) of
+ <<Char/utf8>>=Bin ->
+ ?t:fail({illegal_encoding_accepted,Bin,Char});
+ <<OtherChar/utf8>>=Bin ->
+ ?t:fail({illegal_encoding_accepted,Bin,Char,OtherChar});
+ _ -> ok
+ end,
+ overlong(Char, NumBytes+1);
+overlong(_, _) -> ok.
+
+fail(Bin) ->
+ fail_1(Bin),
+ fail_1(make_unaligned(Bin)).
+
+fail_1(<<Char/utf8>> = Bin) ->
+ ?t:fail({illegal_encoding_accepted, Bin, Char});
+fail_1(_) -> ok.
+
+%%-------------------------------------------------------------------
+
+utf16_illegal_sequences() ->
+ utf16_fail_range(16#10FFFF+1, 16#10FFFF+512), % Too large.
+ utf16_fail_range(16#D800, 16#DFFF), % Reserved for UTF-16.
+ lonely_hi_surrogate(16#D800, 16#DFFF),
+ leading_lo_surrogate(16#DC00, 16#DFFF),
+ ok.
+
+utf16_fail_range(Char, End) when Char =< End ->
+ {'EXIT', _} = (catch <<Char/big-utf16>>),
+ {'EXIT', _} = (catch <<Char/little-utf16>>),
+ utf16_fail_range(Char+1, End);
+utf16_fail_range(_, _) -> ok.
+
+lonely_hi_surrogate(Char, End) when Char =< End ->
+ BinBig = <<Char:16/big>>,
+ BinLittle = <<Char:16/little>>,
+ case {BinBig,BinLittle} of
+ {<<Bad/big-utf16>>,_} ->
+ ?t:fail({lonely_hi_surrogate_accepted,Bad});
+ {_,<<Bad/little-utf16>>} ->
+ ?t:fail({lonely_hi_surrogate_accepted,Bad});
+ {_,_} ->
+ ok
+ end,
+ lonely_hi_surrogate(Char+1, End);
+lonely_hi_surrogate(_, _) -> ok.
+
+leading_lo_surrogate(Char, End) when Char =< End ->
+ leading_lo_surrogate(Char, 16#D800, 16#DFFF),
+ leading_lo_surrogate(Char+1, End);
+leading_lo_surrogate(_, _) -> ok.
+
+leading_lo_surrogate(HiSurr, LoSurr, End) when LoSurr =< End ->
+ BinBig = <<HiSurr:16/big,LoSurr:16/big>>,
+ BinLittle = <<HiSurr:16/little,LoSurr:16/little>>,
+ case {BinBig,BinLittle} of
+ {<<Bad/big-utf16,_/bits>>,_} ->
+ ?t:fail({leading_lo_surrogate_accepted,Bad});
+ {_,<<Bad/little-utf16,_/bits>>} ->
+ ?t:fail({leading_lo_surrogate_accepted,Bad});
+ {_,_} ->
+ ok
+ end,
+ leading_lo_surrogate(HiSurr, LoSurr+1, End);
+leading_lo_surrogate(_, _, _) -> ok.
+
+%%-------------------------------------------------------------------
+
+utf32_illegal_sequences() ->
+ utf32_fail_range(16#10FFFF+1, 16#10FFFF+512), % Too large.
+ utf32_fail_range(16#D800, 16#DFFF), % Reserved for UTF-16.
+ utf32_fail_range(-100, -1),
+ ok.
+
+utf32_fail_range(Char, End) when Char =< End ->
+ {'EXIT', _} = (catch <<Char/big-utf32>>),
+ {'EXIT', _} = (catch <<Char/little-utf32>>),
+ case {<<Char:32>>,<<Char:32/little>>} of
+ {<<Unexpected/utf32>>,_} ->
+ ?t:fail(Unexpected);
+ {_,<<Unexpected/little-utf32>>} ->
+ ?t:fail(Unexpected);
+ {_,_} -> ok
+ end,
+ utf32_fail_range(Char+1, End);
+utf32_fail_range(_, _) -> ok.
+
+%%-------------------------------------------------------------------
+%% This function intentionally allows construction of UTF-8 sequence
+%% in illegal ranges.
+
+int_to_utf8(I) when I =< 16#7F ->
+ <<I>>;
+int_to_utf8(I) when I =< 16#7FF ->
+ B2 = I,
+ B1 = (I bsr 6),
+ <<1:1,1:1,0:1,B1:5,1:1,0:1,B2:6>>;
+int_to_utf8(I) when I =< 16#FFFF ->
+ B3 = I,
+ B2 = (I bsr 6),
+ B1 = (I bsr 12),
+ <<1:1,1:1,1:1,0:1,B1:4,1:1,0:1,B2:6,1:1,0:1,B3:6>>;
+int_to_utf8(I) when I =< 16#3FFFFF ->
+ B4 = I,
+ B3 = (I bsr 6),
+ B2 = (I bsr 12),
+ B1 = (I bsr 18),
+ <<1:1,1:1,1:1,1:1,0:1,B1:3,1:1,0:1,B2:6,1:1,0:1,B3:6,1:1,0:1,B4:6>>;
+int_to_utf8(I) when I =< 16#3FFFFFF ->
+ B5 = I,
+ B4 = (I bsr 6),
+ B3 = (I bsr 12),
+ B2 = (I bsr 18),
+ B1 = (I bsr 24),
+ <<1:1,1:1,1:1,1:1,1:1,0:1,B1:2,1:1,0:1,B2:6,1:1,0:1,B3:6,1:1,0:1,B4:6,
+ 1:1,0:1,B5:6>>.
+
+%% int_to_utf8(I, NumberOfBytes) -> Binary.
+%% This function can be used to construct overlong sequences.
+int_to_utf8(I, 1) ->
+ <<I>>;
+int_to_utf8(I, 2) ->
+ B2 = I,
+ B1 = (I bsr 6),
+ <<1:1,1:1,0:1,B1:5,1:1,0:1,B2:6>>;
+int_to_utf8(I, 3) ->
+ B3 = I,
+ B2 = (I bsr 6),
+ B1 = (I bsr 12),
+ <<1:1,1:1,1:1,0:1,B1:4,1:1,0:1,B2:6,1:1,0:1,B3:6>>;
+int_to_utf8(I, 4) ->
+ B4 = I,
+ B3 = (I bsr 6),
+ B2 = (I bsr 12),
+ B1 = (I bsr 18),
+ <<1:1,1:1,1:1,1:1,0:1,B1:3,1:1,0:1,B2:6,1:1,0:1,B3:6,1:1,0:1,B4:6>>.
+
+%%-------------------------------------------------------------------
+
+make_unaligned(Bin0) when is_binary(Bin0) ->
+ Bin1 = <<0:3,Bin0/binary,31:5>>,
+ Sz = byte_size(Bin0),
+ <<0:3,Bin:Sz/binary,31:5>> = id(Bin1),
+ Bin.
+
+%%-------------------------------------------------------------------
+%% Just to prevent compiler optimizations
+
+id(X) -> X.
diff --git a/lib/hipe/test/hipe_SUITE.erl b/lib/hipe/test/hipe_SUITE.erl
index 554bc972f6..a5b3924aa8 100644
--- a/lib/hipe/test/hipe_SUITE.erl
+++ b/lib/hipe/test/hipe_SUITE.erl
@@ -1,13 +1,14 @@
-%% ``The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved via the world wide web at http://www.erlang.org/.
+%% ``Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
@@ -18,9 +19,6 @@
-compile([export_all]).
-include_lib("common_test/include/ct.hrl").
-suite() ->
- [{ct_hooks, [ts_install_cth]}].
-
all() ->
[app, appup].
diff --git a/lib/hipe/test/hipe_testsuite_driver.erl b/lib/hipe/test/hipe_testsuite_driver.erl
index 5f05a716bc..a3048d907e 100644
--- a/lib/hipe/test/hipe_testsuite_driver.erl
+++ b/lib/hipe/test/hipe_testsuite_driver.erl
@@ -1,6 +1,6 @@
-module(hipe_testsuite_driver).
--export([create_all_suites/0, run/3]).
+-export([create_all_suites/1, run/3]).
-include_lib("kernel/include/file.hrl").
@@ -16,25 +16,17 @@
outputfile :: file:io_device(),
testcases :: [testcase()]}).
--spec create_all_suites() -> 'ok'.
+-spec create_all_suites([string()]) -> 'ok'.
-create_all_suites() ->
- {ok, Cwd} = file:get_cwd(),
- Suites = get_suites(Cwd),
+create_all_suites(SuitesWithSuiteSuffix) ->
+ Suites = get_suites(SuitesWithSuiteSuffix),
lists:foreach(fun create_suite/1, Suites).
--spec get_suites(file:filename()) -> [string()].
+-spec get_suites([string()]) -> [string()].
-get_suites(Dir) ->
- case file:list_dir(Dir) of
- {error, _} -> [];
- {ok, Filenames} ->
- FullFilenames = [filename:join(Dir, F) || F <- Filenames],
- Dirs = [suffix(filename:basename(F), ?suite_data) ||
- F <- FullFilenames,
- file_type(F) =:= {ok, 'directory'}],
- [S || {yes, S} <- Dirs]
- end.
+get_suites(SuitesWithSuiteSuffix) ->
+ Prefixes = [suffix(F, ?suite_suffix) || F <- SuitesWithSuiteSuffix],
+ [S || {yes, S} <- Prefixes].
suffix(String, Suffix) ->
case string:rstr(String, Suffix) of
@@ -107,7 +99,7 @@ write_suite(Suite) ->
write_header(#suite{suitename = SuiteName, outputfile = OutputFile,
testcases = TestCases}) ->
Exports = format_export(TestCases),
- TimeLimit = 2, %% with 1 it fails on some slow machines...
+ TimeLimit = 5, %% with 1 or 2 it fails on some slow machines...
io:format(OutputFile,
"%% ATTENTION!\n"
"%% This is an automatically generated file. Do not edit.\n\n"
@@ -176,7 +168,8 @@ run(TestCase, Dir, _OutDir) ->
HiPEOpts = try TestCase:hipe_options() catch error:undef -> [] end,
{ok, TestCase} = hipe:c(TestCase, HiPEOpts),
ok = TestCase:test(),
- case is_llvm_opt_available() of
+ ToLLVM = try TestCase:to_llvm() catch error:undef -> true end,
+ case ToLLVM andalso hipe:llvm_support_available() of
true ->
{ok, TestCase} = hipe:c(TestCase, [to_llvm|HiPEOpts]),
ok = TestCase:test();
@@ -186,16 +179,3 @@ run(TestCase, Dir, _OutDir) ->
%% lists:foreach(fun (DF) -> ok end, % = file:delete(DF) end,
%% [filename:join(OutDir, D) || D <- DataFiles])
%% end.
-
-
-%% This function, which is supposed to check whether the right LLVM
-%% infrastructure is available, should be probably written in a better
-%% and more portable way and moved to the hipe application.
-
-is_llvm_opt_available() ->
- OptStr = os:cmd("opt -version"),
- SubStr = "LLVM version ", N = length(SubStr),
- case string:str(OptStr, SubStr) of
- 0 -> false;
- S -> P = S + N, string:sub_string(OptStr, P, P + 2) >= "3.4"
- end.
diff --git a/lib/hipe/test/maps_SUITE_data/maps_map_size.erl b/lib/hipe/test/maps_SUITE_data/maps_map_size.erl
index 25c8e5d4c7..3cd2d90dfb 100644
--- a/lib/hipe/test/maps_SUITE_data/maps_map_size.erl
+++ b/lib/hipe/test/maps_SUITE_data/maps_map_size.erl
@@ -17,9 +17,9 @@ test() ->
false = map_is_size(M#{ "c" => 2}, 2),
%% Error cases.
- {'EXIT',{badarg,_}} = (catch map_size([])),
- {'EXIT',{badarg,_}} = (catch map_size(<<1,2,3>>)),
- {'EXIT',{badarg,_}} = (catch map_size(1)),
+ {'EXIT',{{badmap,[]},_}} = (catch map_size([])),
+ {'EXIT',{{badmap,<<1,2,3>>},_}} = (catch map_size(<<1,2,3>>)),
+ {'EXIT',{{badmap,1},_}} = (catch map_size(1)),
ok.
map_is_size(M,N) when map_size(M) =:= N -> true;
diff --git a/lib/hipe/test/maps_SUITE_data/maps_map_sort_literals.erl b/lib/hipe/test/maps_SUITE_data/maps_map_sort_literals.erl
index 31abf15d49..ccacbfe5c8 100644
--- a/lib/hipe/test/maps_SUITE_data/maps_map_sort_literals.erl
+++ b/lib/hipe/test/maps_SUITE_data/maps_map_sort_literals.erl
@@ -10,23 +10,25 @@ test() ->
false = #{ c => 1, b => 1, a => 1} < id(#{ c => 1, a => 1}),
%% key order
- true = id(#{ a => 1 }) < id(#{ b => 1}),
- false = id(#{ b => 1 }) < id(#{ a => 1}),
- true = id(#{ a => 1, b => 1, c => 1 }) < id(#{ b => 1, c => 1, d => 1}),
- true = id(#{ b => 1, c => 1, d => 1 }) > id(#{ a => 1, b => 1, c => 1}),
- true = id(#{ c => 1, b => 1, a => 1 }) < id(#{ b => 1, c => 1, d => 1}),
- true = id(#{ "a" => 1 }) < id(#{ <<"a">> => 1}),
- false = id(#{ <<"a">> => 1 }) < id(#{ "a" => 1}),
- false = id(#{ 1 => 1 }) < id(#{ 1.0 => 1}),
- false = id(#{ 1.0 => 1 }) < id(#{ 1 => 1}),
+ true = #{ a => 1 } < id(#{ b => 1}),
+ false = #{ b => 1 } < id(#{ a => 1}),
+ true = #{ a => 1, b => 1, c => 1 } < id(#{ b => 1, c => 1, d => 1}),
+ true = #{ b => 1, c => 1, d => 1 } > id(#{ a => 1, b => 1, c => 1}),
+ true = #{ c => 1, b => 1, a => 1 } < id(#{ b => 1, c => 1, d => 1}),
+ true = #{ "a" => 1 } < id(#{ <<"a">> => 1}),
+ false = #{ <<"a">> => 1 } < id(#{ "a" => 1}),
+ true = #{ 1 => 1 } < id(#{ 1.0 => 1}),
+ false = #{ 1.0 => 1 } < id(#{ 1 => 1}),
%% value order
- true = id(#{ a => 1 }) < id(#{ a => 2}),
- false = id(#{ a => 2 }) < id(#{ a => 1}),
- false = id(#{ a => 2, b => 1 }) < id(#{ a => 1, b => 3}),
- true = id(#{ a => 1, b => 1 }) < id(#{ a => 1, b => 3}),
+ true = #{ a => 1 } < id(#{ a => 2}),
+ false = #{ a => 2 } < id(#{ a => 1}),
+ false = #{ a => 2, b => 1 } < id(#{ a => 1, b => 3}),
+ true = #{ a => 1, b => 1 } < id(#{ a => 1, b => 3}),
+ false = #{ a => 1 } < id(#{ a => 1.0}),
+ false = #{ a => 1.0 } < id(#{ a => 1}),
- true = id(#{ "a" => "hi", b => 134 }) == id(#{ b => 134,"a" => "hi"}),
+ true = #{ "a" => "hi", b => 134 } == id(#{ b => 134,"a" => "hi"}),
%% lists:sort
@@ -34,7 +36,6 @@ test() ->
[#{1:=ok},#{a:=ok},#{"a":=ok},#{<<"a">>:=ok}] = lists:sort([#{"a"=>ok},#{a=>ok},#{1=>ok},#{<<"a">>=>ok}]),
[#{1:=3},#{a:=2},#{"a":=1},#{<<"a">>:=4}] = lists:sort(SortVs),
[#{1:=3},#{a:=2},#{"a":=1},#{<<"a">>:=4}] = lists:sort(lists:reverse(SortVs)),
-
ok.
%% Use this function to avoid compile-time evaluation of an expression.
diff --git a/lib/hipe/test/maps_SUITE_data/maps_put_map_assoc.erl b/lib/hipe/test/maps_SUITE_data/maps_put_map_assoc.erl
index 72ac9ce078..2fe4f204d1 100644
--- a/lib/hipe/test/maps_SUITE_data/maps_put_map_assoc.erl
+++ b/lib/hipe/test/maps_SUITE_data/maps_put_map_assoc.erl
@@ -8,7 +8,7 @@ test() ->
true = assoc_guard(#{}),
false = assoc_guard(not_a_map),
#{a := true} = assoc_update(#{}),
- {'EXIT', {badarg, [{?MODULE, assoc_update, 1, _}|_]}}
+ {'EXIT', {{badmap, not_a_map}, [{?MODULE, assoc_update, 1, _}|_]}}
= (catch assoc_update(not_a_map)),
ok = assoc_guard_clause(#{}),
{'EXIT', {function_clause, [{?MODULE, assoc_guard_clause, _, _}|_]}}
diff --git a/lib/hipe/test/maps_SUITE_data/maps_put_map_exact.erl b/lib/hipe/test/maps_SUITE_data/maps_put_map_exact.erl
index 1cfcd80180..3c85289a36 100644
--- a/lib/hipe/test/maps_SUITE_data/maps_put_map_exact.erl
+++ b/lib/hipe/test/maps_SUITE_data/maps_put_map_exact.erl
@@ -9,9 +9,9 @@ test() ->
false = exact_guard(not_a_map),
true = exact_guard(#{a => false}),
#{a := true} = exact_update(#{a => false}),
- {'EXIT', {badarg, [{?MODULE, exact_update, 1, _}|_]}}
+ {'EXIT', {{badmap, not_a_map}, [{?MODULE, exact_update, 1, _}|_]}}
= (catch exact_update(not_a_map)),
- {'EXIT', {badarg, [{?MODULE, exact_update, 1, _}|_]}}
+ {'EXIT', {{badkey, a}, [{?MODULE, exact_update, 1, _}|_]}}
= (catch exact_update(#{})),
ok = exact_guard_clause(#{a => yes}),
{'EXIT', {function_clause, [{?MODULE, exact_guard_clause, _, _}|_]}}
diff --git a/lib/hipe/test/maps_SUITE_data/maps_update_assoc.erl b/lib/hipe/test/maps_SUITE_data/maps_update_assoc.erl
index cc7c1353de..99228a1927 100644
--- a/lib/hipe/test/maps_SUITE_data/maps_update_assoc.erl
+++ b/lib/hipe/test/maps_SUITE_data/maps_update_assoc.erl
@@ -14,7 +14,7 @@ test() ->
%% Errors cases.
BadMap = id(badmap),
- {'EXIT',{badarg,_}} = (catch BadMap#{nonexisting=>val}),
+ {'EXIT',{{badmap,badmap},_}} = (catch BadMap#{nonexisting=>val}),
ok.
diff --git a/lib/hipe/test/maps_SUITE_data/maps_update_exact.erl b/lib/hipe/test/maps_SUITE_data/maps_update_exact.erl
index 6e5acb3283..1c38820a7c 100644
--- a/lib/hipe/test/maps_SUITE_data/maps_update_exact.erl
+++ b/lib/hipe/test/maps_SUITE_data/maps_update_exact.erl
@@ -21,11 +21,11 @@ test() ->
1.0 => new_val4 },
%% Errors cases.
- {'EXIT',{badarg,_}} = (catch ((id(nil))#{ a := b })),
- {'EXIT',{badarg,_}} = (catch M0#{nonexisting:=val}),
- {'EXIT',{badarg,_}} = (catch M0#{1.0:=v,1.0=>v2}),
- {'EXIT',{badarg,_}} = (catch M0#{42.0:=v,42:=v2}),
- {'EXIT',{badarg,_}} = (catch M0#{42=>v1,42.0:=v2,42:=v3}),
+ {'EXIT',{{badmap,nil},_}} = (catch ((id(nil))#{ a := b })),
+ {'EXIT',{{badkey,nonexisting},_}} = (catch M0#{nonexisting:=val}),
+ {'EXIT',{{badkey,_},_}} = (catch M0#{1.0:=v,1.0=>v2}),
+ {'EXIT',{{badkey,_},_}} = (catch M0#{42.0:=v,42:=v2}),
+ {'EXIT',{{badkey,_},_}} = (catch M0#{42=>v1,42.0:=v2,42:=v3}),
ok.
%% Use this function to avoid compile-time evaluation of an expression.
diff --git a/lib/hipe/test/maps_SUITE_data/maps_update_map_expressions.erl b/lib/hipe/test/maps_SUITE_data/maps_update_map_expressions.erl
index 181e3f18f7..213fc33d97 100644
--- a/lib/hipe/test/maps_SUITE_data/maps_update_map_expressions.erl
+++ b/lib/hipe/test/maps_SUITE_data/maps_update_map_expressions.erl
@@ -23,9 +23,9 @@ test() ->
#{ "a" := b } = F(),
- %% Error cases, FIXME: should be 'badmap'?
- {'EXIT',{badarg,_}} = (catch (id(<<>>))#{ a := 42, b => 2 }),
- {'EXIT',{badarg,_}} = (catch (id([]))#{ a := 42, b => 2 }),
+ %% Error cases.
+ {'EXIT',{{badmap,<<>>},_}} = (catch (id(<<>>))#{ a := 42, b => 2 }),
+ {'EXIT',{{badmap,[]},_}} = (catch (id([]))#{ a := 42, b => 2 }),
ok.
%% Use this function to avoid compile-time evaluation of an expression.
diff --git a/lib/hipe/test/opt_verify_SUITE.erl b/lib/hipe/test/opt_verify_SUITE.erl
new file mode 100644
index 0000000000..61952e81d7
--- /dev/null
+++ b/lib/hipe/test/opt_verify_SUITE.erl
@@ -0,0 +1,62 @@
+-module(opt_verify_SUITE).
+
+-compile([export_all]).
+
+all() ->
+ [call_elim].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ case erlang:system_info(hipe_architecture) of
+ undefined -> {skip, "HiPE not available or enabled"};
+ _ -> Config
+ end.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+call_elim_test_file(Config, FileName, Option) ->
+ PrivDir = test_server:lookup_config(priv_dir, Config),
+ TempOut = test_server:temp_name(filename:join(PrivDir, "call_elim_out")),
+ {ok, TestCase} = compile:file(FileName),
+ {ok, TestCase} = hipe:c(TestCase, [Option, {pp_range_icode, {file, TempOut}}]),
+ {ok, Icode} = file:read_file(TempOut),
+ ok = file:delete(TempOut),
+ Icode.
+
+substring_count(Icode, Substring) ->
+ substring_count(Icode, Substring, 0).
+substring_count(Icode, Substring, N) ->
+ case string:str(Icode, Substring) of
+ 0 -> N;
+ I -> substring_count(lists:nthtail(I, Icode), Substring, N+1)
+ end.
+
+call_elim() ->
+ [{doc, "Test that the call elimination optimization pass is ok"}].
+call_elim(Config) ->
+ DataDir = test_server:lookup_config(data_dir, Config),
+ F1 = filename:join(DataDir, "call_elim_test.erl"),
+ Icode1 = call_elim_test_file(Config, F1, icode_call_elim),
+ 0 = substring_count(binary:bin_to_list(Icode1), "is_key"),
+ Icode2 = call_elim_test_file(Config, F1, no_icode_call_elim),
+ true = (0 /= substring_count(binary:bin_to_list(Icode2), "is_key")),
+ F2 = filename:join(DataDir, "call_elim_test_branches_no_opt_poss.erl"),
+ Icode3 = call_elim_test_file(Config, F2, icode_call_elim),
+ 3 = substring_count(binary:bin_to_list(Icode3), "is_key"),
+ Icode4 = call_elim_test_file(Config, F2, no_icode_call_elim),
+ 3 = substring_count(binary:bin_to_list(Icode4), "is_key"),
+ F3 = filename:join(DataDir, "call_elim_test_branches_opt_poss.erl"),
+ Icode5 = call_elim_test_file(Config, F3, icode_call_elim),
+ 0 = substring_count(binary:bin_to_list(Icode5), "is_key"),
+ Icode6 = call_elim_test_file(Config, F3, no_icode_call_elim),
+ 3 = substring_count(binary:bin_to_list(Icode6), "is_key"),
+ ok.
diff --git a/lib/hipe/test/opt_verify_SUITE_data/call_elim_test.erl b/lib/hipe/test/opt_verify_SUITE_data/call_elim_test.erl
new file mode 100644
index 0000000000..8b725f8ffe
--- /dev/null
+++ b/lib/hipe/test/opt_verify_SUITE_data/call_elim_test.erl
@@ -0,0 +1,12 @@
+-module(call_elim_test).
+
+-export([test/0]).
+
+test() ->
+ true = has_1_field(#{1=>true}),
+ true = has_1_field(#{1=>"hej", b=>2}),
+ true = has_1_field(#{b=>3, 1=>4}),
+ ok.
+
+has_1_field(#{1:=_}) -> true;
+has_1_field(#{}) -> false.
diff --git a/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_no_opt_poss.erl b/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_no_opt_poss.erl
new file mode 100644
index 0000000000..7ffae86797
--- /dev/null
+++ b/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_no_opt_poss.erl
@@ -0,0 +1,32 @@
+-module(call_elim_test_branches_no_opt_poss).
+
+-export([test/1]).
+
+test(A) ->
+ if A > 0 ->
+ false = has_a_field(#{b=>true}),
+ true = has_a_field(#{b=>1, a=>"2"}),
+ false = has_a_field(#{b=>5, c=>4}),
+ false = has_tuple_field(#{{ab, 2}=><<"qq">>, 1 =>0}),
+ false = has_tuple_field(#{up =>down, {ab, 2}=>[]}),
+ false = has_tuple_field(#{{ab, 2}=>42});
+ A =< 0 ->
+ true = has_a_field(#{a=>q, 'A' =>nej}),
+ true = has_a_field(#{a=>"hej", false=>true}),
+ true = has_a_field(#{a=>3}),
+ true = has_tuple_field(#{{ab, 1}=>q, 'A' =>nej}),
+ true = has_tuple_field(#{{ab, 1}=>"hej", false=>true}),
+ true = has_tuple_field(#{{ab, 1}=>3})
+ end,
+ true = has_nil_field(#{[] =>3, b=>"seven"}),
+ true = has_nil_field(#{"seventeen"=>17}),
+ ok.
+
+has_tuple_field(#{{ab, 1}:=_}) -> true;
+has_tuple_field(#{}) -> false.
+
+has_a_field(#{a:=_}) -> true;
+has_a_field(#{}) -> false.
+
+has_nil_field(#{[]:=_}) -> true;
+has_nil_field(#{}) -> false.
diff --git a/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl b/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl
new file mode 100644
index 0000000000..c8ddfa1e75
--- /dev/null
+++ b/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl
@@ -0,0 +1,32 @@
+-module(call_elim_test_branches_opt_poss).
+
+-export([test/1]).
+
+test(A) ->
+ if A > 0 ->
+ true = has_a_field(#{a=>true}),
+ true = has_a_field(#{b=>1, a=>"2"}),
+ true = has_a_field(#{a=>5, c=>4}),
+ true = has_tuple_field(#{{ab, 1}=><<"qq">>, 1 =>0}),
+ true = has_tuple_field(#{up =>down, {ab, 1}=>[]}),
+ true = has_tuple_field(#{{ab, 1}=>42});
+ A =< 0 ->
+ true = has_a_field(#{a=>q, 'A' =>nej}),
+ true = has_a_field(#{a=>"hej", false=>true}),
+ true = has_a_field(#{a=>3}),
+ true = has_tuple_field(#{{ab, 1}=>q, 'A' =>nej}),
+ true = has_tuple_field(#{{ab, 1}=>"hej", false=>true}),
+ true = has_tuple_field(#{{ab, 1}=>3})
+ end,
+ true = has_nil_field(#{[] =>3, b =>"seven"}),
+ true = has_nil_field(#{"seventeen"=>17, []=>nil}),
+ ok.
+
+has_tuple_field(#{{ab, 1}:=_}) -> true;
+has_tuple_field(#{}) -> false.
+
+has_a_field(#{a:=_}) -> true;
+has_a_field(#{}) -> false.
+
+has_nil_field(#{[]:=_}) -> true;
+has_nil_field(#{}) -> false.
diff --git a/lib/hipe/test/sanity_SUITE_data/sanity_comp_timeout.erl b/lib/hipe/test/sanity_SUITE_data/sanity_comp_timeout.erl
new file mode 100644
index 0000000000..9f0830574f
--- /dev/null
+++ b/lib/hipe/test/sanity_SUITE_data/sanity_comp_timeout.erl
@@ -0,0 +1,28 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%----------------------------------------------------------------------
+%%% Author: Kostis Sagonas
+%%%
+%%% Tests that when the native code compilation times out or gets killed
+%%% for some other reason, the parent process does not also get killed.
+%%%
+%%% Problem discovered by Bjorn G. on 1/12/2003 and fixed by Kostis.
+%%%----------------------------------------------------------------------
+
+-module(sanity_comp_timeout).
+
+-export([test/0, to_llvm/0]).
+
+test() ->
+ ok = write_dummy_mod(),
+ error_logger:tty(false), % disable printouts of error reports
+ Self = self(), % get the parent process
+ c:c(dummy_mod, [native, {hipe, [{timeout, 1}]}]), % This will kill the process
+ Self = self(), % make sure the parent process stays the same
+ ok.
+
+to_llvm() -> false.
+
+write_dummy_mod() ->
+ Prog = <<"-module(dummy_mod).\n-export([test/0]).\ntest() -> ok.\n">>,
+ ok = file:write_file("dummy_mod.erl", Prog).
+
diff --git a/lib/hipe/test/sanity_SUITE_data/sanity_no_zombies.erl b/lib/hipe/test/sanity_SUITE_data/sanity_no_zombies.erl
new file mode 100644
index 0000000000..87e746042e
--- /dev/null
+++ b/lib/hipe/test/sanity_SUITE_data/sanity_no_zombies.erl
@@ -0,0 +1,21 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%----------------------------------------------------------------------
+%%% Author: Per Gustafsson
+%%%
+%%% Checks that HiPE's concurrent compilation does not leave any zombie
+%%% processes around after compilation has finished.
+%%%
+%%% This was a bug reported on erlang-bugs (Oct 25, 2007).
+%%%----------------------------------------------------------------------
+
+-module(sanity_no_zombies).
+
+-export([test/0, to_llvm/0]).
+
+test() ->
+ L = length(processes()),
+ hipe:c(?MODULE, [concurrent_comp]), % force concurrent compilation
+ L = length(processes()),
+ ok.
+
+to_llvm() -> false.
diff --git a/lib/hipe/tools/Makefile b/lib/hipe/tools/Makefile
index ed80eb075b..7a62896c31 100644
--- a/lib/hipe/tools/Makefile
+++ b/lib/hipe/tools/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2012. All Rights Reserved.
+# Copyright Ericsson AB 2002-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -64,7 +65,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += -Werror +warn_export_vars +warn_missing_spec +warn_untyped_record
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/tools/hipe_jit.erl b/lib/hipe/tools/hipe_jit.erl
index 0ac84388ae..ffe0e440e9 100644
--- a/lib/hipe/tools/hipe_jit.erl
+++ b/lib/hipe/tools/hipe_jit.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/tools/hipe_profile.erl b/lib/hipe/tools/hipe_profile.erl
index ea6b1fb42c..9b9c0d6aad 100644
--- a/lib/hipe/tools/hipe_profile.erl
+++ b/lib/hipe/tools/hipe_profile.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/tools/hipe_timer.erl b/lib/hipe/tools/hipe_timer.erl
index 03cc358f17..72aa25d440 100644
--- a/lib/hipe/tools/hipe_timer.erl
+++ b/lib/hipe/tools/hipe_timer.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -46,27 +47,27 @@ tr(F) ->
{R,{WT-EWT,(RT-ERT)/1000}}.
empty_time() ->
- {WT1,WT2,WT3} = erlang:now(),
+ WTA = erlang:monotonic_time(),
{A,_} = erlang:statistics(runtime),
- {WT12,WT22,WT32} = erlang:now(),
+ WTB = erlang:monotonic_time(),
{B,_} = erlang:statistics(runtime),
- {(WT12-WT1)*1000000+(WT22-WT2)+(WT32-WT3)/1000000,B-A}.
+ {(WTB-WTA)/erlang:convert_time_unit(1, seconds, native),B-A}.
time(F) ->
- {WT1,WT2,WT3} = erlang:now(),
+ WTA = erlang:monotonic_time(),
{A,_} = erlang:statistics(runtime),
F(),
- {WT12,WT22,WT32} = erlang:now(),
+ WTB = erlang:monotonic_time(),
{B,_} = erlang:statistics(runtime),
- {(WT12-WT1)*1000000+(WT22-WT2)+(WT32-WT3)/1000000,B-A}.
+ {(WTB-WTA)/erlang:convert_time_unit(1, seconds, native),B-A}.
timer(F) ->
- {WT1,WT2,WT3} = erlang:now(),
+ WTA = erlang:monotonic_time(),
{A,_} = erlang:statistics(runtime),
R = F(),
- {WT12,WT22,WT32} = erlang:now(),
+ WTB = erlang:monotonic_time(),
{B,_} = erlang:statistics(runtime),
- {R,{(WT12-WT1)*1000000+(WT22-WT2)+(WT32-WT3)/1000000,B-A}}.
+ {R,{(WTB-WTA)/erlang:convert_time_unit(1, seconds, native),B-A}}.
advanced(_Fun, I) when I < 2 -> false;
advanced(Fun, Iterations) ->
diff --git a/lib/hipe/util/Makefile b/lib/hipe/util/Makefile
index a5ee232057..66e9421c25 100644
--- a/lib/hipe/util/Makefile
+++ b/lib/hipe/util/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -68,7 +69,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += -Werror +warn_export_vars +warn_missing_spec +warn_untyped_record
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/util/hipe_digraph.erl b/lib/hipe/util/hipe_digraph.erl
index 01b1f8c77c..7446836926 100644
--- a/lib/hipe/util/hipe_digraph.erl
+++ b/lib/hipe/util/hipe_digraph.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/util/hipe_dot.erl b/lib/hipe/util/hipe_dot.erl
index 94f7fd60cc..53e474db42 100644
--- a/lib/hipe/util/hipe_dot.erl
+++ b/lib/hipe/util/hipe_dot.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
+%%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/util/hipe_timing.erl b/lib/hipe/util/hipe_timing.erl
index 191db497e2..bf8a08dee5 100644
--- a/lib/hipe/util/hipe_timing.erl
+++ b/lib/hipe/util/hipe_timing.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/util/hipe_vectors.erl b/lib/hipe/util/hipe_vectors.erl
index d153f3a50d..7f6c8e91c2 100644
--- a/lib/hipe/util/hipe_vectors.erl
+++ b/lib/hipe/util/hipe_vectors.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/util/hipe_vectors.hrl b/lib/hipe/util/hipe_vectors.hrl
index 5e24db238d..d4556e9dc4 100644
--- a/lib/hipe/util/hipe_vectors.hrl
+++ b/lib/hipe/util/hipe_vectors.hrl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index 60b4e0559b..e61c1a042c 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.11.3
+HIPE_VSN = 3.15.1
diff --git a/lib/hipe/x86/Makefile b/lib/hipe/x86/Makefile
index 3602949944..93f8b955dd 100644
--- a/lib/hipe/x86/Makefile
+++ b/lib/hipe/x86/Makefile
@@ -1,18 +1,19 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
+# Copyright Ericsson AB 2001-2016. All Rights Reserved.
#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
# %CopyrightEnd%
#
@@ -83,7 +84,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars
+ERL_COMPILE_FLAGS += -Werror +warn_export_vars
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/x86/hipe_rtl_to_x86.erl b/lib/hipe/x86/hipe_rtl_to_x86.erl
index 36da2f4d44..d13f63b1d9 100644
--- a/lib/hipe/x86/hipe_rtl_to_x86.erl
+++ b/lib/hipe/x86/hipe_rtl_to_x86.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/x86/hipe_x86.erl b/lib/hipe/x86/hipe_x86.erl
index 3298151366..33d7f77cf1 100644
--- a/lib/hipe/x86/hipe_x86.erl
+++ b/lib/hipe/x86/hipe_x86.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/x86/hipe_x86.hrl b/lib/hipe/x86/hipe_x86.hrl
index 3d22fb381f..ef99bf90d9 100644
--- a/lib/hipe/x86/hipe_x86.hrl
+++ b/lib/hipe/x86/hipe_x86.hrl
@@ -1,18 +1,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/x86/hipe_x86_assemble.erl b/lib/hipe/x86/hipe_x86_assemble.erl
index 3f756769c4..e21223a5b1 100644
--- a/lib/hipe/x86/hipe_x86_assemble.erl
+++ b/lib/hipe/x86/hipe_x86_assemble.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
@@ -82,7 +83,7 @@ assemble(CompiledCode, Closures, Exports, Options) ->
DataRelocs = hipe_pack_constants:mk_data_relocs(RefsFromConsts, LabelMap),
SSE = hipe_pack_constants:slim_sorted_exportmap(ExportMap,Closures,Exports),
SlimRefs = hipe_pack_constants:slim_refs(AccRefs),
- Bin = term_to_binary([{?VERSION_STRING(),?HIPE_SYSTEM_CRC},
+ Bin = term_to_binary([{?VERSION_STRING(),?HIPE_ERTS_CHECKSUM},
ConstAlign, ConstSize,
SC,
DataRelocs, % nee LM, LabelMap
diff --git a/lib/hipe/x86/hipe_x86_cfg.erl b/lib/hipe/x86/hipe_x86_cfg.erl
index d15dcc061a..ab40b68580 100644
--- a/lib/hipe/x86/hipe_x86_cfg.erl
+++ b/lib/hipe/x86/hipe_x86_cfg.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/x86/hipe_x86_defuse.erl b/lib/hipe/x86/hipe_x86_defuse.erl
index 3387f77595..9cba6cbe4b 100644
--- a/lib/hipe/x86/hipe_x86_defuse.erl
+++ b/lib/hipe/x86/hipe_x86_defuse.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/x86/hipe_x86_encode.erl b/lib/hipe/x86/hipe_x86_encode.erl
index db7f53ad26..3b7be86608 100644
--- a/lib/hipe/x86/hipe_x86_encode.erl
+++ b/lib/hipe/x86/hipe_x86_encode.erl
@@ -1,18 +1,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/x86/hipe_x86_frame.erl b/lib/hipe/x86/hipe_x86_frame.erl
index 0a3317a369..8851ead250 100644
--- a/lib/hipe/x86/hipe_x86_frame.erl
+++ b/lib/hipe/x86/hipe_x86_frame.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/x86/hipe_x86_liveness.erl b/lib/hipe/x86/hipe_x86_liveness.erl
index 6874b05a59..ce46ec920e 100644
--- a/lib/hipe/x86/hipe_x86_liveness.erl
+++ b/lib/hipe/x86/hipe_x86_liveness.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/x86/hipe_x86_main.erl b/lib/hipe/x86/hipe_x86_main.erl
index f45a49ca0a..13b0bb6b28 100644
--- a/lib/hipe/x86/hipe_x86_main.erl
+++ b/lib/hipe/x86/hipe_x86_main.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/x86/hipe_x86_postpass.erl b/lib/hipe/x86/hipe_x86_postpass.erl
index a95a8745ba..4515822a34 100644
--- a/lib/hipe/x86/hipe_x86_postpass.erl
+++ b/lib/hipe/x86/hipe_x86_postpass.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2003-2013. All Rights Reserved.
+%%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
@@ -94,7 +95,8 @@ peep([I=#move{src=#x86_temp{reg=Src}, dst=#x86_temp{reg=Dst}},
%% ElimBinALMDouble
%% ----------------
-peep([Move=#move{src=Src, dst=Dst}, Alu=#alu{src=Src, dst=Dst}|Insns], Res, Lst) ->
+peep([Move=#move{src=Src, dst=Dst}, Alu=#alu{src=Src, dst=Dst}|Insns], Res, Lst)
+ when not is_record(Dst, x86_mem) ->
peep([Alu#alu{src=Dst}|Insns], [Move|Res], [elimBinALMDouble|Lst]);
diff --git a/lib/hipe/x86/hipe_x86_pp.erl b/lib/hipe/x86/hipe_x86_pp.erl
index 555e21a446..9352cf5dbf 100644
--- a/lib/hipe/x86/hipe_x86_pp.erl
+++ b/lib/hipe/x86/hipe_x86_pp.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/x86/hipe_x86_ra.erl b/lib/hipe/x86/hipe_x86_ra.erl
index d50b9aabad..f66961a7a7 100644
--- a/lib/hipe/x86/hipe_x86_ra.erl
+++ b/lib/hipe/x86/hipe_x86_ra.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/x86/hipe_x86_ra_finalise.erl b/lib/hipe/x86/hipe_x86_ra_finalise.erl
index 10b4df05d2..5dd75cb7ae 100644
--- a/lib/hipe/x86/hipe_x86_ra_finalise.erl
+++ b/lib/hipe/x86/hipe_x86_ra_finalise.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/x86/hipe_x86_ra_ls.erl b/lib/hipe/x86/hipe_x86_ra_ls.erl
index ab7b6708ad..3e34433111 100644
--- a/lib/hipe/x86/hipe_x86_ra_ls.erl
+++ b/lib/hipe/x86/hipe_x86_ra_ls.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/x86/hipe_x86_ra_naive.erl b/lib/hipe/x86/hipe_x86_ra_naive.erl
index e9b99cd2c5..0ef4ef0a04 100644
--- a/lib/hipe/x86/hipe_x86_ra_naive.erl
+++ b/lib/hipe/x86/hipe_x86_ra_naive.erl
@@ -2,18 +2,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/x86/hipe_x86_ra_postconditions.erl b/lib/hipe/x86/hipe_x86_ra_postconditions.erl
index 6d7e90df43..0a70bd1d22 100644
--- a/lib/hipe/x86/hipe_x86_ra_postconditions.erl
+++ b/lib/hipe/x86/hipe_x86_ra_postconditions.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/x86/hipe_x86_ra_x87_ls.erl b/lib/hipe/x86/hipe_x86_ra_x87_ls.erl
index 6bdb08c6fb..1ee76e5948 100644
--- a/lib/hipe/x86/hipe_x86_ra_x87_ls.erl
+++ b/lib/hipe/x86/hipe_x86_ra_x87_ls.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/x86/hipe_x86_registers.erl b/lib/hipe/x86/hipe_x86_registers.erl
index 1cfa095995..179d734501 100644
--- a/lib/hipe/x86/hipe_x86_registers.erl
+++ b/lib/hipe/x86/hipe_x86_registers.erl
@@ -1,18 +1,19 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%%
-%%% The contents of this file are subject to the Erlang Public License,
-%%% Version 1.1, (the "License"); you may not use this file except in
-%%% compliance with the License. You should have received a copy of the
-%%% Erlang Public License along with this software. If not, it can be
-%%% retrieved online at http://www.erlang.org/.
-%%%
-%%% Software distributed under the License is distributed on an "AS IS"
-%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%%% the License for the specific language governing rights and limitations
-%%% under the License.
+%%% Licensed under the Apache License, Version 2.0 (the "License");
+%%% you may not use this file except in compliance with the License.
+%%% You may obtain a copy of the License at
+%%%
+%%% http://www.apache.org/licenses/LICENSE-2.0
+%%%
+%%% Unless required by applicable law or agreed to in writing, software
+%%% distributed under the License is distributed on an "AS IS" BASIS,
+%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%%% See the License for the specific language governing permissions and
+%%% limitations under the License.
%%%
%%% %CopyrightEnd%
%%%
diff --git a/lib/hipe/x86/hipe_x86_spill_restore.erl b/lib/hipe/x86/hipe_x86_spill_restore.erl
index cd927669fb..f17b91f33b 100644
--- a/lib/hipe/x86/hipe_x86_spill_restore.erl
+++ b/lib/hipe/x86/hipe_x86_spill_restore.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
diff --git a/lib/hipe/x86/hipe_x86_x87.erl b/lib/hipe/x86/hipe_x86_x87.erl
index 6ef14abdbb..e874490252 100644
--- a/lib/hipe/x86/hipe_x86_x87.erl
+++ b/lib/hipe/x86/hipe_x86_x87.erl
@@ -2,18 +2,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%