diff options
author | Martin Liska <mliska@suse.cz> | 2021-10-21 11:51:37 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2021-10-21 11:51:37 +0200 |
commit | 9345234b2a80fbb26342f8c72aa8714d673c7dad (patch) | |
tree | d0c6a2f68a3f04ec322ebb6599f3e929d90ae809 | |
parent | 39887dd2c2c81cf3e98466827d59cafda279a258 (diff) | |
parent | 7878981f1d44b4c9bb6c4a3137b37f06c725b73d (diff) | |
download | gcc-9345234b2a80fbb26342f8c72aa8714d673c7dad.zip gcc-9345234b2a80fbb26342f8c72aa8714d673c7dad.tar.gz gcc-9345234b2a80fbb26342f8c72aa8714d673c7dad.tar.bz2 |
Merge branch 'master' into devel/sphinx
537 files changed, 33072 insertions, 9311 deletions
@@ -1,3 +1,7 @@ +2021-10-19 Clément Chigot <clement.chigot@atos.net> + + * MAINTAINERS: Add myself for write after approval. + 2021-10-12 Eric Gallager <egallager@gcc.gnu.org> * Makefile.def: Mark libcody, libdecnumber, diff --git a/MAINTAINERS b/MAINTAINERS index bf4006c..b22f930 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -352,6 +352,7 @@ Gabriel Charette <gchare@google.com> Chandra Chavva <cchavva@redhat.com> Dehao Chen <dehao@google.com> Fabien Chêne <fabien@gcc.gnu.org> +Clément Chigot <clement.chigot@atos.net> Harshit Chopra <harshit@google.com> Tamar Christina <tamar.christina@arm.com> Eric Christopher <echristo@gmail.com> diff --git a/contrib/ChangeLog b/contrib/ChangeLog index 156a61b..d36e6f1 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,13 @@ +2021-10-20 H.J. Lu <hjl.tools@gmail.com> + + * gcc-changelog/git_commit.py (ignored_prefixes): Add libffi/. + +2021-10-18 Martin Liska <mliska@suse.cz> + + * gcc-changelog/git_commit.py: Update location of + 'bad parentheses wrapping'. + * gcc-changelog/test_email.py: Test it. + 2021-10-02 Martin Liska <mliska@suse.cz> * filter-clang-warnings.py: Filter out -Wtautological-compare diff --git a/contrib/gcc-changelog/git_commit.py b/contrib/gcc-changelog/git_commit.py index cf29f76..60377b6 100755 --- a/contrib/gcc-changelog/git_commit.py +++ b/contrib/gcc-changelog/git_commit.py @@ -134,6 +134,7 @@ ignored_prefixes = { 'gcc/go/gofrontend/', 'gcc/testsuite/gdc.test/', 'gcc/testsuite/go.test/test/', + 'libffi/', 'libgo/', 'libphobos/libdruntime/', 'libphobos/src/', diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8175862..115f32e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,510 @@ +2021-10-20 Alex Coplan <alex.coplan@arm.com> + + * calls.c (initialize_argument_information): Remove some dead + code, remove handling for function_arg returning const_int. + * doc/tm.texi: Delete documentation for unused target hooks. + * doc/tm.texi.in: Likewise. + * target.def (load_bounds_for_arg): Delete. + (store_bounds_for_arg): Delete. + (load_returned_bounds): Delete. + (store_returned_bounds): Delete. + * targhooks.c (default_load_bounds_for_arg): Delete. + (default_store_bounds_for_arg): Delete. + (default_load_returned_bounds): Delete. + (default_store_returned_bounds): Delete. + * targhooks.h (default_load_bounds_for_arg): Delete. + (default_store_bounds_for_arg): Delete. + (default_load_returned_bounds): Delete. + (default_store_returned_bounds): Delete. + +2021-10-20 Jonathan Wakely <jwakely@redhat.com> + + * doc/extend.texi (Basic Asm): Clarify that asm is not an + extension in C++. + * doc/invoke.texi (-fno-asm): Fix description for C++. + +2021-10-20 Jonathan Wakely <jwakely@redhat.com> + + * doc/install.texi: Remove link to old.html + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-simd.md (*aarch64_cmtst_same_<mode>): New. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-simd.md (*aarch64_narrow_trunc<mode>): New. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-simd.md (aarch64_simd_ashr<mode>): Add case cmp + case. + * config/aarch64/constraints.md (D1): New. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-simd.md + (*aarch64_<srn_op>topbits_shuffle<mode>_le): New. + (*aarch64_topbits_shuffle<mode>_le): New. + (*aarch64_<srn_op>topbits_shuffle<mode>_be): New. + (*aarch64_topbits_shuffle<mode>_be): New. + * config/aarch64/predicates.md + (aarch64_simd_shift_imm_vec_exact_top): New. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-simd.md (*aarch64_<srn_op>shrn<mode>_vect, + *aarch64_<srn_op>shrn<mode>2_vect_le, + *aarch64_<srn_op>shrn<mode>2_vect_be): New. + * config/aarch64/iterators.md (srn_op): New. + +2021-10-20 Chung-Lin Tang <cltang@codesourcery.com> + + * omp-low.c (omp_copy_decl_2): For !ctx, use record_vars to add new copy + as local variable. + (scan_sharing_clauses): Place copy of OMP_CLAUSE_IN_REDUCTION decl in + ctx->outer instead of ctx. + +2021-10-20 Martin Liska <mliska@suse.cz> + + Revert: + 2021-10-19 Martin Liska <mliska@suse.cz> + + PR target/102374 + * config/i386/i386-options.c (ix86_valid_target_attribute_inner_p): Strip whitespaces. + * system.h (strip_whilespaces): New function. + +2021-10-20 Martin Liska <mliska@suse.cz> + + Revert: + 2021-10-19 Martin Liska <mliska@suse.cz> + + PR target/102375 + * config/aarch64/aarch64.c (aarch64_process_one_target_attr): + Strip whitespaces. + +2021-10-20 Wilco Dijkstra <wdijkstr@arm.com> + + * config/aarch64/aarch64.c (aarch64_case_values_threshold): + Change to 8 with -Os, 11 otherwise. + +2021-10-20 Wilco Dijkstra <wdijkstr@arm.com> + + * config/aarch64/aarch64.c (neoversev1_tunings): + Enable AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND. + (neoversen2_tunings): Likewise. + +2021-10-20 Wilco Dijkstra <wdijkstr@arm.com> + + PR target/100966 + * config/aarch64/aarch64.md (frint_pattern): Update comment. + * config/aarch64/aarch64-simd-builtins.def: Change frintn to roundeven. + * config/aarch64/arm_fp16.h: Change frintn to roundeven. + * config/aarch64/arm_neon.h: Likewise. + * config/aarch64/iterators.md (frint_pattern): Use roundeven for FRINTN. + +2021-10-20 Martin Liska <mliska@suse.cz> + + * config/arm/arm.c (arm_unwind_emit_sequence): Do not declare + already declared global variable. + (arm_unwind_emit_set): Use out_file as function argument. + (arm_unwind_emit): Likewise. + * config/darwin.c (machopic_output_data_section_indirection): Likewise. + (machopic_output_stub_indirection): Likewise. + (machopic_output_indirection): Likewise. + (machopic_finish): Likewise. + * config/i386/i386.c (ix86_asm_output_function_label): Likewise. + * config/i386/winnt.c (i386_pe_seh_unwind_emit): Likewise. + * config/ia64/ia64.c (process_epilogue): Likewise. + (process_cfa_adjust_cfa): Likewise. + (process_cfa_register): Likewise. + (process_cfa_offset): Likewise. + (ia64_asm_unwind_emit): Likewise. + * config/s390/s390.c (s390_asm_output_function_label): Likewise. + +2021-10-20 Andre Simoes Dias Vieira <andre.simoesdiasvieira@arm.com> + + * config/aarch64/aarch64-builtins.c + (aarch64_general_gimple_fold_builtin): + lower vld1 and vst1 variants of the neon builtins + * config/aarch64/aarch64-protos.h: + (aarch64_general_gimple_fold_builtin): Add gsi parameter. + * config/aarch64/aarch64.c (aarch64_general_gimple_fold_builtin): + Likwise. + +2021-10-20 Andre Simoes Dias Vieira <andre.simoesdiasvieira@arm.com> + + * match.pd: Generate IFN_TRUNC. + +2021-10-20 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102853 + * tree-data-ref.c (split_constant_offset_1): Bail out + immediately if the expression traps on overflow. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + + * tree-ssa-threadbackward.c (back_threader::~back_threader): Remove. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + + * tree-ssa-threadupdate.c (back_jt_path_registry::adjust_paths_after_duplication): + Remove superflous debugging message. + (back_jt_path_registry::duplicate_thread_path): Same. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + + * tree-ssa-threadbackward.c (back_threader_registry::back_threader_registry): + Remove. + (back_threader_registry::register_path): Remove m_threaded_paths. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/102814 + * doc/invoke.texi: Document --param=max-fsm-thread-length. + * params.opt: Add --param=max-fsm-thread-length. + * tree-ssa-threadbackward.c + (back_threader_profitability::profitable_path_p): Fail on paths + longer than max-fsm-thread-length. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + PR middle-end/102764 + * cfgexpand.c (expand_gimple_basic_block): Disregard a final debug + statement to reset the current location for the outgoing edges. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + Richard Biener <rguenther@suse.de> + + * tree-ssa-threadupdate.c (cancel_thread): Dump threading reason + on the same line as the threading cancellation. + (jt_path_registry::cancel_invalid_paths): Avoid rotating loops. + Avoid threading through loop headers where the path remains in the + loop. + +2021-10-20 Siddhesh Poyarekar <siddhesh@gotplt.org> + + * tree-object-size.c (unknown): Make into a function. Adjust + all uses. + (unknown_object_size): Simplify implementation. + +2021-10-20 Hongtao Liu <hongtao.liu@intel.com> + Kewen Lin <linkw@linux.ibm.com> + + * doc/sourcebuild.texi (Effective-Target Keywords): Document + vect_slp_v2qi_store, vect_slp_v4qi_store, vect_slp_v8qi_store, + vect_slp_v16qi_store, vect_slp_v2hi_store, + vect_slp_v4hi_store, vect_slp_v2si_store, vect_slp_v4si_store. + +2021-10-19 Jonathan Wakely <jwakely@redhat.com> + + * doc/extend.texi (Basic PowerPC Built-in Functions): Fix typo. + +2021-10-19 Paul A. Clarke <pc@us.ibm.com> + + PR target/101893 + PR target/102719 + * config/rs6000/emmintrin.h: Guard POWER8 intrinsics. + * config/rs6000/pmmintrin.h: Same. + * config/rs6000/smmintrin.h: Same. + * config/rs6000/tmmintrin.h: Same. + +2021-10-19 Paul A. Clarke <pc@us.ibm.com> + + * config.gcc (extra_headers): Add nmmintrin.h. + +2021-10-19 Richard Biener <rguenther@suse.de> + + * tree-vectorizer.h (vect_supportable_dr_alignment): Add + misalignment parameter. + * tree-vect-data-refs.c (vect_get_peeling_costs_all_drs): + Do not change DR_MISALIGNMENT in place, instead pass the + adjusted misalignment to vect_supportable_dr_alignment. + (vect_peeling_supportable): Likewise. + (vect_peeling_hash_get_lowest_cost): Adjust. + (vect_enhance_data_refs_alignment): Likewise. + (vect_vfa_access_size): Likewise. + (vect_supportable_dr_alignment): Add misalignment + parameter and simplify. + * tree-vect-stmts.c (get_negative_load_store_type): Adjust. + (get_group_load_store_type): Likewise. + (get_load_store_type): Likewise. + +2021-10-19 Clément Chigot <clement.chigot@atos.net> + + * config/rs6000/rs6000.c (rs6000_xcoff_file_end): Move + __tls_get_addr reference to .text csect. + +2021-10-19 Martin Liska <mliska@suse.cz> + + PR target/102375 + * config/aarch64/aarch64.c (aarch64_process_one_target_attr): + Strip whitespaces. + +2021-10-19 Richard Biener <rguenther@suse.de> + + * tree-vectorizer.h (vect_get_store_cost): Adjust signature. + (vect_get_load_cost): Likewise. + * tree-vect-data-refs.c (vect_get_data_access_cost): Get + alignment support scheme and misalignment as arguments + and pass them down. + (vect_get_peeling_costs_all_drs): Compute that info here + and note that we shouldn't need to. + * tree-vect-stmts.c (vect_model_store_cost): Get + alignment support scheme and misalignment as arguments. + (vect_get_store_cost): Likewise. + (vect_model_load_cost): Likewise. + (vect_get_load_cost): Likewise. + (vectorizable_store): Pass down alignment support scheme + and misalignment to costing. + (vectorizable_load): Likewise. + +2021-10-19 Richard Biener <rguenther@suse.de> + + * tree-vect-stmts.c (get_negative_load_store_type): Add + offset output parameter and initialize it. + (get_group_load_store_type): Likewise. + (get_load_store_type): Likewise. + (vectorizable_store): Use offset as computed by + get_load_store_type. + (vectorizable_load): Likewise. + +2021-10-19 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102827 + * tree-if-conv.c (predicate_statements): Add pe parameter + and use that edge to insert invariant stmts on. + (combine_blocks): Pass through pe. + (tree_if_conversion): Compute the edge to insert invariant + stmts on and pass it along. + +2021-10-19 Roger Sayle <roger@nextmovesoftware.com> + + PR target/102785 + * config/bfin/bfin.md (addsubv2hi3, subaddv2hi3, ssaddsubv2hi3, + sssubaddv2hi3): Swap the order of operators in vec_concat. + +2021-10-19 Xionghu Luo <luoxhu@linux.ibm.com> + + * config/rs6000/altivec.md (*altivec_vmrghb_internal): Delete. + (altivec_vmrghb_direct): New. + (*altivec_vmrghh_internal): Delete. + (altivec_vmrghh_direct): New. + (*altivec_vmrghw_internal): Delete. + (altivec_vmrghw_direct_<mode>): New. + (altivec_vmrghw_direct): Delete. + (*altivec_vmrglb_internal): Delete. + (altivec_vmrglb_direct): New. + (*altivec_vmrglh_internal): Delete. + (altivec_vmrglh_direct): New. + (*altivec_vmrglw_internal): Delete. + (altivec_vmrglw_direct_<mode>): New. + (altivec_vmrglw_direct): Delete. + * config/rs6000/rs6000-p8swap.c (rtx_is_swappable_p): Adjust. + * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): + Adjust. + * config/rs6000/vsx.md (vsx_xxmrghw_<mode>): Adjust. + (vsx_xxmrglw_<mode>): Adjust. + +2021-10-19 Aldy Hernandez <aldyh@redhat.com> + + * passes.def: Change threading comment before pass_ccp pass. + +2021-10-19 Haochen Gui <guihaoc@gcc.gnu.org> + + * config/rs6000/rs6000-call.c (altivec_expand_lxvr_builtin): + Modify the expansion for sign extension. All extensions are done + within VSX registers. + +2021-10-19 Richard Biener <rguenther@suse.de> + + * tree-vect-stmts.c (get_group_load_store_type): Add + misalignment output parameter and initialize it. + (get_group_load_store_type): Likewise. + (vectorizable_store): Remove now redundant queries. + (vectorizable_load): Likewise. + +2021-10-19 Richard Biener <rguenther@suse.de> + + * tree-vectorizer.h (vect_supportable_dr_alignment): Remove + check_aligned argument. + * tree-vect-data-refs.c (vect_supportable_dr_alignment): + Likewise. + (vect_peeling_hash_insert): Add supportable_if_not_aligned + argument and do not call vect_supportable_dr_alignment here. + (vect_peeling_supportable): Adjust. + (vect_enhance_data_refs_alignment): Compute whether the + access is supported with different alignment here and + pass that down to vect_peeling_hash_insert. + (vect_vfa_access_size): Adjust. + * tree-vect-stmts.c (vect_get_store_cost): Likewise. + (vect_get_load_cost): Likewise. + (get_negative_load_store_type): Likewise. + (get_group_load_store_type): Likewise. + (get_load_store_type): Likewise. + +2021-10-19 Martin Liska <mliska@suse.cz> + + PR target/102374 + * config/i386/i386-options.c (ix86_valid_target_attribute_inner_p): Strip whitespaces. + * system.h (strip_whilespaces): New function. + +2021-10-19 dianhong xu <dianhong.xu@intel.com> + + * config/i386/avx512fp16intrin.h: + (_mm512_set1_pch): New intrinsic. + * config/i386/avx512fp16vlintrin.h: + (_mm256_set1_pch): New intrinsic. + (_mm_set1_pch): Ditto. + +2021-10-18 Andrew MacLeod <amacleod@redhat.com> + + PR tree-optimization/102796 + * gimple-range.cc (gimple_ranger::range_on_edge): Process EH edges + normally. Return get_tree_range for non gimple_range_ssa_p names. + (gimple_ranger::range_of_stmt): Use get_tree_range for non + gimple_range_ssa_p names. + +2021-10-18 UroÅ¡ Bizjak <ubizjak@gmail.com> + + PR target/102761 + * config/i386/i386.c (ix86_print_operand_address): + Error out for non-address_operand asm operands. + +2021-10-18 Richard Biener <rguenther@suse.de> + + * tree-vect-data-refs.c (vect_peeling_hash_insert): Do + not auto-convert dr_alignment_support to bool. + (vect_peeling_supportable): Likewise. + (vect_enhance_data_refs_alignment): Likewise. + (vect_supportable_dr_alignment): Commonize read/write case. + * tree-vect-stmts.c (vect_get_store_cost): Use + dr_alignment_support, not int, for the vect_supportable_dr_alignment + result. + (vect_get_load_cost): Likewise. + +2021-10-18 Siddhesh Poyarekar <siddhesh@gotplt.org> + + * tree-object-size.c (object_sizes_execute): Consolidate LHS + null check and do it early. + +2021-10-18 Richard Biener <rguenther@suse.de> + + * tree-vect-stmts.c (vectorizable_store): Use the + computed alignment scheme instead of querying + aligned_access_p. + +2021-10-18 Richard Biener <rguenther@suse.de> + + * tree-vect-stmts.c (vectorizable_store): Do not recompute + alignment scheme already determined by get_load_store_type. + +2021-10-18 Aldy Hernandez <aldyh@redhat.com> + + * tree-ssa-threadbackward.c (class pass_thread_jumps_full): + Clone corresponding pass. + +2021-10-18 Roger Sayle <roger@nextmovesoftware.com> + + * combine.c (recog_for_combine): For an unrecognized move/set of + a constant, try force_const_mem to place it in the constant pool. + * cse.c (constant_pool_entries_cost, constant_pool_entries_regcost): + Delete global variables (that are no longer assigned a cost value). + (cse_insn): Simplify logic for deciding whether to place a folded + constant in the constant pool using force_const_mem. + (cse_main): Remove zero initialization of constant_pool_entries_cost + and constant_pool_entries_regcost. + * config/i386/i386.c (ix86_rtx_costs): Make memory accesses + fractionally more expensive, when optimizing for speed. + +2021-10-18 Martin Liska <mliska@suse.cz> + + PR gcov-profile/102746 + PR gcov-profile/102747 + * gcov.c (main): Return return_code. + (output_gcov_file): Mark return_code when error happens. + (generate_results): Likewise. + (read_graph_file): Likewise. + (read_count_file): Likewise. + +2021-10-18 Roger Sayle <roger@nextmovesoftware.com> + + * config/bfin/bfin.md (define_constants): Remove UNSPEC_ONES. + (define_insn "ones"): Replace UNSPEC_ONES with a truncate of + a popcount, allowing compile-time evaluation/simplification. + (popcountsi2, popcounthi2): New expanders using a "ones" insn. + +2021-10-18 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102788 + * tree-vect-patterns.c (vect_init_pattern_stmt): Allow + a NULL vectype. + (vect_pattern_recog_1): Likewise. + (vect_recog_bool_pattern): Continue matching the pattern + even if we do not have a vector type for a conversion + result. + +2021-10-18 Roger Sayle <roger@nextmovesoftware.com> + + * simplify-rtx.c (simplify_const_unary_operation) [SS_NEG, SS_ABS]: + Evalute SS_NEG and SS_ABS of a constant argument. + +2021-10-18 prathamesh.kulkarni <prathamesh.kulkarni@linaro.org> + + PR target/93183 + * gimple-match-head.c (try_conditional_simplification): Add case for single operand. + * internal-fn.def: Add entry for COND_NEG internal function. + * internal-fn.c (FOR_EACH_CODE_MAPPING): Add entry for + NEGATE_EXPR, COND_NEG mapping. + * optabs.def: Add entry for cond_neg_optab. + * match.pd (UNCOND_UNARY, COND_UNARY): New operator lists. + (vec_cond COND (foo A) B) -> (IFN_COND_FOO COND A B): New pattern. + (vec_cond COND B (foo A)) -> (IFN_COND_FOO ~COND A B): Likewise. + +2021-10-18 Aldy Hernandez <aldyh@redhat.com> + + * tree-ssa-strlen.c (class strlen_pass): Rename from + strlen_dom_walker. + (handle_builtin_stxncpy_strncat): Move to strlen_pass. + (handle_assign): Same. + (adjust_last_stmt): Same. + (maybe_warn_overflow): Same. + (handle_builtin_strlen): Same. + (handle_builtin_strchr): Same. + (handle_builtin_strcpy): Same. + (handle_builtin_strncat): Same. + (handle_builtin_stxncpy_strncat): Same. + (handle_builtin_memcpy): Same. + (handle_builtin_strcat): Same. + (handle_alloc_call): Same. + (handle_builtin_memset): Same. + (handle_builtin_memcmp): Same. + (get_len_or_size): Same. + (strxcmp_eqz_result): Same. + (handle_builtin_string_cmp): Same. + (handle_pointer_plus): Same. + (count_nonzero_bytes_addr): Same. + (count_nonzero_bytes): Same. + (handle_store): Same. + (strlen_check_and_optimize_call): Same. + (handle_integral_assign): Same. + (check_and_optimize_stmt): Same. + (printf_strlen_execute): Rename strlen_dom_walker to strlen_pass. + +2021-10-18 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102798 + * tree-vect-data-refs.c (vect_create_addr_base_for_vector_ref): + Only copy points-to info to newly generated SSA names. + +2021-10-18 Martin Liska <mliska@suse.cz> + + * dbgcnt.c (dbg_cnt_process_opt): Remove unused but set variable. + * gcov.c (get_cycles_count): Likewise. + * lto-compress.c (lto_compression_zlib): Likewise. + (lto_uncompression_zlib): Likewise. + * targhooks.c (default_pch_valid_p): Likewise. + 2021-10-17 Aldy Hernandez <aldyh@redhat.com> * tree-pass.h (make_pass_thread_jumps_full): New. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 1a35f32..9b3296b 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20211018 +20211021 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c6d856a..13f349c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,252 @@ +2021-10-20 Bob Duff <duff@adacore.com> + + * gcc-interface/decl.c (gnat_to_gnu_entity): Remove unnecessary + call to No_Uint_To_0. + +2021-10-20 Richard Kenner <kenner@adacore.com> + + * exp_unst.adb (Visit_Node, when N_Subprogram_Call): Never treat + instrinsic subprograms as nested. + +2021-10-20 Yannick Moy <moy@adacore.com> + + * libgnat/s-widlllu.ads: Mark in SPARK. + * libgnat/s-widllu.ads: Likewise. + * libgnat/s-widuns.ads: Likewise. + * libgnat/s-widthu.adb: Add ghost code and a + pseudo-postcondition. + +2021-10-20 Yannick Moy <moy@adacore.com> + + * libgnat/a-nbnbin__ghost.adb (Signed_Conversions, + Unsigned_Conversions): Mark subprograms as not imported. + * libgnat/a-nbnbin__ghost.ads: Provide a dummy body. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + * sem_eval.adb (Eval_Type_Conversion): If the target subtype is + a static floating-point subtype and the result is a real literal, + consider its machine-rounded value to raise Constraint_Error. + (Test_In_Range): Turn local variables into constants. + +2021-10-20 Doug Rupp <rupp@adacore.com> + + * libgnat/g-io-put__vxworks.adb: Remove (unused) + * libgnat/s-parame__ae653.ads: Likewise. + * libgnat/s-thread.ads: Likewise. + * libgnat/s-thread__ae653.adb: Likewise. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + * sem_eval.ads (Machine_Number): New inline function. + * sem_eval.adb (Machine_Number): New function body implementing + the machine rounding operation specified by RM 4.9(38/2). + (Check_Non_Static_Context): Call Machine_Number and set the + Is_Machine_Number flag consistently on the resulting node. + * sem_attr.adb (Eval_Attribute) <Attribute_Machine>: Likewise. + * checks.adb (Apply_Float_Conversion_Check): Call Machine_Number. + (Round_Machine): Likewise. + +2021-10-20 Johannes Kliemann <kliemann@adacore.com> + + * vxworks7-cert-rtp-link.spec: Add the definition of + __wrs_rtp_base. + +2021-10-20 Piotr Trojanek <trojanek@adacore.com> + + * sem_aggr.adb (Resolve_Delta_Record_Aggregate): Reject boxes in + record delta aggregates. + +2021-10-20 Justin Squirek <squirek@adacore.com> + + * sem_ch6.adb (Check_Return_Construct_Accessibility): Modify + generation of accessibility checks to be more consolidated and + get triggered properly in required cases. + * sem_util.adb (Accessibility_Level): Add extra check within + condition to handle aliased formals properly in more cases. + +2021-10-20 Justin Squirek <squirek@adacore.com> + + * exp_ch7.adb (Make_Final_Call): Detect expanded protected types + and use original protected type in order to calculate + appropriate finalization routine. + +2021-10-20 Johannes Kliemann <kliemann@adacore.com> + + * libgnat/a-nbnbin__ghost.ads: Add ghost package. + +2021-10-20 Piotr Trojanek <trojanek@adacore.com> + + * sem_aggr.adb (Variant_Depth): Refine type from Integer to + Natural. + +2021-10-20 Bob Duff <duff@adacore.com> + + * atree.ads: Comment improvements. How is a "completely new + node" different from a "new node"? Document default values + corresponding to field types. + * exp_ch7.adb (Process_Tagged_Type_Declaration): Use + higher-level Scope_Depth instead of Scope_Depth_Value. Remove + confusing comment: not clear what a "true" library level package + is. + * uintp.adb (Image_Out): Print No_Uint in a more readable way. + * gen_il-gen.adb, gen_il-gen-gen_entities.adb, + gen_il-gen-gen_nodes.adb, gen_il-types.ads: Tighten up the + subtypes of fields whose type is Uint, where possible; use + more-constrained subtypes such as Unat. + * einfo-utils.adb, einfo-utils.ads, exp_attr.adb, + exp_ch3.adb, exp_intr.adb, exp_unst.adb, exp_util.adb, + freeze.adb, repinfo.adb, sem.adb, sem_ch12.adb, sem_ch13.adb, + sem_ch3.adb, sem_ch8.adb, sem_util.adb, sprint.adb, treepr.adb: + No longer use Uint_0 to indicate "unknown" or "not yet known" + for various fields whose type is Uint. Use No_Uint for that, + except in a small number of legacy cases that cause test + failures. Protect many queries of such fields with calls to + Known_... functions. Improve comments. + * exp_aggr.adb: Likewise. + (Is_OK_Aggregate): Check whether Csiz is present. + (Aggr_Assignment_OK_For_Backend): Ensure we do not access an + uninitialized size. + * exp_strm.adb (Build_Elementary_Input_Call, + Build_Elementary_Write_Call): Check whether P_Size is present. + * cstand.adb: Leave Component_Size of Any_Composite unknown. + Similar for RM_Size of Standard_Exception_Type. These should + not be used. + * einfo.ads: Comment improvements. + * exp_disp.ads: Minor. + * gen_il-internals.ads, gen_il-internals.adb: Minor. + * sinfo-utils.adb: Take advantage of full-coverage rules. + * types.h: Minor. + +2021-10-20 Gary Dismukes <dismukes@adacore.com> + + * sem_ch6.adb: Add with and use of Warnsw. + (Check_Conformance): Report a warning when subtypes or + designated subtypes of formal parameters or result subtypes + denote different declarations between the spec and body of the + (Subprogram_Subtypes_Have_Same_Declaration): New function nested + within Check_Conformance that determines whether two subtype + entities referenced in a subprogram come from the same + declaration. Returns True immediately if the subprogram is in a + generic instantiation, or the subprogram is marked Is_Internal + or is declared in an internal (GNAT library) unit, or GNAT_Mode + is enabled, otherwise compares the nonlimited views of the + entities (or their designated subtypes' nonlimited views in the + anonymous access cases). + (Nonlimited_View_Of_Subtype): New function nested within + function Subprogram_Subtypes_Have_Same_Declaration that returns + Non_Limited_View of a type or subtype that is an incomplete or + class-wide type that comes from a limited of a + package (From_Limited_With is True for the entity), or returns + Full_View when the nonlimited view is an incomplete type. + Otherwise returns the entity passed in. + * warnsw.ads (Warn_On_Pedantic_Checks): New warning flag. + (type Warning_Record): New component Warn_On_Pedantic_Checks. + * warnsw.adb (All_Warnings): Set Warn_On_Pedantic_Checks from + parameter Setting. + (Restore_Warnings): Restore the value of the + Warn_On_Pedantic_Checks flag. + (Save_Warnings): Save the value of the Warn_On_Pedantic_Checks + flag. + (Set_Underscore_Warning_Switch): Add settings of the + Warn_On_Pedantic flag according to the switch ("-gnatw_p" vs. + "-gnatw_P"). + * doc/gnat_ugn/building_executable_programs_with_gnat.rst: Add + documentation of new switches -gnatw_p and -gnatw_P (warnings + for pedantic checks). + * gnat_ugn.texi: Regenerate. + * usage.adb: Add Warn_On_Pedantic_Checks. + +2021-10-20 Piotr Trojanek <trojanek@adacore.com> + + * exp_spark.adb (Expand_SPARK_N_Attribute_Reference): Guard + against equality of an uninitialized RM_Size field. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + * sem_ch12.adb (Analyze_Subprogram_Instantiation): Also propagate an + interface name on an intrinsic subprogram. Remove obsolete comment. + * libgnat/s-atopri.ads (Atomic_Load): New generic intrinsic function + (Atomic_Load_8): Rewrite into instantiation. + (Atomic_Load_16): Likewise. + (Atomic_Load_32): Likewise. + (Atomic_Load_64): Likewise. + (Sync_Compare_And_Swap): New generic intrinsic function. + (Sync_Compare_And_Swap_8): Rewrite into instantiation. + (Sync_Compare_And_Swap_16): Likewise. + (Sync_Compare_And_Swap_32): Likewise. + (Sync_Compare_And_Swap_64): Likewise. + (Lock_Free_Read): New generic inline function. + (Lock_Free_Read_8): Rewrite into instantiation. + (Lock_Free_Read_16): Likewise. + (Lock_Free_Read_32): Likewise. + (Lock_Free_Read_64): Likewise. + (Lock_Free_Try_Write): New generic inline function. + (Lock_Free_Try_Write_8): Rewrite into instantiation. + (Lock_Free_Try_Write_16): Likewise. + (Lock_Free_Try_Write_32): Likewise. + (Lock_Free_Try_Write_64): Likewise. + * libgnat/s-atopri.adb (Lock_Free_Read): New function body. + (Lock_Free_Read_8): Delete. + (Lock_Free_Read_16): Likewise. + (Lock_Free_Read_32): Likewise. + (Lock_Free_Read_64): Likewise. + (Lock_Free_Try_Write): New function body. + (Lock_Free_Try_Write_8): Delete. + (Lock_Free_Try_Write_16): Likewise. + (Lock_Free_Try_Write_32): Likewise. + (Lock_Free_Try_Write_64): Likewise. + * libgnat/s-aoinar.adb (Atomic_Fetch_And_Add): Use type-generic GCC + atomic builtin and tidy up implementation. + (Atomic_Fetch_And_Subtract): Likewise. + * libgnat/s-aomoar.adb (Atomic_Fetch_And_Add): Likewise. + (Atomic_Fetch_And_Subtract): Likewise. + * libgnat/s-atopex.adb (Atomic_Exchange): Likewise. + (Atomic_Compare_And_Exchange): Likewise. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Subprogram_Type>: + Replace test on Convention_Intrinsic with Is_Intrinsic_Subprogram. + (gnat_to_gnu_param): Likewise. + (gnat_to_gnu_subprog_type): Likewise. + * gcc-interface/trans.c (elaborate_all_entities_for_package): Ditto. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + * sem_eval.ads (Check_Non_Static_Context): Update documentation. + * sem_eval.adb (In_Any_Integer_Context): Change parameter type, + adjust accordingly and remove unreachable case. + (Eval_Integer_Literal): Consider the node kind throughout and + trim down verbose condition. + +2021-10-20 Doug Rupp <rupp@adacore.com> + + * Makefile.rtl: Remove references to system-vxworks-ppc.ads + and system-vxworks-x86.ads. + * libgnat/system-vxworks-ppc.ads: Remove. + * libgnat/system-vxworks-ppc-ravenscar.ads: Likewise. + * libgnat/system-vxworks-x86.ads: Likewise. + +2021-10-20 Yannick Moy <moy@adacore.com> + + * sem_ch4.adb (Analyze_QUantified_Expression): Issue warning on + conjunct/disjunct sub-expression of the full expression inside a + quantified expression, when it does not reference the quantified + variable. + +2021-10-20 Marc Poulhiès <poulhies@adacore.com> + + * checks.adb (Insert_Valid_Check): in case of checked type + conversion, update Typ to match Exp's type and add call to + Analyze_And_Resolve. + +2021-10-20 Arnaud Charlet <charlet@adacore.com> + + PR ada/100486 + * sem_prag.adb (Check_Valid_Library_Unit_Pragma): Do not raise an + exception as part of the bootstrap. + 2021-10-15 Richard Biener <rguenther@suse.de> * gcc-interface/misc.c (gnat_post_options): Do not warn diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 7fef517..ebfbe95 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -1166,9 +1166,6 @@ ifeq ($(strip $(filter-out powerpc% wrs vxworks vxworksspe vxworks7% vxworks7spe s-vxwext.ads<libgnarl/s-vxwext__kernel.ads \ s-vxwext.adb<libgnarl/s-vxwext__kernel.adb \ system.ads<libgnat/$(SVX)-$(ARCH_STR)-kernel.ads - else - LIBGNAT_TARGET_PAIRS += \ - system.ads<libgnat/system-vxworks-ppc.ads endif endif EXTRA_GNATRTL_NONTASKING_OBJS+=i-vxinco.o i-vxwork.o i-vxwoio.o @@ -1315,9 +1312,6 @@ ifeq ($(strip $(filter-out %86 x86_64 wrs vxworks vxworks7%,$(target_cpu) $(targ s-vxwext.ads<libgnarl/s-vxwext__kernel.ads \ s-vxwext.adb<libgnarl/s-vxwext__kernel.adb \ system.ads<libgnat/$(SVX)-x86-kernel.ads - else - LIBGNAT_TARGET_PAIRS += \ - system.ads<libgnat/system-vxworks-x86.ads endif endif diff --git a/gcc/ada/atree.ads b/gcc/ada/atree.ads index 2f3ca40..4861236 100644 --- a/gcc/ada/atree.ads +++ b/gcc/ada/atree.ads @@ -230,11 +230,18 @@ package Atree is function New_Node (New_Node_Kind : Node_Kind; New_Sloc : Source_Ptr) return Node_Id; - -- Allocates a completely new node with the given node type and source - -- location values. All other fields are set to their standard defaults: + -- Allocates a new node with the given node type and source location + -- values. Fields have defaults depending on their type: + + -- Flag: False + -- Node_Id: Empty + -- List_Id: Empty + -- Elist_Id: No_Elist + -- Uint: No_Uint -- - -- Empty for all FieldN fields - -- False for all FlagN fields + -- Name_Id, String_Id, Valid_Uint, Unat, Upos, Nonzero_Uint, Ureal: + -- No default. This means it is an error to call the getter before + -- calling the setter. -- -- The usual approach is to build a new node using this function and -- then, using the value returned, use the Set_xxx functions to set @@ -288,16 +295,16 @@ package Atree is -- with copying aspect specifications where this is required. function New_Copy (Source : Node_Id) return Node_Id; - -- This function allocates a completely new node, and then initializes - -- it by copying the contents of the source node into it. The contents of - -- the source node is not affected. The target node is always marked as - -- not being in a list (even if the source is a list member), and not - -- overloaded. The new node will have an extension if the source has - -- an extension. New_Copy (Empty) returns Empty, and New_Copy (Error) - -- returns Error. Note that, unlike Copy_Separate_Tree, New_Copy does not - -- recursively copy any descendants, so in general parent pointers are not - -- set correctly for the descendants of the copied node. Both normal and - -- extended nodes (entities) may be copied using New_Copy. + -- This function allocates a new node, and then initializes it by copying + -- the contents of the source node into it. The contents of the source node + -- is not affected. The target node is always marked as not being in a list + -- (even if the source is a list member), and not overloaded. The new node + -- will have an extension if the source has an extension. New_Copy (Empty) + -- returns Empty, and New_Copy (Error) returns Error. Note that, unlike + -- Copy_Separate_Tree, New_Copy does not recursively copy any descendants, + -- so in general parent pointers are not set correctly for the descendants + -- of the copied node. Both normal and extended nodes (entities) may be + -- copied using New_Copy. function Relocate_Node (Source : Node_Id) return Node_Id; -- Source is a non-entity node that is to be relocated. A new node is @@ -340,11 +347,11 @@ package Atree is -- Exchange the contents of two entities. The parent pointers are switched -- as well as the Defining_Identifier fields in the parents, so that the -- entities point correctly to their original parents. The effect is thus - -- to leave the tree completely unchanged in structure, except that the - -- entity ID values of the two entities are interchanged. Neither of the - -- two entities may be list members. Note that entities appear on two - -- semantic chains: Homonym and Next_Entity: the corresponding links must - -- be adjusted by the caller, according to context. + -- to leave the tree unchanged in structure, except that the entity ID + -- values of the two entities are interchanged. Neither of the two entities + -- may be list members. Note that entities appear on two semantic chains: + -- Homonym and Next_Entity: the corresponding links must be adjusted by the + -- caller, according to context. procedure Extend_Node (Source : Node_Id); -- This turns a node into an entity; it function is used only by Sinfo.CN. diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index a58a495..c85cba9a5 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -2171,7 +2171,7 @@ package body Checks is Lo_OK := (Ifirst > 0); else - Lo := Machine (Expr_Type, UR_From_Uint (Ifirst), Round_Even, Expr); + Lo := Machine_Number (Expr_Type, UR_From_Uint (Ifirst), Expr); Lo_OK := (Lo >= UR_From_Uint (Ifirst)); end if; @@ -2214,7 +2214,7 @@ package body Checks is Hi := UR_From_Uint (Ilast) + Ureal_Half; Hi_OK := (Ilast < 0); else - Hi := Machine (Expr_Type, UR_From_Uint (Ilast), Round_Even, Expr); + Hi := Machine_Number (Expr_Type, UR_From_Uint (Ilast), Expr); Hi_OK := (Hi <= UR_From_Uint (Ilast)); end if; @@ -5563,7 +5563,7 @@ package body Checks is -- the results in Lo_Right, Hi_Right, Lo_Left, Hi_Left. function Round_Machine (B : Ureal) return Ureal; - -- B is a real bound. Round it using mode Round_Even. + -- B is a real bound. Round it to the nearest machine number. ----------------- -- OK_Operands -- @@ -5589,7 +5589,7 @@ package body Checks is function Round_Machine (B : Ureal) return Ureal is begin - return Machine (Typ, B, Round_Even, N); + return Machine_Number (Typ, B, N); end Round_Machine; -- Start of processing for Determine_Range_R @@ -8077,7 +8077,7 @@ package body Checks is Is_High_Bound : Boolean := False) is Loc : constant Source_Ptr := Sloc (Expr); - Typ : constant Entity_Id := Etype (Expr); + Typ : Entity_Id := Etype (Expr); Exp : Node_Id; begin @@ -8137,6 +8137,7 @@ package body Checks is while Nkind (Exp) = N_Type_Conversion loop Exp := Expression (Exp); end loop; + Typ := Etype (Exp); -- Do not generate a check for a variable which already validates the -- value of an assignable object. @@ -8217,6 +8218,14 @@ package body Checks is Set_Do_Range_Check (Validated_Object (Var_Id), False); end if; + -- In case of a type conversion, an expansion of the expr may be + -- needed (eg. fixed-point as actual). + + if Exp /= Expr then + pragma Assert (Nkind (Expr) = N_Type_Conversion); + Analyze_And_Resolve (Expr); + end if; + PV := New_Occurrence_Of (Var_Id, Loc); -- Otherwise the expression does not denote a variable. Force its diff --git a/gcc/ada/cstand.adb b/gcc/ada/cstand.adb index 41de2a5..3822d93 100644 --- a/gcc/ada/cstand.adb +++ b/gcc/ada/cstand.adb @@ -1233,10 +1233,11 @@ package body CStand is Mutate_Ekind (Any_Composite, E_Array_Type); Set_Scope (Any_Composite, Standard_Standard); Set_Etype (Any_Composite, Any_Composite); - Set_Component_Size (Any_Composite, Uint_0); Set_Component_Type (Any_Composite, Standard_Integer); Reinit_Size_Align (Any_Composite); + pragma Assert (not Known_Component_Size (Any_Composite)); + Any_Discrete := New_Standard_Entity ("a discrete type"); Mutate_Ekind (Any_Discrete, E_Signed_Integer_Type); Set_Scope (Any_Discrete, Standard_Standard); @@ -1508,10 +1509,11 @@ package body CStand is Set_Scope (Standard_Exception_Type, Standard_Standard); Set_Stored_Constraint (Standard_Exception_Type, No_Elist); - Set_RM_Size (Standard_Exception_Type, Uint_0); Set_Size_Known_At_Compile_Time (Standard_Exception_Type, True); + pragma Assert (not Known_RM_Size (Standard_Exception_Type)); + Make_Aliased_Component (Standard_Exception_Type, Standard_Boolean, "Not_Handled_By_Others"); Make_Aliased_Component (Standard_Exception_Type, Standard_Character, diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst index 67fd130..48b7623 100644 --- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst +++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst @@ -3582,6 +3582,25 @@ of the pragma in the :title:`GNAT_Reference_manual`). ordering. +.. index:: -gnatw_p (gcc) + +:switch:`-gnatw_p` + *Activate warnings for pedantic checks.* + + This switch activates warnings for the failure of certain pedantic checks. + The only case currently supported is a check that the subtype_marks given + for corresponding formal parameter and function results in a subprogram + declaration and its body denote the same subtype declaration. The default + is that such warnings are not given. + +.. index:: -gnatw_P (gcc) + +:switch:`-gnatw_P` + *Suppress warnings for pedantic checks.* + + This switch suppresses warnings on violations of pedantic checks. + + .. index:: -gnatwq (gcc) .. index:: Parentheses, warnings diff --git a/gcc/ada/einfo-utils.adb b/gcc/ada/einfo-utils.adb index 0274e6b..0c89c82 100644 --- a/gcc/ada/einfo-utils.adb +++ b/gcc/ada/einfo-utils.adb @@ -390,34 +390,23 @@ package body Einfo.Utils is function Known_Static_Component_Bit_Offset (E : Entity_Id) return B is begin - return Present (Component_Bit_Offset (E)) + return Known_Component_Bit_Offset (E) and then Component_Bit_Offset (E) >= Uint_0; end Known_Static_Component_Bit_Offset; function Known_Component_Size (E : Entity_Id) return B is begin - return Component_Size (E) /= Uint_0 - and then Present (Component_Size (E)); + return Present (Component_Size (E)); end Known_Component_Size; function Known_Static_Component_Size (E : Entity_Id) return B is begin - return Component_Size (E) > Uint_0; + return Known_Component_Size (E) and then Component_Size (E) >= Uint_0; end Known_Static_Component_Size; - Use_New_Unknown_Rep : constant Boolean := False; - -- If False, we represent "unknown" as Uint_0, which is wrong. - -- We intend to make it True (and remove it), and represent - -- "unknown" as Field_Is_Initial_Zero. We also need to change - -- the type of Esize and RM_Size from Uint to Valid_Uint. - function Known_Esize (E : Entity_Id) return B is begin - if Use_New_Unknown_Rep then - return not Field_Is_Initial_Zero (E, F_Esize); - else - return Present (Esize (E)) and then Esize (E) /= Uint_0; - end if; + return Present (Esize (E)); end Known_Esize; function Known_Static_Esize (E : Entity_Id) return B is @@ -429,11 +418,7 @@ package body Einfo.Utils is procedure Reinit_Esize (Id : E) is begin - if Use_New_Unknown_Rep then - Reinit_Field_To_Zero (Id, F_Esize); - else - Set_Esize (Id, Uint_0); - end if; + Reinit_Field_To_Zero (Id, F_Esize); end Reinit_Esize; procedure Copy_Esize (To, From : E) is @@ -452,7 +437,7 @@ package body Einfo.Utils is function Known_Static_Normalized_First_Bit (E : Entity_Id) return B is begin - return Present (Normalized_First_Bit (E)) + return Known_Normalized_First_Bit (E) and then Normalized_First_Bit (E) >= Uint_0; end Known_Static_Normalized_First_Bit; @@ -463,43 +448,25 @@ package body Einfo.Utils is function Known_Static_Normalized_Position (E : Entity_Id) return B is begin - return Present (Normalized_Position (E)) + return Known_Normalized_Position (E) and then Normalized_Position (E) >= Uint_0; end Known_Static_Normalized_Position; function Known_RM_Size (E : Entity_Id) return B is begin - if Use_New_Unknown_Rep then - return not Field_Is_Initial_Zero (E, F_RM_Size); - else - return Present (RM_Size (E)) - and then (RM_Size (E) /= Uint_0 - or else Is_Discrete_Type (E) - or else Is_Fixed_Point_Type (E)); - end if; + return Present (RM_Size (E)); end Known_RM_Size; function Known_Static_RM_Size (E : Entity_Id) return B is begin - if Use_New_Unknown_Rep then - return Known_RM_Size (E) - and then RM_Size (E) >= Uint_0 - and then not Is_Generic_Type (E); - else - return (RM_Size (E) > Uint_0 - or else Is_Discrete_Type (E) - or else Is_Fixed_Point_Type (E)) - and then not Is_Generic_Type (E); - end if; + return Known_RM_Size (E) + and then RM_Size (E) >= Uint_0 + and then not Is_Generic_Type (E); end Known_Static_RM_Size; procedure Reinit_RM_Size (Id : E) is begin - if Use_New_Unknown_Rep then - Reinit_Field_To_Zero (Id, F_RM_Size); - else - Set_RM_Size (Id, Uint_0); - end if; + Reinit_Field_To_Zero (Id, F_RM_Size); end Reinit_RM_Size; procedure Copy_RM_Size (To, From : E) is @@ -541,9 +508,8 @@ package body Einfo.Utils is begin pragma Assert (Is_Type (Id)); pragma Assert (not Known_Esize (Id) or else Esize (Id) = V); - if Use_New_Unknown_Rep then - pragma Assert (not Known_RM_Size (Id) or else RM_Size (Id) = V); - end if; + pragma Assert (not Known_RM_Size (Id) or else RM_Size (Id) = V); + Set_Esize (Id, UI_From_Int (V)); Set_RM_Size (Id, UI_From_Int (V)); end Init_Size; @@ -2593,6 +2559,16 @@ package body Einfo.Utils is return Scope_Depth_Value (Scop); end Scope_Depth; + function Scope_Depth_Default_0 (Id : E) return U is + begin + if Scope_Depth_Set (Id) then + return Scope_Depth (Id); + + else + return Uint_0; + end if; + end Scope_Depth_Default_0; + --------------------- -- Scope_Depth_Set -- --------------------- diff --git a/gcc/ada/einfo-utils.ads b/gcc/ada/einfo-utils.ads index 8046722..0e6c8cd 100644 --- a/gcc/ada/einfo-utils.ads +++ b/gcc/ada/einfo-utils.ads @@ -274,14 +274,21 @@ package Einfo.Utils is function Safe_Emax_Value (Id : E) return U; function Safe_First_Value (Id : E) return R; function Safe_Last_Value (Id : E) return R; - function Scope_Depth (Id : E) return U; - function Scope_Depth_Set (Id : E) return B; function Size_Clause (Id : E) return N; function Stream_Size_Clause (Id : E) return N; function Type_High_Bound (Id : E) return N; function Type_Low_Bound (Id : E) return N; function Underlying_Type (Id : E) return E; + function Scope_Depth (Id : E) return U; + function Scope_Depth_Set (Id : E) return B; + + function Scope_Depth_Default_0 (Id : E) return U; + -- In rare cases, the Scope_Depth_Value (queried by Scope_Depth) is + -- not correctly set before querying it; this may be used instead of + -- Scope_Depth in such cases. It returns Uint_0 if the Scope_Depth_Value + -- has not been set. See documentation in Einfo. + pragma Inline (Address_Clause); pragma Inline (Alignment_Clause); pragma Inline (Base_Type); @@ -314,41 +321,58 @@ package Einfo.Utils is -- Type Representation Attribute Fields -- ------------------------------------------ - -- Each of the following fields can be in a "known" or "unknown" state: + function Known_Alignment (E : Entity_Id) return B with Inline; + procedure Reinit_Alignment (Id : E) with Inline; + procedure Copy_Alignment (To, From : E); + + function Known_Component_Bit_Offset (E : Entity_Id) return B with Inline; + function Known_Static_Component_Bit_Offset (E : Entity_Id) return B + with Inline; + + function Known_Component_Size (E : Entity_Id) return B with Inline; + function Known_Static_Component_Size (E : Entity_Id) return B with Inline; + + function Known_Esize (E : Entity_Id) return B with Inline; + function Known_Static_Esize (E : Entity_Id) return B with Inline; + procedure Reinit_Esize (Id : E) with Inline; + procedure Copy_Esize (To, From : E); + + function Known_Normalized_First_Bit (E : Entity_Id) return B with Inline; + function Known_Static_Normalized_First_Bit (E : Entity_Id) return B + with Inline; + + function Known_Normalized_Position (E : Entity_Id) return B with Inline; + function Known_Static_Normalized_Position (E : Entity_Id) return B + with Inline; + + function Known_RM_Size (E : Entity_Id) return B with Inline; + function Known_Static_RM_Size (E : Entity_Id) return B with Inline; + procedure Reinit_RM_Size (Id : E) with Inline; + procedure Copy_RM_Size (To, From : E); - -- Alignment - -- Component_Size - -- Component_Bit_Offset - -- Digits_Value - -- Esize - -- Normalized_First_Bit - -- Normalized_Position - -- RM_Size - -- -- NOTE: "known" here does not mean "known at compile time". It means that -- the compiler has computed the value of the field (either by default, or -- by noting some representation clauses), and the field has not been -- reinitialized. -- - -- We document the Esize functions here; the others are analogous: + -- We document the Esize functions here; the others above are analogous: -- -- Known_Esize: True if Set_Esize has been called without a subsequent -- Reinit_Esize. -- -- Known_Static_Esize: True if Known_Esize and the Esize is known at -- compile time. (We're not using "static" in the Ada RM sense here. We - -- are using it to mean "known at compile time.) + -- are using it to mean "known at compile time".) -- -- Reinit_Esize: Set the Esize field to its initial unknown state. -- -- Copy_Esize: Copies the Esize from From to To; Known_Esize (From) may -- be False, in which case Known_Esize (To) becomes False. -- - -- Esize: This is the normal automatially-generated getter for Esize, - -- declared elsewhere. It is an error to call this if Set_Esize has not - -- yet been called, or if Reinit_Esize has been called subsequently. + -- Esize: This is the normal automatically-generated getter for Esize, + -- declared elsewhere. Returns No_Uint if not Known_Esize. -- - -- Set_Esize: This is the normal automatially-generated setter for + -- Set_Esize: This is the normal automatically-generated setter for -- Esize. After a call to this, Known_Esize is True. It is an error -- to call this with a No_Uint value. -- @@ -357,13 +381,6 @@ package Einfo.Utils is -- before calling Esize, because the code is written in such a way that we -- don't know whether Set_Esize has already been called. -- - -- We intend to use the initial zero value to represent "unknown". Note - -- that this value is different from No_Uint, and different from Uint_0. - -- However, this is work in progress; we are still using No_Uint or Uint_0 - -- to represent "unknown" in some cases. Using Uint_0 leads to several - -- bugs, because zero is a legitimate value (T'Size can be zero bits) -- - -- Uint_0 shouldn't mean two different things. - -- -- In two cases, Known_Static_Esize and Known_Static_RM_Size, there is one -- more consideration, which is that we always return False for generic -- types. Within a template, the size can look Known_Static, because of the @@ -371,35 +388,6 @@ package Einfo.Utils is -- Known_Static and anyone testing if they are Known_Static within the -- template should get False as a result to prevent incorrect assumptions. - function Known_Alignment (E : Entity_Id) return B with Inline; - procedure Reinit_Alignment (Id : E) with Inline; - procedure Copy_Alignment (To, From : E); - - function Known_Component_Bit_Offset (E : Entity_Id) return B with Inline; - function Known_Static_Component_Bit_Offset (E : Entity_Id) return B - with Inline; - - function Known_Component_Size (E : Entity_Id) return B with Inline; - function Known_Static_Component_Size (E : Entity_Id) return B with Inline; - - function Known_Esize (E : Entity_Id) return B with Inline; - function Known_Static_Esize (E : Entity_Id) return B with Inline; - procedure Reinit_Esize (Id : E) with Inline; - procedure Copy_Esize (To, From : E); - - function Known_Normalized_First_Bit (E : Entity_Id) return B with Inline; - function Known_Static_Normalized_First_Bit (E : Entity_Id) return B - with Inline; - - function Known_Normalized_Position (E : Entity_Id) return B with Inline; - function Known_Static_Normalized_Position (E : Entity_Id) return B - with Inline; - - function Known_RM_Size (E : Entity_Id) return B with Inline; - function Known_Static_RM_Size (E : Entity_Id) return B with Inline; - procedure Reinit_RM_Size (Id : E) with Inline; - procedure Copy_RM_Size (To, From : E); - --------------------------------------------------------- -- Procedures for setting multiple of the above fields -- --------------------------------------------------------- diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads index 0239a70..13440ce 100644 --- a/gcc/ada/einfo.ads +++ b/gcc/ada/einfo.ads @@ -4323,7 +4323,8 @@ package Einfo is -- Indicates the number of scopes that statically enclose the declaration -- of the unit or type. Library units have a depth of zero. Note that -- record types can act as scopes but do NOT have this field set (see --- Scope_Depth above). +-- Scope_Depth above). Queries should normally be via Scope_Depth, +-- and not call Scope_Depth_Value directly. -- Scope_Depth_Set (synthesized) -- Applies to a special predicate function that returns a Boolean value @@ -4555,7 +4556,7 @@ package Einfo is -- in inheritance of subprograms between views of the same type. -- Subps_Index --- Present in subprogram entries. Set if the subprogram contains nested +-- Present in subprogram entities. Set if the subprogram contains nested -- subprograms, or is a subprogram nested within such a subprogram. Holds -- the index in the Exp_Unst.Subps table for the subprogram. Note that -- for the outer level subprogram, this is the starting index in the Subp diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index ebc7a87..f3d83a5 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -490,7 +490,7 @@ package body Exp_Aggr is -- Fat pointers are rejected as they are not really elementary -- for the backend. - if Csiz /= System_Address_Size then + if No (Csiz) or else Csiz /= System_Address_Size then return False; end if; @@ -504,8 +504,7 @@ package body Exp_Aggr is -- Scalar types are OK if their size is a multiple of Storage_Unit - elsif Is_Scalar_Type (Ctyp) then - pragma Assert (Present (Csiz)); + elsif Is_Scalar_Type (Ctyp) and then Present (Csiz) then if Csiz mod System_Storage_Unit /= 0 then return False; @@ -9098,11 +9097,11 @@ package body Exp_Aggr is ----------------------------- function Is_Two_Dim_Packed_Array (Typ : Entity_Id) return Boolean is - C : constant Int := UI_To_Int (Component_Size (Typ)); + C : constant Uint := Component_Size (Typ); begin return Number_Dimensions (Typ) = 2 and then Is_Bit_Packed_Array (Typ) - and then (C = 1 or else C = 2 or else C = 4); + and then C in Uint_1 | Uint_2 | Uint_4; -- False if No_Uint end Is_Two_Dim_Packed_Array; -------------------- diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 096671f..49f5c94 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -6294,7 +6294,7 @@ package body Exp_Attr is -- size. This applies to both types and objects. The size of an -- object can be specified in the following ways: - -- An explicit size object is given for an object + -- An explicit size clause is given for an object -- A component size is specified for an indexed component -- A component clause is specified for a selected component -- The object is a component of a packed composite object @@ -6310,7 +6310,7 @@ package body Exp_Attr is or else Is_Packed (Etype (Prefix (Pref))))) or else (Nkind (Pref) = N_Indexed_Component - and then (Component_Size (Etype (Prefix (Pref))) /= 0 + and then (Known_Component_Size (Etype (Prefix (Pref))) or else Is_Packed (Etype (Prefix (Pref))))) then Set_Attribute_Name (N, Name_Size); @@ -7970,7 +7970,6 @@ package body Exp_Attr is elsif Id = Attribute_Size and then Is_Entity_Name (Pref) and then Is_Object (Entity (Pref)) - and then Known_Esize (Entity (Pref)) and then Known_Static_Esize (Entity (Pref)) then Siz := Esize (Entity (Pref)); diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index d4373ee..e7eed28 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -942,11 +942,11 @@ package body Exp_Ch3 is (Case_Id : Entity_Id; Variant : Node_Id) return Node_Id; -- Build a case statement containing only two alternatives. The first - -- alternative corresponds exactly to the discrete choices given on the - -- variant with contains the components that we are generating the - -- checks for. If the discriminant is one of these return False. The - -- second alternative is an OTHERS choice that will return True - -- indicating the discriminant did not match. + -- alternative corresponds to the discrete choices given on the variant + -- that contains the components that we are generating the checks + -- for. If the discriminant is one of these return False. The second + -- alternative is an OTHERS choice that returns True indicating the + -- discriminant did not match. function Build_Dcheck_Function (Case_Id : Entity_Id; @@ -976,6 +976,7 @@ package body Exp_Ch3 is begin Case_Node := New_Node (N_Case_Statement, Loc); + Set_End_Span (Case_Node, Uint_0); -- Replace the discriminant which controls the variant with the name -- of the formal of the checking function. diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 71cad98..cd9ff21 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -3613,11 +3613,10 @@ package body Exp_Ch7 is and then (not Is_Library_Level_Entity (Spec_Id) - -- Nested packages are considered to be library level entities, - -- but do not need to be processed separately. True library level - -- packages have a scope value of 1. + -- Nested packages are library level entities, but do not need to + -- be processed separately. - or else Scope_Depth_Value (Spec_Id) /= Uint_1 + or else Scope_Depth (Spec_Id) /= Uint_1 or else (Is_Generic_Instance (Spec_Id) and then Package_Instantiation (Spec_Id) /= N)) @@ -8954,11 +8953,12 @@ package body Exp_Ch7 is Typ : Entity_Id; Skip_Self : Boolean := False) return Node_Id is - Loc : constant Source_Ptr := Sloc (Obj_Ref); - Atyp : Entity_Id; - Fin_Id : Entity_Id := Empty; - Ref : Node_Id; - Utyp : Entity_Id; + Loc : constant Source_Ptr := Sloc (Obj_Ref); + Atyp : Entity_Id; + Prot_Typ : Entity_Id := Empty; + Fin_Id : Entity_Id := Empty; + Ref : Node_Id; + Utyp : Entity_Id; begin Ref := Obj_Ref; @@ -9036,6 +9036,19 @@ package body Exp_Ch7 is Set_Assignment_OK (Ref); end if; + -- Detect if Typ is a protected type or an expanded protected type and + -- store the relevant type within Prot_Typ for later processing. + + if Is_Protected_Type (Typ) then + Prot_Typ := Typ; + + elsif Ekind (Typ) = E_Record_Type + and then Present (Corresponding_Concurrent_Type (Typ)) + and then Is_Protected_Type (Corresponding_Concurrent_Type (Typ)) + then + Prot_Typ := Corresponding_Concurrent_Type (Typ); + end if; + -- The underlying type may not be present due to a missing full view. In -- this case freezing did not take place and there is no [Deep_]Finalize -- primitive to call. @@ -9081,7 +9094,7 @@ package body Exp_Ch7 is -- Protected types: these also require finalization even though they -- are not marked controlled explicitly. - elsif Is_Protected_Type (Typ) then + elsif Present (Prot_Typ) then -- Protected objects do not need to be finalized on restricted -- runtimes. @@ -9091,7 +9104,7 @@ package body Exp_Ch7 is -- ??? Only handle the simple case for now. Will not support a record -- or array containing protected objects. - elsif Is_Simple_Protected_Type (Typ) then + elsif Is_Simple_Protected_Type (Prot_Typ) then Fin_Id := RTE (RE_Finalize_Protection); else raise Program_Error; diff --git a/gcc/ada/exp_disp.ads b/gcc/ada/exp_disp.ads index 9d9811b..f286763 100644 --- a/gcc/ada/exp_disp.ads +++ b/gcc/ada/exp_disp.ads @@ -373,9 +373,9 @@ package Exp_Disp is -- target object in its first argument; such implicit argument is explicit -- in the IP procedures built here. - procedure Set_DT_Position_Value (Prim : Entity_Id; Value : Uint); - -- Set the position of a dispatching primitive its dispatch table. For - -- subprogram wrappers propagate the value to the wrapped subprogram. + procedure Set_DT_Position_Value (Prim : Entity_Id; Value : Uint); + -- Set the position of a dispatching primitive in its dispatch table. + -- For subprogram wrappers propagate the value to the wrapped subprogram. procedure Set_DTC_Entity_Value (Tagged_Type : Entity_Id; Prim : Entity_Id); -- Set the definite value of the DTC_Entity value associated with a given diff --git a/gcc/ada/exp_intr.adb b/gcc/ada/exp_intr.adb index 86cb702..c139bb4 100644 --- a/gcc/ada/exp_intr.adb +++ b/gcc/ada/exp_intr.adb @@ -325,7 +325,7 @@ package body Exp_Intr is Result_Typ := Class_Wide_Type (Etype (Act_Constr)); -- Check that the accessibility level of the tag is no deeper than that - -- of the constructor function (unless CodePeer_Mode) + -- of the constructor function (unless CodePeer_Mode). if not CodePeer_Mode then Insert_Action (N, @@ -335,7 +335,8 @@ package body Exp_Intr is Left_Opnd => Build_Get_Access_Level (Loc, New_Copy_Tree (Tag_Arg)), Right_Opnd => - Make_Integer_Literal (Loc, Scope_Depth (Act_Constr))), + Make_Integer_Literal + (Loc, Scope_Depth_Default_0 (Act_Constr))), Then_Statements => New_List ( Make_Raise_Statement (Loc, diff --git a/gcc/ada/exp_spark.adb b/gcc/ada/exp_spark.adb index bbfee62..bce745b 100644 --- a/gcc/ada/exp_spark.adb +++ b/gcc/ada/exp_spark.adb @@ -451,6 +451,7 @@ package body Exp_SPARK is Apply_Universal_Integer_Attribute_Checks (N); if Present (Typ) + and then Known_RM_Size (Typ) and then RM_Size (Typ) = RM_Size (Standard_Long_Long_Integer) then -- ??? This should rather be a range check, but this would diff --git a/gcc/ada/exp_strm.adb b/gcc/ada/exp_strm.adb index c87b881..8983dab1c 100644 --- a/gcc/ada/exp_strm.adb +++ b/gcc/ada/exp_strm.adb @@ -624,7 +624,7 @@ package body Exp_Strm is end if; else pragma Assert (Is_Access_Type (U_Type)); - if P_Size > System_Address_Size then + if Present (P_Size) and then P_Size > System_Address_Size then Lib_RE := RE_I_AD; else Lib_RE := RE_I_AS; @@ -868,7 +868,7 @@ package body Exp_Strm is else pragma Assert (Is_Access_Type (U_Type)); - if P_Size > System_Address_Size then + if Present (P_Size) and then P_Size > System_Address_Size then Lib_RE := RE_W_AD; else Lib_RE := RE_W_AS; diff --git a/gcc/ada/exp_unst.adb b/gcc/ada/exp_unst.adb index c071a9c..be06580 100644 --- a/gcc/ada/exp_unst.adb +++ b/gcc/ada/exp_unst.adb @@ -270,7 +270,9 @@ package body Exp_Unst is begin pragma Assert (Is_Subprogram (E)); - if Subps_Index (E) = Uint_0 then + if Field_Is_Initial_Zero (E, F_Subps_Index) + or else Subps_Index (E) = Uint_0 + then E := Ultimate_Alias (E); -- The body of a protected operation has a different name and @@ -886,6 +888,7 @@ package body Exp_Unst is if Is_Subprogram (Ent) and then not Is_Generic_Subprogram (Ent) and then not Is_Imported (Ent) + and then not Is_Intrinsic_Subprogram (Ent) and then Scope_Within (Ultimate_Alias (Ent), Subp) then Append_Unique_Call ((N, Current_Subprogram, Ent)); diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 0a6837c..9bc9449 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -4784,7 +4784,8 @@ package body Exp_Util is -- record or bit-packed array, then everything is fine, since the back -- end can handle these cases correctly. - elsif Esize (Comp) <= System_Max_Integer_Size + elsif Known_Esize (Comp) + and then Esize (Comp) <= System_Max_Integer_Size and then (Is_Record_Type (UT) or else Is_Bit_Packed_Array (UT)) then return False; diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index 5f81d9e..fac7094 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -865,9 +865,12 @@ package body Freeze is Error_Msg_NE (Size_Too_Small_Message, Size_Clause (T), T); end if; - -- Set size if not set already + -- Set size if not set already. Do not set it to Uint_0, because in + -- some cases (notably array-of-record), the Component_Size is + -- No_Uint, which causes S to be Uint_0. Presumably the RM_Size and + -- Component_Size will eventually be set correctly by the back end. - elsif not Known_RM_Size (T) then + elsif not Known_RM_Size (T) and then S /= Uint_0 then Set_RM_Size (T, S); end if; end Set_Small_Size; @@ -899,8 +902,17 @@ package body Freeze is -- String literals always have known size, and we can set it if Ekind (T) = E_String_Literal_Subtype then - Set_Small_Size - (T, Component_Size (T) * String_Literal_Length (T)); + if Known_Component_Size (T) then + Set_Small_Size + (T, Component_Size (T) * String_Literal_Length (T)); + + else + -- The following is wrong, but does what previous versions + -- did. The Component_Size is unknown for the string in a + -- pragma Warnings. + Set_Small_Size (T, Uint_0); + end if; + return True; -- Unconstrained types never have known at compile time size @@ -932,6 +944,12 @@ package body Freeze is Dim : Uint; begin + -- See comment in Set_Small_Size above + + if No (Size) then + Size := Uint_0; + end if; + Index := First_Index (T); while Present (Index) loop if Nkind (Index) = N_Range then @@ -954,7 +972,7 @@ package body Freeze is else Dim := Expr_Value (High) - Expr_Value (Low) + 1; - if Dim >= 0 then + if Dim > Uint_0 then Size := Size * Dim; else Size := Uint_0; @@ -3703,6 +3721,7 @@ package body Freeze is if Has_Pragma_Pack (Arr) and then not Present (Comp_Size_C) and then (Csiz = 7 or else Csiz = 15 or else Csiz = 31) + and then Known_Esize (Base_Type (Ctyp)) and then Esize (Base_Type (Ctyp)) = Csiz + 1 then Error_Msg_Uint_1 := Csiz; @@ -6646,7 +6665,7 @@ package body Freeze is Dim := Expr_Value (Hi) - Expr_Value (Lo) + 1; - if Dim >= 0 then + if Dim > Uint_0 then Num_Elmts := Num_Elmts * Dim; else Num_Elmts := Uint_0; @@ -6668,9 +6687,12 @@ package body Freeze is if Implicit_Packing then Set_Component_Size (Btyp, Rsiz); - -- Otherwise give an error message + -- Otherwise give an error message, except that if the + -- specified Size is zero, there is no need for pragma + -- Pack. Note that size zero is not considered + -- Addressable. - else + elsif RM_Size (E) /= Uint_0 then Error_Msg_NE ("size given for& too small", SZ, E); Error_Msg_N -- CODEFIX diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 639cf06..98b4aaf 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -3946,7 +3946,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) bool extern_flag = ((Is_Public (gnat_entity) && !definition) || imported_p - || (Convention (gnat_entity) == Convention_Intrinsic + || (Is_Intrinsic_Subprogram (gnat_entity) && Has_Pragma_Inline_Always (gnat_entity))); tree gnu_param_list; @@ -4490,7 +4490,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) /* Likewise for the RM size, if any. */ if (!Known_RM_Size (gnat_entity) && TYPE_SIZE (gnu_type)) Set_RM_Size (gnat_entity, - No_Uint_To_0 (annotate_value (rm_size (gnu_type)))); + annotate_value (rm_size (gnu_type))); /* If we are at global level, GCC applied variable_size to the size but this has done nothing. So, if it's not constant or self-referential, @@ -5366,7 +5366,7 @@ gnat_to_gnu_param (Entity_Id gnat_param, tree gnu_param_type, bool first, /* Builtins are expanded inline and there is no real call sequence involved. So the type expected by the underlying expander is always the type of the argument "as is". */ - if (Convention (gnat_subprog) == Convention_Intrinsic + if (Is_Intrinsic_Subprogram (gnat_subprog) && Present (Interface_Name (gnat_subprog))) mech = By_Copy; @@ -5823,9 +5823,10 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition, else { - /* For foreign convention subprograms, return System.Address as void * - or equivalent. Note that this comprises GCC builtins. */ - if (Has_Foreign_Convention (gnat_subprog) + /* For foreign convention/intrinsic subprograms, return System.Address + as void * or equivalent; this comprises GCC builtins. */ + if ((Has_Foreign_Convention (gnat_subprog) + || Is_Intrinsic_Subprogram (gnat_subprog)) && Is_Descendant_Of_Address (Underlying_Type (gnat_return_type))) gnu_return_type = ptr_type_node; else @@ -5995,9 +5996,10 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition, { Entity_Id gnat_param_type = Etype (gnat_param); - /* For foreign convention subprograms, pass System.Address as void * - or equivalent. Note that this comprises GCC builtins. */ - if (Has_Foreign_Convention (gnat_subprog) + /* For foreign convention/intrinsic subprograms, pass System.Address + as void * or equivalent; this comprises GCC builtins. */ + if ((Has_Foreign_Convention (gnat_subprog) + || Is_Intrinsic_Subprogram (gnat_subprog)) && Is_Descendant_Of_Address (Underlying_Type (gnat_param_type))) gnu_param_type = ptr_type_node; else @@ -6303,7 +6305,7 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition, /* If this subprogram is expectedly bound to a GCC builtin, fetch the corresponding DECL node and check the parameter association. */ - if (Convention (gnat_subprog) == Convention_Intrinsic + if (Is_Intrinsic_Subprogram (gnat_subprog) && Present (Interface_Name (gnat_subprog))) { tree gnu_ext_name = create_concat_name (gnat_subprog, NULL); diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 8a192c7..dc2a03c 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -9079,7 +9079,7 @@ elaborate_all_entities_for_package (Entity_Id gnat_package) continue; /* Skip stuff internal to the compiler. */ - if (Convention (gnat_entity) == Convention_Intrinsic) + if (Is_Intrinsic_Subprogram (gnat_entity)) continue; if (kind == E_Operator) continue; diff --git a/gcc/ada/gen_il-gen-gen_entities.adb b/gcc/ada/gen_il-gen-gen_entities.adb index 1fa7f0b..d91faaa 100644 --- a/gcc/ada/gen_il-gen-gen_entities.adb +++ b/gcc/ada/gen_il-gen-gen_entities.adb @@ -252,7 +252,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Contract, Node_Id), Sm (Is_Elaboration_Warnings_OK_Id, Flag), Sm (Original_Record_Component, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Pragma, Node_Id), Sm (SPARK_Pragma_Inherited, Flag), Sm (Current_Value, Node_Id), -- setter only @@ -607,7 +607,7 @@ begin -- Gen_IL.Gen.Gen_Entities -- this is the first named subtype). Ab (Decimal_Fixed_Point_Kind, Fixed_Point_Kind, - (Sm (Digits_Value, Uint), + (Sm (Digits_Value, Upos), Sm (Has_Machine_Radix_Clause, Flag), Sm (Machine_Radix_10, Flag), Sm (Scale_Value, Uint))); @@ -623,7 +623,7 @@ begin -- Gen_IL.Gen.Gen_Entities -- first named subtype). Ab (Float_Kind, Real_Kind, - (Sm (Digits_Value, Uint))); + (Sm (Digits_Value, Upos))); Cc (E_Floating_Point_Type, Float_Kind); -- Floating point type, used for the anonymous base type of the @@ -866,23 +866,23 @@ begin -- Gen_IL.Gen.Gen_Entities -- A private type, created by a private type declaration that has -- neither the keyword limited nor the keyword tagged. (Sm (Scalar_Range, Node_Id), - Sm (Scope_Depth_Value, Uint))); + Sm (Scope_Depth_Value, Unat))); Cc (E_Private_Subtype, Private_Kind, -- A subtype of a private type, created by a subtype declaration used -- to declare a subtype of a private type. - (Sm (Scope_Depth_Value, Uint))); + (Sm (Scope_Depth_Value, Unat))); Cc (E_Limited_Private_Type, Private_Kind, -- A limited private type, created by a private type declaration that -- has the keyword limited, but not the keyword tagged. (Sm (Scalar_Range, Node_Id), - Sm (Scope_Depth_Value, Uint))); + Sm (Scope_Depth_Value, Unat))); Cc (E_Limited_Private_Subtype, Private_Kind, -- A subtype of a limited private type, created by a subtype declaration -- used to declare a subtype of a limited private type. - (Sm (Scope_Depth_Value, Uint))); + (Sm (Scope_Depth_Value, Unat))); Ab (Incomplete_Kind, Incomplete_Or_Private_Kind, (Sm (Non_Limited_View, Node_Id))); @@ -900,7 +900,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (First_Entity, Node_Id), Sm (First_Private_Entity, Node_Id), Sm (Last_Entity, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (Stored_Constraint, Elist_Id))); Ab (Task_Kind, Concurrent_Kind, @@ -1005,11 +1005,11 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Linker_Section_Pragma, Node_Id), Sm (Overridden_Operation, Node_Id), Sm (Protected_Body_Subprogram, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (Static_Call_Helper, Node_Id), Sm (SPARK_Pragma, Node_Id), Sm (SPARK_Pragma_Inherited, Flag), - Sm (Subps_Index, Uint))); + Sm (Subps_Index, Unat))); Cc (E_Function, Subprogram_Kind, -- A function, created by a function declaration or a function body @@ -1137,7 +1137,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Postconditions_Proc, Node_Id), Sm (Protected_Body_Subprogram, Node_Id), Sm (Protection_Object, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Pragma, Node_Id), Sm (SPARK_Pragma_Inherited, Flag))); @@ -1164,7 +1164,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Protected_Body_Subprogram, Node_Id), Sm (Protection_Object, Node_Id), Sm (Renamed_Or_Alias, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Pragma, Node_Id), Sm (SPARK_Pragma_Inherited, Flag))); @@ -1178,7 +1178,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Last_Entity, Node_Id), Sm (Renamed_Or_Alias, Node_Id), Sm (Return_Applies_To, Node_Id), - Sm (Scope_Depth_Value, Uint))); + Sm (Scope_Depth_Value, Unat))); Cc (E_Entry_Index_Parameter, Entity_Kind, -- An entry index parameter created by an entry index specification @@ -1209,7 +1209,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Is_Elaboration_Warnings_OK_Id, Flag), Sm (Last_Entity, Node_Id), Sm (Renamed_Or_Alias, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Pragma, Node_Id), Sm (SPARK_Pragma_Inherited, Flag))); @@ -1254,7 +1254,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Has_Loop_Entry_Attributes, Flag), Sm (Last_Entity, Node_Id), Sm (Renamed_Or_Alias, Node_Id), - Sm (Scope_Depth_Value, Uint))); + Sm (Scope_Depth_Value, Unat))); Cc (E_Return_Statement, Entity_Kind, -- A dummy entity created for each return statement. Used to hold @@ -1266,7 +1266,7 @@ begin -- Gen_IL.Gen.Gen_Entities (Sm (First_Entity, Node_Id), Sm (Last_Entity, Node_Id), Sm (Return_Applies_To, Node_Id), - Sm (Scope_Depth_Value, Uint))); + Sm (Scope_Depth_Value, Unat))); Cc (E_Package, Entity_Kind, -- A package, created by a package declaration @@ -1303,7 +1303,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Related_Instance, Node_Id), Sm (Renamed_In_Spec, Flag), Sm (Renamed_Or_Alias, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Aux_Pragma, Node_Id), Sm (SPARK_Aux_Pragma_Inherited, Flag), Sm (SPARK_Pragma, Node_Id), @@ -1323,7 +1323,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Last_Entity, Node_Id), Sm (Related_Instance, Node_Id), Sm (Renamed_Or_Alias, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Aux_Pragma, Node_Id), Sm (SPARK_Aux_Pragma_Inherited, Flag), Sm (SPARK_Pragma, Node_Id), @@ -1358,7 +1358,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Interface_Name, Node_Id), Sm (Last_Entity, Node_Id), Sm (Renamed_Or_Alias, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Pragma, Node_Id), Sm (SPARK_Pragma_Inherited, Flag))); diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb index 20d25ea..3b6bd68 100644 --- a/gcc/ada/gen_il-gen-gen_nodes.adb +++ b/gcc/ada/gen_il-gen-gen_nodes.adb @@ -984,7 +984,7 @@ begin -- Gen_IL.Gen.Gen_Nodes Cc (N_Case_Statement, N_Statement_Other_Than_Procedure_Call, (Sy (Expression, Node_Id, Default_Empty), Sy (Alternatives, List_Id, Default_No_List), - Sy (End_Span, Uint, Default_Uint_0), + Sy (End_Span, Unat, Default_Uint_0), Sm (From_Conditional_Expression, Flag))); Cc (N_Code_Statement, N_Statement_Other_Than_Procedure_Call, @@ -1094,7 +1094,7 @@ begin -- Gen_IL.Gen.Gen_Nodes Sy (Then_Statements, List_Id), Sy (Elsif_Parts, List_Id, Default_No_List), Sy (Else_Statements, List_Id, Default_No_List), - Sy (End_Span, Uint, Default_Uint_0), + Sy (End_Span, Unat, Default_Uint_0), Sm (From_Conditional_Expression, Flag))); Cc (N_Accept_Alternative, Node_Kind, @@ -1594,7 +1594,7 @@ begin -- Gen_IL.Gen.Gen_Nodes Sm (Dcheck_Function, Node_Id), Sm (Enclosing_Variant, Node_Id), Sm (Has_SP_Choice, Flag), - Sm (Present_Expr, Uint))); + Sm (Present_Expr, Valid_Uint))); Cc (N_Variant_Part, Node_Kind, (Sy (Name, Node_Id, Default_Empty), diff --git a/gcc/ada/gen_il-gen.adb b/gcc/ada/gen_il-gen.adb index e786251..eed98ee 100644 --- a/gcc/ada/gen_il-gen.adb +++ b/gcc/ada/gen_il-gen.adb @@ -1197,6 +1197,12 @@ package body Gen_IL.Gen is for F in First .. Last loop if Field_Table (F).Field_Type in Node_Or_Entity_Type then Result (Node_Id) := True; + + -- Subtypes of Uint all use the same Cast for Uint + + elsif Field_Table (F).Field_Type in Uint_Subtype then + Result (Uint) := True; + else Result (Field_Table (F).Field_Type) := True; end if; @@ -1767,6 +1773,7 @@ package body Gen_IL.Gen is end if; Put_Get_Set_Incr (S, F, "Set"); + Decrease_Indent (S, 3); Put (S, "end Set_" & Image (F) & ";" & LF & LF); end Put_Setter_Body; diff --git a/gcc/ada/gen_il-internals.adb b/gcc/ada/gen_il-internals.adb index fe1af78..a1a8062 100644 --- a/gcc/ada/gen_il-internals.adb +++ b/gcc/ada/gen_il-internals.adb @@ -370,7 +370,7 @@ package body Gen_IL.Internals is return Image (Default); else - -- Strip off the prefix and capitalize it + -- Strip off the prefix declare Im : constant String := Image (Default); diff --git a/gcc/ada/gen_il-internals.ads b/gcc/ada/gen_il-internals.ads index a811e0b4..7b095c0 100644 --- a/gcc/ada/gen_il-internals.ads +++ b/gcc/ada/gen_il-internals.ads @@ -133,7 +133,7 @@ package Gen_IL.Internals is Default_Uint_0); -- Uint -- Default value for a field in the Nmake functions. No_Default if the -- field parameter has no default value. Otherwise this indicates the - -- default value used, which must matcht the type of the field. + -- default value used, which must match the type of the field. function Image (Default : Field_Default_Value) return String; -- This will be something like "Default_Empty". @@ -191,7 +191,10 @@ package Gen_IL.Internals is function Special_Default (Field_Type : Type_Enum) return String is - (if Field_Type = Elist_Id then "No_Elist" else "Uint_0"); + (case Field_Type is + when Elist_Id => "No_Elist", + when Uint => "No_Uint", + when others => "can't happen"); ---------------- diff --git a/gcc/ada/gen_il-types.ads b/gcc/ada/gen_il-types.ads index 97b9dd2..9395e00 100644 --- a/gcc/ada/gen_il-types.ads +++ b/gcc/ada/gen_il-types.ads @@ -589,5 +589,7 @@ package Gen_IL.Types is subtype Uint_Subtype is Type_Enum with Predicate => Uint_Subtype in Valid_Uint | Unat | Upos | Nonzero_Uint; + -- These are the subtypes of Uint that have predicates restricting their + -- values. end Gen_IL.Types; diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 28f2f19..cae1fad 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -21,7 +21,7 @@ @copying @quotation -GNAT User's Guide for Native Platforms , Sep 28, 2021 +GNAT User's Guide for Native Platforms , Oct 19, 2021 AdaCore @@ -11800,6 +11800,34 @@ This switch suppresses warnings on cases of suspicious parameter ordering. @end table +@geindex -gnatw_p (gcc) + + +@table @asis + +@item @code{-gnatw_p} + +@emph{Activate warnings for pedantic checks.} + +This switch activates warnings for the failure of certain pedantic checks. +The only case currently supported is a check that the subtype_marks given +for corresponding formal parameter and function results in a subprogram +declaration and its body denote the same subtype declaration. The default +is that such warnings are not given. +@end table + +@geindex -gnatw_P (gcc) + + +@table @asis + +@item @code{-gnatw_P} + +@emph{Suppress warnings for pedantic checks.} + +This switch suppresses warnings on violations of pedantic checks. +@end table + @geindex -gnatwq (gcc) @geindex Parentheses diff --git a/gcc/ada/libgnat/g-io-put__vxworks.adb b/gcc/ada/libgnat/a-nbnbin__ghost.adb index 29307f9..7d22086 100644 --- a/gcc/ada/libgnat/g-io-put__vxworks.adb +++ b/gcc/ada/libgnat/a-nbnbin__ghost.adb @@ -2,11 +2,11 @@ -- -- -- GNAT RUN-TIME COMPONENTS -- -- -- --- G N A T . I O -- +-- ADA.NUMERICS.BIG_NUMBERS.BIG_INTEGERS -- -- -- -- B o d y -- -- -- --- Copyright (C) 1995-2021, AdaCore -- +-- Copyright (C) 2021, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -29,25 +29,48 @@ -- -- ------------------------------------------------------------------------------ --- vxworks zfp version of Put (C : Character) +-- This body is provided as a work-around for a GNAT compiler bug, as GNAT +-- currently does not compile instantiations of the spec with imported ghost +-- generics for packages Signed_Conversions and Unsigned_Conversions. -with Interfaces.C; use Interfaces.C; +package body Ada.Numerics.Big_Numbers.Big_Integers with + SPARK_Mode => Off +is -separate (GNAT.IO) -procedure Put (C : Character) is + package body Signed_Conversions with + SPARK_Mode => Off + is - function ioGlobalStdGet - (File : int) return int; - pragma Import (C, ioGlobalStdGet, "ioGlobalStdGet"); + function To_Big_Integer (Arg : Int) return Valid_Big_Integer is + begin + raise Program_Error; + return (null record); + end To_Big_Integer; - procedure fdprintf - (File : int; - Format : String; - Value : Character); - pragma Import (C, fdprintf, "fdprintf"); + function From_Big_Integer (Arg : Valid_Big_Integer) return Int is + begin + raise Program_Error; + return 0; + end From_Big_Integer; - Stdout_ID : constant int := 1; + end Signed_Conversions; -begin - fdprintf (ioGlobalStdGet (Stdout_ID), "%c" & ASCII.NUL, C); -end Put; + package body Unsigned_Conversions with + SPARK_Mode => Off + is + + function To_Big_Integer (Arg : Int) return Valid_Big_Integer is + begin + raise Program_Error; + return (null record); + end To_Big_Integer; + + function From_Big_Integer (Arg : Valid_Big_Integer) return Int is + begin + raise Program_Error; + return 0; + end From_Big_Integer; + + end Unsigned_Conversions; + +end Ada.Numerics.Big_Numbers.Big_Integers; diff --git a/gcc/ada/libgnat/a-nbnbin__ghost.ads b/gcc/ada/libgnat/a-nbnbin__ghost.ads new file mode 100644 index 0000000..3663dd7 --- /dev/null +++ b/gcc/ada/libgnat/a-nbnbin__ghost.ads @@ -0,0 +1,202 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT RUN-TIME COMPONENTS -- +-- -- +-- ADA.NUMERICS.BIG_NUMBERS.BIG_INTEGERS -- +-- -- +-- S p e c -- +-- -- +-- This specification is derived from the Ada Reference Manual for use with -- +-- GNAT. In accordance with the copyright of that document, you can freely -- +-- copy and modify this specification, provided that if you redistribute a -- +-- modified version, any changes that you have made are clearly indicated. -- +-- -- +------------------------------------------------------------------------------ + +package Ada.Numerics.Big_Numbers.Big_Integers with + SPARK_Mode, + Ghost, + Preelaborate +is + type Big_Integer is private + with Integer_Literal => From_Universal_Image; + + function Is_Valid (Arg : Big_Integer) return Boolean + with + Import, + Global => null; + + subtype Valid_Big_Integer is Big_Integer + with Dynamic_Predicate => Is_Valid (Valid_Big_Integer), + Predicate_Failure => raise Program_Error; + + function "=" (L, R : Valid_Big_Integer) return Boolean with + Import, + Global => null; + + function "<" (L, R : Valid_Big_Integer) return Boolean with + Import, + Global => null; + + function "<=" (L, R : Valid_Big_Integer) return Boolean with + Import, + Global => null; + + function ">" (L, R : Valid_Big_Integer) return Boolean with + Import, + Global => null; + + function ">=" (L, R : Valid_Big_Integer) return Boolean with + Import, + Global => null; + + function To_Big_Integer (Arg : Integer) return Valid_Big_Integer + with + Import, + Global => null; + + subtype Big_Positive is Big_Integer + with Dynamic_Predicate => + (if Is_Valid (Big_Positive) + then Big_Positive > To_Big_Integer (0)), + Predicate_Failure => (raise Constraint_Error); + + subtype Big_Natural is Big_Integer + with Dynamic_Predicate => + (if Is_Valid (Big_Natural) + then Big_Natural >= To_Big_Integer (0)), + Predicate_Failure => (raise Constraint_Error); + + function In_Range + (Arg : Valid_Big_Integer; Low, High : Big_Integer) return Boolean + is (Low <= Arg and Arg <= High) + with + Import, + Global => null; + + function To_Integer (Arg : Valid_Big_Integer) return Integer + with + Import, + Pre => In_Range (Arg, + Low => To_Big_Integer (Integer'First), + High => To_Big_Integer (Integer'Last)) + or else (raise Constraint_Error), + Global => null; + + generic + type Int is range <>; + package Signed_Conversions is + + function To_Big_Integer (Arg : Int) return Valid_Big_Integer + with + Global => null; + + function From_Big_Integer (Arg : Valid_Big_Integer) return Int + with + Pre => In_Range (Arg, + Low => To_Big_Integer (Int'First), + High => To_Big_Integer (Int'Last)) + or else (raise Constraint_Error), + Global => null; + end Signed_Conversions; + + generic + type Int is mod <>; + package Unsigned_Conversions is + + function To_Big_Integer (Arg : Int) return Valid_Big_Integer + with + Global => null; + + function From_Big_Integer (Arg : Valid_Big_Integer) return Int + with + Pre => In_Range (Arg, + Low => To_Big_Integer (Int'First), + High => To_Big_Integer (Int'Last)) + or else (raise Constraint_Error), + Global => null; + + end Unsigned_Conversions; + + function From_String (Arg : String) return Valid_Big_Integer + with + Import, + Global => null; + + function From_Universal_Image (Arg : String) return Valid_Big_Integer + renames From_String; + + function "+" (L : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "-" (L : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "abs" (L : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "+" (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "-" (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "*" (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "/" (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "mod" (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "rem" (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "**" (L : Valid_Big_Integer; R : Natural) return Valid_Big_Integer + with + Import, + Global => null; + + function Min (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function Max (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function Greatest_Common_Divisor + (L, R : Valid_Big_Integer) return Big_Positive + with + Import, + Pre => (L /= To_Big_Integer (0) and R /= To_Big_Integer (0)) + or else (raise Constraint_Error), + Global => null; + +private + pragma SPARK_Mode (Off); + + type Big_Integer is null record; + +end Ada.Numerics.Big_Numbers.Big_Integers; diff --git a/gcc/ada/libgnat/s-aoinar.adb b/gcc/ada/libgnat/s-aoinar.adb index 2f430ed..41d0cda 100644 --- a/gcc/ada/libgnat/s-aoinar.adb +++ b/gcc/ada/libgnat/s-aoinar.adb @@ -72,22 +72,10 @@ package body System.Atomic_Operations.Integer_Arithmetic is Value : Atomic_Type) return Atomic_Type is pragma Warnings (Off); - function Atomic_Fetch_Add_1 + function Atomic_Fetch_Add (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_1, "__atomic_fetch_add_1"); - function Atomic_Fetch_Add_2 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_2, "__atomic_fetch_add_2"); - function Atomic_Fetch_Add_4 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_4, "__atomic_fetch_add_4"); - function Atomic_Fetch_Add_8 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_8, "__atomic_fetch_add_8"); + pragma Import (Intrinsic, Atomic_Fetch_Add, "__atomic_fetch_add"); pragma Warnings (On); begin @@ -96,21 +84,14 @@ package body System.Atomic_Operations.Integer_Arithmetic is if Atomic_Type'Base'Last = Atomic_Type'Last and then Atomic_Type'Base'First = Atomic_Type'First - and then Atomic_Type'Last - in 2 ** 7 - 1 | 2 ** 15 - 1 | 2 ** 31 - 1 | 2 ** 63 - 1 + and then Atomic_Type'Last = 2**(Atomic_Type'Object_Size - 1) - 1 then - case Long_Long_Integer (Atomic_Type'Last) is - when 2 ** 7 - 1 => - return Atomic_Fetch_Add_1 (Item'Address, Value); - when 2 ** 15 - 1 => - return Atomic_Fetch_Add_2 (Item'Address, Value); - when 2 ** 31 - 1 => - return Atomic_Fetch_Add_4 (Item'Address, Value); - when 2 ** 63 - 1 => - return Atomic_Fetch_Add_8 (Item'Address, Value); - when others => - raise Program_Error; - end case; + if Atomic_Type'Object_Size in 8 | 16 | 32 | 64 then + return Atomic_Fetch_Add (Item'Address, Value); + else + raise Program_Error; + end if; + else declare Old_Value : aliased Atomic_Type := Item; @@ -138,22 +119,10 @@ package body System.Atomic_Operations.Integer_Arithmetic is Value : Atomic_Type) return Atomic_Type is pragma Warnings (Off); - function Atomic_Fetch_Sub_1 + function Atomic_Fetch_Sub (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_1, "__atomic_fetch_sub_1"); - function Atomic_Fetch_Sub_2 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_2, "__atomic_fetch_sub_2"); - function Atomic_Fetch_Sub_4 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_4, "__atomic_fetch_sub_4"); - function Atomic_Fetch_Sub_8 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_8, "__atomic_fetch_sub_8"); + pragma Import (Intrinsic, Atomic_Fetch_Sub, "__atomic_fetch_sub"); pragma Warnings (On); begin @@ -162,21 +131,14 @@ package body System.Atomic_Operations.Integer_Arithmetic is if Atomic_Type'Base'Last = Atomic_Type'Last and then Atomic_Type'Base'First = Atomic_Type'First - and then Atomic_Type'Last - in 2 ** 7 - 1 | 2 ** 15 - 1 | 2 ** 31 - 1 | 2 ** 63 - 1 + and then Atomic_Type'Last = 2**(Atomic_Type'Object_Size - 1) - 1 then - case Long_Long_Integer (Atomic_Type'Last) is - when 2 ** 7 - 1 => - return Atomic_Fetch_Sub_1 (Item'Address, Value); - when 2 ** 15 - 1 => - return Atomic_Fetch_Sub_2 (Item'Address, Value); - when 2 ** 31 - 1 => - return Atomic_Fetch_Sub_4 (Item'Address, Value); - when 2 ** 63 - 1 => - return Atomic_Fetch_Sub_8 (Item'Address, Value); - when others => - raise Program_Error; - end case; + if Atomic_Type'Object_Size in 8 | 16 | 32 | 64 then + return Atomic_Fetch_Sub (Item'Address, Value); + else + raise Program_Error; + end if; + else declare Old_Value : aliased Atomic_Type := Item; diff --git a/gcc/ada/libgnat/s-aomoar.adb b/gcc/ada/libgnat/s-aomoar.adb index a6f4b0e..617a5b3 100644 --- a/gcc/ada/libgnat/s-aomoar.adb +++ b/gcc/ada/libgnat/s-aomoar.adb @@ -72,48 +72,26 @@ package body System.Atomic_Operations.Modular_Arithmetic is Value : Atomic_Type) return Atomic_Type is pragma Warnings (Off); - function Atomic_Fetch_Add_1 + function Atomic_Fetch_Add (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_1, "__atomic_fetch_add_1"); - function Atomic_Fetch_Add_2 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_2, "__atomic_fetch_add_2"); - function Atomic_Fetch_Add_4 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_4, "__atomic_fetch_add_4"); - function Atomic_Fetch_Add_8 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_8, "__atomic_fetch_add_8"); + pragma Import (Intrinsic, Atomic_Fetch_Add, "__atomic_fetch_add"); pragma Warnings (On); begin -- Use the direct intrinsics when possible, and fallback to -- compare-and-exchange otherwise. - -- Also suppress spurious warnings. - pragma Warnings (Off); if Atomic_Type'Base'Last = Atomic_Type'Last and then Atomic_Type'First = 0 - and then Atomic_Type'Last - in 2 ** 8 - 1 | 2 ** 16 - 1 | 2 ** 32 - 1 | 2 ** 64 - 1 + and then Atomic_Type'Last = 2**Atomic_Type'Object_Size - 1 then - pragma Warnings (On); - case Unsigned_64 (Atomic_Type'Last) is - when 2 ** 8 - 1 => - return Atomic_Fetch_Add_1 (Item'Address, Value); - when 2 ** 16 - 1 => - return Atomic_Fetch_Add_2 (Item'Address, Value); - when 2 ** 32 - 1 => - return Atomic_Fetch_Add_4 (Item'Address, Value); - when 2 ** 64 - 1 => - return Atomic_Fetch_Add_8 (Item'Address, Value); - when others => - raise Program_Error; - end case; + if Atomic_Type'Object_Size in 8 | 16 | 32 | 64 then + return Atomic_Fetch_Add (Item'Address, Value); + else + raise Program_Error; + end if; + else declare Old_Value : aliased Atomic_Type := Item; @@ -141,48 +119,26 @@ package body System.Atomic_Operations.Modular_Arithmetic is Value : Atomic_Type) return Atomic_Type is pragma Warnings (Off); - function Atomic_Fetch_Sub_1 + function Atomic_Fetch_Sub (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_1, "__atomic_fetch_sub_1"); - function Atomic_Fetch_Sub_2 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_2, "__atomic_fetch_sub_2"); - function Atomic_Fetch_Sub_4 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_4, "__atomic_fetch_sub_4"); - function Atomic_Fetch_Sub_8 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_8, "__atomic_fetch_sub_8"); + pragma Import (Intrinsic, Atomic_Fetch_Sub, "__atomic_fetch_sub"); pragma Warnings (On); begin -- Use the direct intrinsics when possible, and fallback to -- compare-and-exchange otherwise. - -- Also suppress spurious warnings. - pragma Warnings (Off); if Atomic_Type'Base'Last = Atomic_Type'Last and then Atomic_Type'First = 0 - and then Atomic_Type'Last - in 2 ** 8 - 1 | 2 ** 16 - 1 | 2 ** 32 - 1 | 2 ** 64 - 1 + and then Atomic_Type'Last = 2**Atomic_Type'Object_Size - 1 then - pragma Warnings (On); - case Unsigned_64 (Atomic_Type'Last) is - when 2 ** 8 - 1 => - return Atomic_Fetch_Sub_1 (Item'Address, Value); - when 2 ** 16 - 1 => - return Atomic_Fetch_Sub_2 (Item'Address, Value); - when 2 ** 32 - 1 => - return Atomic_Fetch_Sub_4 (Item'Address, Value); - when 2 ** 64 - 1 => - return Atomic_Fetch_Sub_8 (Item'Address, Value); - when others => - raise Program_Error; - end case; + if Atomic_Type'Object_Size in 8 | 16 | 32 | 64 then + return Atomic_Fetch_Sub (Item'Address, Value); + else + raise Program_Error; + end if; + else declare Old_Value : aliased Atomic_Type := Item; diff --git a/gcc/ada/libgnat/s-atopex.adb b/gcc/ada/libgnat/s-atopex.adb index b0aa9e5..65e9433 100644 --- a/gcc/ada/libgnat/s-atopex.adb +++ b/gcc/ada/libgnat/s-atopex.adb @@ -43,36 +43,19 @@ package body System.Atomic_Operations.Exchange is Value : Atomic_Type) return Atomic_Type is pragma Warnings (Off); - function Atomic_Exchange_1 + function Atomic_Exchange (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Exchange_1, "__atomic_exchange_1"); - function Atomic_Exchange_2 - (Ptr : System.Address; - Val : Atomic_Type; - Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Exchange_2, "__atomic_exchange_2"); - function Atomic_Exchange_4 - (Ptr : System.Address; - Val : Atomic_Type; - Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Exchange_4, "__atomic_exchange_4"); - function Atomic_Exchange_8 - (Ptr : System.Address; - Val : Atomic_Type; - Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Exchange_8, "__atomic_exchange_8"); + pragma Import (Intrinsic, Atomic_Exchange, "__atomic_exchange_n"); pragma Warnings (On); begin - case Atomic_Type'Object_Size is - when 8 => return Atomic_Exchange_1 (Item'Address, Value); - when 16 => return Atomic_Exchange_2 (Item'Address, Value); - when 32 => return Atomic_Exchange_4 (Item'Address, Value); - when 64 => return Atomic_Exchange_8 (Item'Address, Value); - when others => raise Program_Error; - end case; + if Atomic_Type'Object_Size in 8 | 16 | 32 | 64 then + return Atomic_Exchange (Item'Address, Value); + else + raise Program_Error; + end if; end Atomic_Exchange; --------------------------------- @@ -85,34 +68,7 @@ package body System.Atomic_Operations.Exchange is Desired : Atomic_Type) return Boolean is pragma Warnings (Off); - function Atomic_Compare_Exchange_1 - (Ptr : System.Address; - Expected : System.Address; - Desired : Atomic_Type; - Weak : Boolean := False; - Success_Model : Mem_Model := Seq_Cst; - Failure_Model : Mem_Model := Seq_Cst) return Boolean; - pragma Import - (Intrinsic, Atomic_Compare_Exchange_1, "__atomic_compare_exchange_1"); - function Atomic_Compare_Exchange_2 - (Ptr : System.Address; - Expected : System.Address; - Desired : Atomic_Type; - Weak : Boolean := False; - Success_Model : Mem_Model := Seq_Cst; - Failure_Model : Mem_Model := Seq_Cst) return Boolean; - pragma Import - (Intrinsic, Atomic_Compare_Exchange_2, "__atomic_compare_exchange_2"); - function Atomic_Compare_Exchange_4 - (Ptr : System.Address; - Expected : System.Address; - Desired : Atomic_Type; - Weak : Boolean := False; - Success_Model : Mem_Model := Seq_Cst; - Failure_Model : Mem_Model := Seq_Cst) return Boolean; - pragma Import - (Intrinsic, Atomic_Compare_Exchange_4, "__atomic_compare_exchange_4"); - function Atomic_Compare_Exchange_8 + function Atomic_Compare_Exchange (Ptr : System.Address; Expected : System.Address; Desired : Atomic_Type; @@ -120,26 +76,15 @@ package body System.Atomic_Operations.Exchange is Success_Model : Mem_Model := Seq_Cst; Failure_Model : Mem_Model := Seq_Cst) return Boolean; pragma Import - (Intrinsic, Atomic_Compare_Exchange_8, "__atomic_compare_exchange_8"); + (Intrinsic, Atomic_Compare_Exchange, "__atomic_compare_exchange_n"); pragma Warnings (On); begin - case Atomic_Type'Object_Size is - when 8 => - return - Atomic_Compare_Exchange_1 (Item'Address, Prior'Address, Desired); - when 16 => - return - Atomic_Compare_Exchange_2 (Item'Address, Prior'Address, Desired); - when 32 => - return - Atomic_Compare_Exchange_4 (Item'Address, Prior'Address, Desired); - when 64 => - return - Atomic_Compare_Exchange_8 (Item'Address, Prior'Address, Desired); - when others => - raise Program_Error; - end case; + if Atomic_Type'Object_Size in 8 | 16 | 32 | 64 then + return Atomic_Compare_Exchange (Item'Address, Prior'Address, Desired); + else + raise Program_Error; + end if; end Atomic_Compare_And_Exchange; ------------------ diff --git a/gcc/ada/libgnat/s-atopri.adb b/gcc/ada/libgnat/s-atopri.adb index ba284f0..20aa666 100644 --- a/gcc/ada/libgnat/s-atopri.adb +++ b/gcc/ada/libgnat/s-atopri.adb @@ -31,103 +31,39 @@ package body System.Atomic_Primitives is - ---------------------- - -- Lock_Free_Read_8 -- - ---------------------- + -------------------- + -- Lock_Free_Read -- + -------------------- - function Lock_Free_Read_8 (Ptr : Address) return uint8 is - begin - if uint8'Atomic_Always_Lock_Free then - return Atomic_Load_8 (Ptr, Acquire); - else - raise Program_Error; - end if; - end Lock_Free_Read_8; - - ----------------------- - -- Lock_Free_Read_16 -- - ----------------------- + function Lock_Free_Read (Ptr : Address) return Atomic_Type is + function My_Atomic_Load is new Atomic_Load (Atomic_Type); - function Lock_Free_Read_16 (Ptr : Address) return uint16 is begin - if uint16'Atomic_Always_Lock_Free then - return Atomic_Load_16 (Ptr, Acquire); + if Atomic_Type'Atomic_Always_Lock_Free then + return My_Atomic_Load (Ptr, Acquire); else raise Program_Error; end if; - end Lock_Free_Read_16; + end Lock_Free_Read; - ----------------------- - -- Lock_Free_Read_32 -- - ----------------------- - - function Lock_Free_Read_32 (Ptr : Address) return uint32 is - begin - if uint32'Atomic_Always_Lock_Free then - return Atomic_Load_32 (Ptr, Acquire); - else - raise Program_Error; - end if; - end Lock_Free_Read_32; + ------------------------- + -- Lock_Free_Try_Write -- + ------------------------- - ----------------------- - -- Lock_Free_Read_64 -- - ----------------------- - - function Lock_Free_Read_64 (Ptr : Address) return uint64 is - begin - if uint64'Atomic_Always_Lock_Free then - return Atomic_Load_64 (Ptr, Acquire); - else - raise Program_Error; - end if; - end Lock_Free_Read_64; - - --------------------------- - -- Lock_Free_Try_Write_8 -- - --------------------------- - - function Lock_Free_Try_Write_8 + function Lock_Free_Try_Write (Ptr : Address; - Expected : in out uint8; - Desired : uint8) return Boolean + Expected : in out Atomic_Type; + Desired : Atomic_Type) return Boolean is - Actual : uint8; + function My_Sync_Compare_And_Swap is + new Sync_Compare_And_Swap (Atomic_Type); - begin - if Expected /= Desired then - - if uint8'Atomic_Always_Lock_Free then - Actual := Sync_Compare_And_Swap_8 (Ptr, Expected, Desired); - else - raise Program_Error; - end if; - - if Actual /= Expected then - Expected := Actual; - return False; - end if; - end if; - - return True; - end Lock_Free_Try_Write_8; - - ---------------------------- - -- Lock_Free_Try_Write_16 -- - ---------------------------- - - function Lock_Free_Try_Write_16 - (Ptr : Address; - Expected : in out uint16; - Desired : uint16) return Boolean - is - Actual : uint16; + Actual : Atomic_Type; begin if Expected /= Desired then - - if uint16'Atomic_Always_Lock_Free then - Actual := Sync_Compare_And_Swap_16 (Ptr, Expected, Desired); + if Atomic_Type'Atomic_Always_Lock_Free then + Actual := My_Sync_Compare_And_Swap (Ptr, Expected, Desired); else raise Program_Error; end if; @@ -139,63 +75,6 @@ package body System.Atomic_Primitives is end if; return True; - end Lock_Free_Try_Write_16; - - ---------------------------- - -- Lock_Free_Try_Write_32 -- - ---------------------------- + end Lock_Free_Try_Write; - function Lock_Free_Try_Write_32 - (Ptr : Address; - Expected : in out uint32; - Desired : uint32) return Boolean - is - Actual : uint32; - - begin - if Expected /= Desired then - - if uint32'Atomic_Always_Lock_Free then - Actual := Sync_Compare_And_Swap_32 (Ptr, Expected, Desired); - else - raise Program_Error; - end if; - - if Actual /= Expected then - Expected := Actual; - return False; - end if; - end if; - - return True; - end Lock_Free_Try_Write_32; - - ---------------------------- - -- Lock_Free_Try_Write_64 -- - ---------------------------- - - function Lock_Free_Try_Write_64 - (Ptr : Address; - Expected : in out uint64; - Desired : uint64) return Boolean - is - Actual : uint64; - - begin - if Expected /= Desired then - - if uint64'Atomic_Always_Lock_Free then - Actual := Sync_Compare_And_Swap_64 (Ptr, Expected, Desired); - else - raise Program_Error; - end if; - - if Actual /= Expected then - Expected := Actual; - return False; - end if; - end if; - - return True; - end Lock_Free_Try_Write_64; end System.Atomic_Primitives; diff --git a/gcc/ada/libgnat/s-atopri.ads b/gcc/ada/libgnat/s-atopri.ads index 891b2ed..ea03f1a 100644 --- a/gcc/ada/libgnat/s-atopri.ads +++ b/gcc/ada/libgnat/s-atopri.ads @@ -29,7 +29,7 @@ -- -- ------------------------------------------------------------------------------ --- This package contains both atomic primitives defined from gcc built-in +-- This package contains both atomic primitives defined from GCC built-in -- functions and operations used by the compiler to generate the lock-free -- implementation of protected objects. @@ -66,71 +66,31 @@ package System.Atomic_Primitives is -- GCC built-in atomic primitives -- ------------------------------------ - function Atomic_Load_8 + generic + type Atomic_Type is mod <>; + function Atomic_Load (Ptr : Address; - Model : Mem_Model := Seq_Cst) return uint8; - pragma Import (Intrinsic, Atomic_Load_8, "__atomic_load_1"); + Model : Mem_Model := Seq_Cst) return Atomic_Type; + pragma Import (Intrinsic, Atomic_Load, "__atomic_load_n"); - function Atomic_Load_16 - (Ptr : Address; - Model : Mem_Model := Seq_Cst) return uint16; - pragma Import (Intrinsic, Atomic_Load_16, "__atomic_load_2"); - - function Atomic_Load_32 - (Ptr : Address; - Model : Mem_Model := Seq_Cst) return uint32; - pragma Import (Intrinsic, Atomic_Load_32, "__atomic_load_4"); - - function Atomic_Load_64 - (Ptr : Address; - Model : Mem_Model := Seq_Cst) return uint64; - pragma Import (Intrinsic, Atomic_Load_64, "__atomic_load_8"); - - function Sync_Compare_And_Swap_8 - (Ptr : Address; - Expected : uint8; - Desired : uint8) return uint8; - pragma Import (Intrinsic, - Sync_Compare_And_Swap_8, - "__sync_val_compare_and_swap_1"); - - function Sync_Compare_And_Swap_16 - (Ptr : Address; - Expected : uint16; - Desired : uint16) return uint16; - pragma Import (Intrinsic, - Sync_Compare_And_Swap_16, - "__sync_val_compare_and_swap_2"); + function Atomic_Load_8 is new Atomic_Load (uint8); + function Atomic_Load_16 is new Atomic_Load (uint16); + function Atomic_Load_32 is new Atomic_Load (uint32); + function Atomic_Load_64 is new Atomic_Load (uint64); - function Sync_Compare_And_Swap_32 + generic + type Atomic_Type is mod <>; + function Sync_Compare_And_Swap (Ptr : Address; - Expected : uint32; - Desired : uint32) return uint32; - pragma Import (Intrinsic, - Sync_Compare_And_Swap_32, - "__sync_val_compare_and_swap_4"); + Expected : Atomic_Type; + Desired : Atomic_Type) return Atomic_Type; + pragma Import + (Intrinsic, Sync_Compare_And_Swap, "__sync_val_compare_and_swap"); - function Sync_Compare_And_Swap_64 - (Ptr : Address; - Expected : uint64; - Desired : uint64) return uint64; - pragma Import (Intrinsic, - Sync_Compare_And_Swap_64, - "__sync_val_compare_and_swap_8"); - - -- ??? We might want to switch to the __atomic series of builtins for - -- compare-and-swap operations at some point. - - -- function Atomic_Compare_Exchange_8 - -- (Ptr : Address; - -- Expected : Address; - -- Desired : uint8; - -- Weak : Boolean := False; - -- Success_Model : Mem_Model := Seq_Cst; - -- Failure_Model : Mem_Model := Seq_Cst) return Boolean; - -- pragma Import (Intrinsic, - -- Atomic_Compare_Exchange_8, - -- "__atomic_compare_exchange_1"); + function Sync_Compare_And_Swap_8 is new Sync_Compare_And_Swap (uint8); + function Sync_Compare_And_Swap_16 is new Sync_Compare_And_Swap (uint16); + function Sync_Compare_And_Swap_32 is new Sync_Compare_And_Swap (uint32); + function Sync_Compare_And_Swap_64 is new Sync_Compare_And_Swap (uint64); function Atomic_Test_And_Set (Ptr : System.Address; @@ -155,46 +115,37 @@ package System.Atomic_Primitives is -- The lock-free implementation uses two atomic instructions for the -- expansion of protected operations: - -- * Lock_Free_Read_N atomically loads the value of the protected component - -- accessed by the current protected operation. - - -- * Lock_Free_Try_Write_N tries to write the Desired value into Ptr only - -- if Expected and Desired mismatch. + -- * Lock_Free_Read atomically loads the value contained in Ptr (with the + -- Acquire synchronization mode). - function Lock_Free_Read_8 (Ptr : Address) return uint8; + -- * Lock_Free_Try_Write atomically tries to write the Desired value into + -- Ptr if Ptr contains the Expected value. It returns true if the value + -- in Ptr was changed, or False if it was not, in which case Expected is + -- updated to the unexpected value in Ptr. Note that it does nothing and + -- returns true if Desired and Expected are equal. - function Lock_Free_Read_16 (Ptr : Address) return uint16; + generic + type Atomic_Type is mod <>; + function Lock_Free_Read (Ptr : Address) return Atomic_Type; - function Lock_Free_Read_32 (Ptr : Address) return uint32; + function Lock_Free_Read_8 is new Lock_Free_Read (uint8); + function Lock_Free_Read_16 is new Lock_Free_Read (uint16); + function Lock_Free_Read_32 is new Lock_Free_Read (uint32); + function Lock_Free_Read_64 is new Lock_Free_Read (uint64); - function Lock_Free_Read_64 (Ptr : Address) return uint64; - - function Lock_Free_Try_Write_8 - (Ptr : Address; - Expected : in out uint8; - Desired : uint8) return Boolean; - - function Lock_Free_Try_Write_16 - (Ptr : Address; - Expected : in out uint16; - Desired : uint16) return Boolean; - - function Lock_Free_Try_Write_32 - (Ptr : Address; - Expected : in out uint32; - Desired : uint32) return Boolean; + generic + type Atomic_Type is mod <>; + function Lock_Free_Try_Write + (Ptr : Address; + Expected : in out Atomic_Type; + Desired : Atomic_Type) return Boolean; - function Lock_Free_Try_Write_64 - (Ptr : Address; - Expected : in out uint64; - Desired : uint64) return Boolean; + function Lock_Free_Try_Write_8 is new Lock_Free_Try_Write (uint8); + function Lock_Free_Try_Write_16 is new Lock_Free_Try_Write (uint16); + function Lock_Free_Try_Write_32 is new Lock_Free_Try_Write (uint32); + function Lock_Free_Try_Write_64 is new Lock_Free_Try_Write (uint64); - pragma Inline (Lock_Free_Read_8); - pragma Inline (Lock_Free_Read_16); - pragma Inline (Lock_Free_Read_32); - pragma Inline (Lock_Free_Read_64); - pragma Inline (Lock_Free_Try_Write_8); - pragma Inline (Lock_Free_Try_Write_16); - pragma Inline (Lock_Free_Try_Write_32); - pragma Inline (Lock_Free_Try_Write_64); +private + pragma Inline (Lock_Free_Read); + pragma Inline (Lock_Free_Try_Write); end System.Atomic_Primitives; diff --git a/gcc/ada/libgnat/s-parame__ae653.ads b/gcc/ada/libgnat/s-parame__ae653.ads deleted file mode 100644 index a3e2351..0000000 --- a/gcc/ada/libgnat/s-parame__ae653.ads +++ /dev/null @@ -1,196 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT COMPILER COMPONENTS -- --- -- --- S Y S T E M . P A R A M E T E R S -- --- -- --- S p e c -- --- -- --- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- Version is used by VxWorks 653, VxWorks MILS, and VxWorks6 cert Ravenscar - --- This package defines some system dependent parameters for GNAT. These --- are values that are referenced by the runtime library and are therefore --- relevant to the target machine. - --- The parameters whose value is defined in the spec are not generally --- expected to be changed. If they are changed, it will be necessary to --- recompile the run-time library. - --- The parameters which are defined by functions can be changed by modifying --- the body of System.Parameters in file s-parame.adb. A change to this body --- requires only rebinding and relinking of the application. - --- Note: do not introduce any pragma Inline statements into this unit, since --- otherwise the relinking and rebinding capability would be deactivated. - -package System.Parameters is - pragma Pure; - - --------------------------------------- - -- Task And Stack Allocation Control -- - --------------------------------------- - - type Size_Type is range - -(2 ** (Integer'(Standard'Address_Size) - 1)) .. - +(2 ** (Integer'(Standard'Address_Size) - 1)) - 1; - -- Type used to provide task stack sizes to the runtime. Sized to permit - -- stack sizes of up to half the total addressable memory space. This may - -- seem excessively large (even for 32-bit systems), however there are many - -- instances of users requiring large stack sizes (for example string - -- processing). - - Unspecified_Size : constant Size_Type := Size_Type'First; - -- Value used to indicate that no size type is set - - function Default_Stack_Size return Size_Type; - -- Default task stack size used if none is specified - - function Minimum_Stack_Size return Size_Type; - -- Minimum task stack size permitted - - function Adjust_Storage_Size (Size : Size_Type) return Size_Type; - -- Given the storage size stored in the TCB, return the Storage_Size - -- value required by the RM for the Storage_Size attribute. The - -- required adjustment is as follows: - -- - -- when Size = Unspecified_Size, return Default_Stack_Size - -- when Size < Minimum_Stack_Size, return Minimum_Stack_Size - -- otherwise return given Size - - Default_Env_Stack_Size : constant Size_Type := 14_336; - -- Assumed size of the environment task, if no other information - -- is available. This value is used when stack checking is - -- enabled and no GNAT_STACK_LIMIT environment variable is set. - -- This value is chosen as the VxWorks default stack size is 20kB, - -- and a little more than 4kB is necessary for the run time. - - Stack_Grows_Down : constant Boolean := True; - -- This constant indicates whether the stack grows up (False) or - -- down (True) in memory as functions are called. It is used for - -- proper implementation of the stack overflow check. - - Runtime_Default_Sec_Stack_Size : constant Size_Type := 10 * 1024; - -- The run-time chosen default size for secondary stacks that may be - -- overridden by the user with the use of binder -D switch. - - Sec_Stack_Dynamic : constant Boolean := False; - -- Indicates if secondary stacks can grow and shrink at run-time. If False, - -- the size of a secondary stack is fixed at the point of its creation. - - ------------------------------------ - -- Characteristics of time_t type -- - ------------------------------------ - - -- IMPORTANT NOTE: - -- time_t_bits must match the size specified in the VSB. - - time_t_bits : constant := Long_Long_Integer'Size; - -- Number of bits in type time_t for SR0660 and newer, - -- with the default configuration of the VSB. - - ---------------------------------------------- - -- Characteristics of types in Interfaces.C -- - ---------------------------------------------- - - long_bits : constant := Long_Integer'Size; - -- Number of bits in type long and unsigned_long. The normal convention - -- is that this is the same as type Long_Integer, but this may not be true - -- of all targets. - - ptr_bits : constant := Standard'Address_Size; - subtype C_Address is System.Address; - -- Number of bits in Interfaces.C pointers, normally a standard address - - C_Malloc_Linkname : constant String := "__gnat_malloc"; - -- Name of runtime function used to allocate such a pointer - - ---------------------------------------------- - -- Behavior of Pragma Finalize_Storage_Only -- - ---------------------------------------------- - - -- Garbage_Collected is a Boolean constant whose value indicates the - -- effect of the pragma Finalize_Storage_Entry on a controlled type. - - -- Garbage_Collected = False - - -- The system releases all storage on program termination only, - -- but not other garbage collection occurs, so finalization calls - -- are omitted only for outer level objects can be omitted if - -- pragma Finalize_Storage_Only is used. - - -- Garbage_Collected = True - - -- The system provides full garbage collection, so it is never - -- necessary to release storage for controlled objects for which - -- a pragma Finalize_Storage_Only is used. - - Garbage_Collected : constant Boolean := False; - -- The storage mode for this system (release on program exit) - - --------------------- - -- Tasking Profile -- - --------------------- - - -- In the following sections, constant parameters are defined to - -- allow some optimizations and fine tuning within the tasking run time - -- based on restrictions on the tasking features. - - ------------------- - -- Task Abortion -- - ------------------- - - No_Abort : constant Boolean := False; - -- This constant indicates whether abort statements and asynchronous - -- transfer of control (ATC) are disallowed. If set to True, it is - -- assumed that neither construct is used, and the run time does not - -- need to defer/undefer abort and check for pending actions at - -- completion points. A value of True for No_Abort corresponds to: - -- pragma Restrictions (No_Abort_Statements); - -- pragma Restrictions (Max_Asynchronous_Select_Nesting => 0); - - --------------------- - -- Task Attributes -- - --------------------- - - Max_Attribute_Count : constant := 8; - -- Number of task attributes stored in the task control block - - ----------------------- - -- Task Image Length -- - ----------------------- - - Max_Task_Image_Length : constant := 32; - -- This constant specifies the maximum length of a task's image - - ------------------------------ - -- Exception Message Length -- - ------------------------------ - - Default_Exception_Msg_Max_Length : constant := 200; - -- This constant specifies the default number of characters to allow - -- in an exception message (200 is minimum required by RM 11.4.1(18)). - -end System.Parameters; diff --git a/gcc/ada/libgnat/s-thread.ads b/gcc/ada/libgnat/s-thread.ads deleted file mode 100644 index 6508df5..0000000 --- a/gcc/ada/libgnat/s-thread.ads +++ /dev/null @@ -1,92 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT COMPILER COMPONENTS -- --- -- --- S Y S T E M . T H R E A D S -- --- -- --- S p e c -- --- -- --- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- This package provides facilities to register a thread to the runtime, --- and allocate its task specific datas. - --- This package is currently implemented for: - --- VxWorks7r2Cert Light - -with Ada.Unchecked_Conversion; - -with Interfaces.C; - -with System.Secondary_Stack; - -package System.Threads is - - package SST renames System.Secondary_Stack; - - type ATSD is limited private; - -- Type of the Ada thread specific data. It contains datas needed - -- by the GNAT runtime. - - type ATSD_Access is access ATSD; - function From_Address is - new Ada.Unchecked_Conversion (Address, ATSD_Access); - - subtype STATUS is Interfaces.C.int; - -- Equivalent of the C type STATUS - - type t_id is new Interfaces.C.long; - subtype Thread_Id is t_id; - - function Register (T : Thread_Id) return STATUS; - -- Create the task specific data necessary for Ada language support - - -------------------------- - -- Thread Body Handling -- - -------------------------- - - -- The subprograms in this section are called from the process body - -- wrapper in the APEX process registration package. - - procedure Thread_Body_Enter - (Sec_Stack_Ptr : SST.SS_Stack_Ptr; - Process_ATSD_Address : System.Address); - -- Enter thread body, see above for details - - procedure Thread_Body_Leave; - -- Leave thread body (normally), see above for details - - procedure Thread_Body_Exceptional_Exit; - -- Leave thread body (abnormally on exception), see above for details - -private - - type ATSD is record - Sec_Stack_Ptr : SST.SS_Stack_Ptr; - -- Pointer of the allocated secondary stack - - end record; - -end System.Threads; diff --git a/gcc/ada/libgnat/s-thread__ae653.adb b/gcc/ada/libgnat/s-thread__ae653.adb deleted file mode 100644 index 2282a66..0000000 --- a/gcc/ada/libgnat/s-thread__ae653.adb +++ /dev/null @@ -1,163 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT COMPILER COMPONENTS -- --- -- --- S Y S T E M . T H R E A D S -- --- -- --- B o d y -- --- -- --- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- This is the VxWorks7r2Cert Light version of this package - -pragma Restrictions (No_Tasking); --- The VxWorks7r2Cert Light version of this package is intended only --- for programs which do not use Ada tasking. This restriction ensures --- that this will be checked by the binder. - -with System.Storage_Elements; use System.Storage_Elements; - -package body System.Threads is - - use Interfaces.C; - - Main_ATSD : aliased ATSD; - -- TSD for environment task - - Current_ATSD : aliased System.Address := System.Null_Address; - pragma Thread_Local_Storage (Current_ATSD); - -- pragma TLS needed since TaskVarAdd no longer available - - -- VxWorks specific API - ERROR : constant STATUS := Interfaces.C.int (-1); - OK : constant STATUS := Interfaces.C.int (0); - - function taskIdVerify (tid : t_id) return STATUS; - pragma Import (C, taskIdVerify, "taskIdVerify"); - - function taskIdSelf return t_id; - pragma Import (C, taskIdSelf, "taskIdSelf"); - - ----------------------- - -- Local Subprograms -- - ----------------------- - - procedure Init_RTS; - -- This procedure performs the initialization of the run-time lib. - -- It installs System.Threads versions of certain operations of the - -- run-time lib. - - function Get_Sec_Stack return SST.SS_Stack_Ptr; - - ----------------------- - -- Thread_Body_Enter -- - ----------------------- - - procedure Thread_Body_Enter - (Sec_Stack_Ptr : SST.SS_Stack_Ptr; - Process_ATSD_Address : System.Address) - is - - ATSD : constant ATSD_Access := From_Address (Process_ATSD_Address); - - begin - - ATSD.Sec_Stack_Ptr := Sec_Stack_Ptr; - SST.SS_Init (ATSD.Sec_Stack_Ptr); - Current_ATSD := Process_ATSD_Address; - - end Thread_Body_Enter; - - ---------------------------------- - -- Thread_Body_Exceptional_Exit -- - ---------------------------------- - - procedure Thread_Body_Exceptional_Exit is - begin - -- No action for this target - - null; - end Thread_Body_Exceptional_Exit; - - ----------------------- - -- Thread_Body_Leave -- - ----------------------- - - procedure Thread_Body_Leave is - begin - -- No action for this target - - null; - end Thread_Body_Leave; - - -------------- - -- Init_RTS -- - -------------- - - procedure Init_RTS is - -- Register environment task - Result : constant Interfaces.C.int := Register (taskIdSelf); - pragma Assert (Result /= ERROR); - - begin - Main_ATSD.Sec_Stack_Ptr := Get_Sec_Stack; - Current_ATSD := Main_ATSD'Address; - end Init_RTS; - - ------------------- - -- Get_Sec_Stack -- - ------------------- - - function Get_Sec_Stack return SST.SS_Stack_Ptr is - CTSD : constant ATSD_Access := From_Address (Current_ATSD); - begin - pragma Assert (CTSD /= null); - return CTSD.Sec_Stack_Ptr; - end Get_Sec_Stack; - - -------------- - -- Register -- - -------------- - - function Register (T : Thread_Id) return STATUS is - begin - -- It cannot be assumed that the caller of this routine has a ATSD; - -- so neither this procedure nor the procedures that it calls should - -- raise or handle exceptions, or make use of a secondary stack. - - if taskIdVerify (T) = ERROR then - return ERROR; - end if; - - Current_ATSD := To_Address (Integer_Address (T)); - - return OK; - end Register; - -begin - -- Initialize run-time library - - Init_RTS; - -end System.Threads; diff --git a/gcc/ada/libgnat/s-widlllu.ads b/gcc/ada/libgnat/s-widlllu.ads index 018e740..10a0c9c 100644 --- a/gcc/ada/libgnat/s-widlllu.ads +++ b/gcc/ada/libgnat/s-widlllu.ads @@ -34,8 +34,9 @@ with System.Width_U; with System.Unsigned_Types; -package System.Wid_LLLU is - +package System.Wid_LLLU + with SPARK_Mode +is subtype Long_Long_Long_Unsigned is Unsigned_Types.Long_Long_Long_Unsigned; function Width_Long_Long_Long_Unsigned is diff --git a/gcc/ada/libgnat/s-widllu.ads b/gcc/ada/libgnat/s-widllu.ads index ab7ec58..7eaf966 100644 --- a/gcc/ada/libgnat/s-widllu.ads +++ b/gcc/ada/libgnat/s-widllu.ads @@ -34,8 +34,9 @@ with System.Width_U; with System.Unsigned_Types; -package System.Wid_LLU is - +package System.Wid_LLU + with SPARK_Mode +is subtype Long_Long_Unsigned is Unsigned_Types.Long_Long_Unsigned; function Width_Long_Long_Unsigned is new Width_U (Long_Long_Unsigned); diff --git a/gcc/ada/libgnat/s-widthu.adb b/gcc/ada/libgnat/s-widthu.adb index a91baec..e0e4d17 100644 --- a/gcc/ada/libgnat/s-widthu.adb +++ b/gcc/ada/libgnat/s-widthu.adb @@ -29,10 +29,87 @@ -- -- ------------------------------------------------------------------------------ +with Ada.Numerics.Big_Numbers.Big_Integers; +use Ada.Numerics.Big_Numbers.Big_Integers; + function System.Width_U (Lo, Hi : Uns) return Natural is + + -- Ghost code, loop invariants and assertions in this unit are meant for + -- analysis only, not for run-time checking, as it would be too costly + -- otherwise. This is enforced by setting the assertion policy to Ignore. + + pragma Assertion_Policy (Ghost => Ignore, + Loop_Invariant => Ignore, + Assert => Ignore); + W : Natural; T : Uns; + package Unsigned_Conversion is new Unsigned_Conversions (Int => Uns); + + function Big (Arg : Uns) return Big_Integer is + (Unsigned_Conversion.To_Big_Integer (Arg)) + with Ghost; + + -- Maximum value of exponent for 10 that fits in Uns'Base + function Max_Log10 return Natural is + (case Uns'Base'Size is + when 8 => 2, + when 16 => 4, + when 32 => 9, + when 64 => 19, + when 128 => 38, + when others => raise Program_Error) + with Ghost; + + Max_W : constant Natural := Max_Log10 with Ghost; + Big_10 : constant Big_Integer := Big (10) with Ghost; + + procedure Lemma_Lower_Mult (A, B, C : Big_Natural) + with + Ghost, + Pre => A <= B, + Post => A * C <= B * C; + + procedure Lemma_Div_Commutation (X, Y : Uns) + with + Ghost, + Pre => Y /= 0, + Post => Big (X) / Big (Y) = Big (X / Y); + + procedure Lemma_Div_Twice (X : Big_Natural; Y, Z : Big_Positive) + with + Ghost, + Post => X / Y / Z = X / (Y * Z); + + procedure Lemma_Lower_Mult (A, B, C : Big_Natural) is + begin + null; + end Lemma_Lower_Mult; + + procedure Lemma_Div_Commutation (X, Y : Uns) is + begin + null; + end Lemma_Div_Commutation; + + procedure Lemma_Div_Twice (X : Big_Natural; Y, Z : Big_Positive) is + XY : constant Big_Natural := X / Y; + YZ : constant Big_Natural := Y * Z; + XYZ : constant Big_Natural := X / Y / Z; + R : constant Big_Natural := (XY rem Z) * Y + (X rem Y); + begin + pragma Assert (X = XY * Y + (X rem Y)); + pragma Assert (XY = XY / Z * Z + (XY rem Z)); + pragma Assert (X = XYZ * YZ + R); + pragma Assert ((XY rem Z) * Y <= (Z - 1) * Y); + pragma Assert (R <= YZ - 1); + pragma Assert (X / YZ = (XYZ * YZ + R) / YZ); + pragma Assert (X / YZ = XYZ + R / YZ); + end Lemma_Div_Twice; + + Pow : Big_Integer := 1 with Ghost; + T_Init : constant Uns := Uns'Max (Lo, Hi) with Ghost; + begin if Lo > Hi then return 0; @@ -50,10 +127,40 @@ begin -- Increase value if more digits required while T >= 10 loop + Lemma_Div_Commutation (T, 10); + Lemma_Div_Twice (Big (T_Init), Big_10 ** (W - 2), Big_10); + T := T / 10; W := W + 1; + Pow := Pow * 10; + + pragma Loop_Variant (Decreases => T); + pragma Loop_Invariant (W in 3 .. Max_W + 3); + pragma Loop_Invariant (Pow = Big_10 ** (W - 2)); + pragma Loop_Invariant (Big (T) = Big (T_Init) / Pow); end loop; + declare + F : constant Big_Integer := Big_10 ** (W - 2) with Ghost; + Q : constant Big_Integer := Big (T_Init) / F with Ghost; + R : constant Big_Integer := Big (T_Init) rem F with Ghost; + begin + pragma Assert (Q < Big_10); + pragma Assert (Big (T_Init) = Q * F + R); + Lemma_Lower_Mult (Q, Big (9), F); + pragma Assert (Big (T_Init) <= Big (9) * F + F - 1); + pragma Assert (Big (T_Init) < Big_10 * F); + pragma Assert (Big_10 * F = Big_10 ** (W - 1)); + end; + + -- This is an expression of the functional postcondition for Width_U, + -- which cannot be expressed readily as a postcondition as this would + -- require making the instantiation Unsigned_Conversion and function + -- Big available from the spec. + + pragma Assert (Big (Lo) < Big_10 ** (W - 1)); + pragma Assert (Big (Hi) < Big_10 ** (W - 1)); + return W; end if; diff --git a/gcc/ada/libgnat/s-widuns.ads b/gcc/ada/libgnat/s-widuns.ads index 0528456..713532e 100644 --- a/gcc/ada/libgnat/s-widuns.ads +++ b/gcc/ada/libgnat/s-widuns.ads @@ -34,8 +34,9 @@ with System.Width_U; with System.Unsigned_Types; -package System.Wid_Uns is - +package System.Wid_Uns + with SPARK_Mode +is subtype Unsigned is Unsigned_Types.Unsigned; function Width_Unsigned is new Width_U (Unsigned); diff --git a/gcc/ada/libgnat/system-vxworks-ppc-ravenscar.ads b/gcc/ada/libgnat/system-vxworks-ppc-ravenscar.ads deleted file mode 100644 index b918c18..0000000 --- a/gcc/ada/libgnat/system-vxworks-ppc-ravenscar.ads +++ /dev/null @@ -1,185 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- S Y S T E M -- --- -- --- S p e c -- --- (VxWorks/HIE Ravenscar Version PPC) -- --- -- --- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- --- -- --- This specification is derived from the Ada Reference Manual for use with -- --- GNAT. The copyright notice above, and the license provisions that follow -- --- apply solely to the contents of the part following the private keyword. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- This is a Ravenscar VxWorks version of this package for PowerPC targets - -pragma Restrictions (No_Exception_Propagation); --- Only local exception handling is supported in this profile - -pragma Restrictions (No_Exception_Registration); --- Disable exception name registration. This capability is not used because --- it is only required by exception stream attributes which are not supported --- in this run time. - -pragma Restrictions (No_Implicit_Dynamic_Code); --- Pointers to nested subprograms are not allowed in this run time, in order --- to prevent the compiler from building "trampolines". - -pragma Restrictions (No_Finalization); --- Controlled types are not supported in this run time - -pragma Profile (Ravenscar); --- This is a Ravenscar run time - -pragma Discard_Names; --- Disable explicitly the generation of names associated with entities in --- order to reduce the amount of storage used. These names are not used anyway --- (attributes such as 'Image and 'Value are not supported in this run time). - -package System is - pragma Pure; - -- Note that we take advantage of the implementation permission to make - -- this unit Pure instead of Preelaborable; see RM 13.7.1(15). In Ada - -- 2005, this is Pure in any case (AI-362). - - pragma No_Elaboration_Code_All; - -- Allow the use of that restriction in units that WITH this unit - - type Name is (SYSTEM_NAME_GNAT); - System_Name : constant Name := SYSTEM_NAME_GNAT; - - -- System-Dependent Named Numbers - - Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1); - Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1; - - Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size; - Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1; - - Max_Base_Digits : constant := Long_Long_Float'Digits; - Max_Digits : constant := Long_Long_Float'Digits; - - Max_Mantissa : constant := Standard'Max_Integer_Size - 1; - Fine_Delta : constant := 2.0 ** (-Max_Mantissa); - - Tick : constant := 1.0 / 60.0; - - -- Storage-related Declarations - - type Address is private; - pragma Preelaborable_Initialization (Address); - Null_Address : constant Address; - - Storage_Unit : constant := 8; - Word_Size : constant := 32; - Memory_Size : constant := 2 ** 32; - - -- Address comparison - - function "<" (Left, Right : Address) return Boolean; - function "<=" (Left, Right : Address) return Boolean; - function ">" (Left, Right : Address) return Boolean; - function ">=" (Left, Right : Address) return Boolean; - function "=" (Left, Right : Address) return Boolean; - - pragma Import (Intrinsic, "<"); - pragma Import (Intrinsic, "<="); - pragma Import (Intrinsic, ">"); - pragma Import (Intrinsic, ">="); - pragma Import (Intrinsic, "="); - - -- Other System-Dependent Declarations - - type Bit_Order is (High_Order_First, Low_Order_First); - Default_Bit_Order : constant Bit_Order := High_Order_First; - pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning - - -- Priority-related Declarations (RM D.1) - - -- Ada priorities are mapped to VxWorks priorities using the following - -- transformation: 255 - Ada Priority - - -- Ada priorities are used as follows: - - -- 256 is reserved for the VxWorks kernel - -- 248 - 255 correspond to hardware interrupt levels 0 .. 7 - -- 247 is a catchall default "interrupt" priority for signals, - -- allowing higher priority than normal tasks, but lower than - -- hardware priority levels. Protected Object ceilings can - -- override these values. - -- 246 is used by the Interrupt_Manager task - - Max_Priority : constant Positive := 245; - Max_Interrupt_Priority : constant Positive := 255; - - subtype Any_Priority is Integer range 0 .. 255; - subtype Priority is Any_Priority range 0 .. 245; - subtype Interrupt_Priority is Any_Priority range 246 .. 255; - - Default_Priority : constant Priority := 122; - -private - - type Address is mod Memory_Size; - Null_Address : constant Address := 0; - - -------------------------------------- - -- System Implementation Parameters -- - -------------------------------------- - - -- These parameters provide information about the target that is used - -- by the compiler. They are in the private part of System, where they - -- can be accessed using the special circuitry in the Targparm unit - -- whose source should be consulted for more detailed descriptions - -- of the individual switch values. - - Backend_Divide_Checks : constant Boolean := False; - Backend_Overflow_Checks : constant Boolean := True; - Command_Line_Args : constant Boolean := False; - Configurable_Run_Time : constant Boolean := True; - Denorm : constant Boolean := True; - Duration_32_Bits : constant Boolean := True; - Exit_Status_Supported : constant Boolean := True; - Machine_Overflows : constant Boolean := True; - Machine_Rounds : constant Boolean := True; - Preallocated_Stacks : constant Boolean := False; - Signed_Zeros : constant Boolean := True; - Stack_Check_Default : constant Boolean := False; - Stack_Check_Probes : constant Boolean := False; - Stack_Check_Limits : constant Boolean := True; - Support_Aggregates : constant Boolean := True; - Support_Composite_Assign : constant Boolean := True; - Support_Composite_Compare : constant Boolean := True; - Support_Long_Shifts : constant Boolean := True; - Always_Compatible_Rep : constant Boolean := True; - Suppress_Standard_Library : constant Boolean := True; - Use_Ada_Main_Program_Name : constant Boolean := True; - Frontend_Exceptions : constant Boolean := True; - ZCX_By_Default : constant Boolean := False; - - Executable_Extension : constant String := ".out"; - -end System; diff --git a/gcc/ada/libgnat/system-vxworks-ppc.ads b/gcc/ada/libgnat/system-vxworks-ppc.ads deleted file mode 100644 index 8f384e9..0000000 --- a/gcc/ada/libgnat/system-vxworks-ppc.ads +++ /dev/null @@ -1,163 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- S Y S T E M -- --- -- --- S p e c -- --- (VxWorks 5 Version PPC) -- --- -- --- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- --- -- --- This specification is derived from the Ada Reference Manual for use with -- --- GNAT. The copyright notice above, and the license provisions that follow -- --- apply solely to the contents of the part following the private keyword. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package System is - pragma Pure; - -- Note that we take advantage of the implementation permission to make - -- this unit Pure instead of Preelaborable; see RM 13.7.1(15). In Ada - -- 2005, this is Pure in any case (AI-362). - - pragma No_Elaboration_Code_All; - -- Allow the use of that restriction in units that WITH this unit - - type Name is (SYSTEM_NAME_GNAT); - System_Name : constant Name := SYSTEM_NAME_GNAT; - - -- System-Dependent Named Numbers - - Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1); - Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1; - - Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size; - Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1; - - Max_Base_Digits : constant := Long_Long_Float'Digits; - Max_Digits : constant := Long_Long_Float'Digits; - - Max_Mantissa : constant := Standard'Max_Integer_Size - 1; - Fine_Delta : constant := 2.0 ** (-Max_Mantissa); - - Tick : constant := 1.0 / 60.0; - - -- Storage-related Declarations - - type Address is private; - pragma Preelaborable_Initialization (Address); - Null_Address : constant Address; - - Storage_Unit : constant := 8; - Word_Size : constant := 32; - Memory_Size : constant := 2 ** 32; - - -- Address comparison - - function "<" (Left, Right : Address) return Boolean; - function "<=" (Left, Right : Address) return Boolean; - function ">" (Left, Right : Address) return Boolean; - function ">=" (Left, Right : Address) return Boolean; - function "=" (Left, Right : Address) return Boolean; - - pragma Import (Intrinsic, "<"); - pragma Import (Intrinsic, "<="); - pragma Import (Intrinsic, ">"); - pragma Import (Intrinsic, ">="); - pragma Import (Intrinsic, "="); - - -- Other System-Dependent Declarations - - type Bit_Order is (High_Order_First, Low_Order_First); - Default_Bit_Order : constant Bit_Order := High_Order_First; - pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning - - -- Priority-related Declarations (RM D.1) - - -- Ada priorities are mapped to VxWorks priorities using the following - -- transformation: 255 - Ada Priority - - -- Ada priorities are used as follows: - - -- 256 is reserved for the VxWorks kernel - -- 248 - 255 correspond to hardware interrupt levels 0 .. 7 - -- 247 is a catchall default "interrupt" priority for signals, - -- allowing higher priority than normal tasks, but lower than - -- hardware priority levels. Protected Object ceilings can - -- override these values. - -- 246 is used by the Interrupt_Manager task - - Max_Priority : constant Positive := 245; - Max_Interrupt_Priority : constant Positive := 255; - - subtype Any_Priority is Integer range 0 .. 255; - subtype Priority is Any_Priority range 0 .. 245; - subtype Interrupt_Priority is Any_Priority range 246 .. 255; - - Default_Priority : constant Priority := 122; - -private - - pragma Linker_Options ("--specs=vxworks-ppc-link.spec"); - -- Setup proper set of -L's for this configuration - - type Address is mod Memory_Size; - Null_Address : constant Address := 0; - - -------------------------------------- - -- System Implementation Parameters -- - -------------------------------------- - - -- These parameters provide information about the target that is used - -- by the compiler. They are in the private part of System, where they - -- can be accessed using the special circuitry in the Targparm unit - -- whose source should be consulted for more detailed descriptions - -- of the individual switch values. - - Backend_Divide_Checks : constant Boolean := False; - Backend_Overflow_Checks : constant Boolean := True; - Command_Line_Args : constant Boolean := False; - Configurable_Run_Time : constant Boolean := False; - Denorm : constant Boolean := True; - Duration_32_Bits : constant Boolean := False; - Exit_Status_Supported : constant Boolean := True; - Machine_Overflows : constant Boolean := False; - Machine_Rounds : constant Boolean := True; - Preallocated_Stacks : constant Boolean := False; - Signed_Zeros : constant Boolean := True; - Stack_Check_Default : constant Boolean := False; - Stack_Check_Probes : constant Boolean := False; - Stack_Check_Limits : constant Boolean := True; - Support_Aggregates : constant Boolean := True; - Support_Composite_Assign : constant Boolean := True; - Support_Composite_Compare : constant Boolean := True; - Support_Long_Shifts : constant Boolean := True; - Always_Compatible_Rep : constant Boolean := False; - Suppress_Standard_Library : constant Boolean := False; - Use_Ada_Main_Program_Name : constant Boolean := True; - Frontend_Exceptions : constant Boolean := True; - ZCX_By_Default : constant Boolean := False; - - Executable_Extension : constant String := ".out"; - -end System; diff --git a/gcc/ada/libgnat/system-vxworks-x86.ads b/gcc/ada/libgnat/system-vxworks-x86.ads deleted file mode 100644 index 6f952a2..0000000 --- a/gcc/ada/libgnat/system-vxworks-x86.ads +++ /dev/null @@ -1,164 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- S Y S T E M -- --- -- --- S p e c -- --- (VxWorks 5 Version x86) -- --- -- --- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- --- -- --- This specification is derived from the Ada Reference Manual for use with -- --- GNAT. The copyright notice above, and the license provisions that follow -- --- apply solely to the contents of the part following the private keyword. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package System is - pragma Pure; - -- Note that we take advantage of the implementation permission to make - -- this unit Pure instead of Preelaborable; see RM 13.7.1(15). In Ada - -- 2005, this is Pure in any case (AI-362). - - pragma No_Elaboration_Code_All; - -- Allow the use of that restriction in units that WITH this unit - - type Name is (SYSTEM_NAME_GNAT); - System_Name : constant Name := SYSTEM_NAME_GNAT; - - -- System-Dependent Named Numbers - - Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1); - Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1; - - Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size; - Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1; - - Max_Base_Digits : constant := Long_Long_Float'Digits; - Max_Digits : constant := Long_Long_Float'Digits; - - Max_Mantissa : constant := Standard'Max_Integer_Size - 1; - Fine_Delta : constant := 2.0 ** (-Max_Mantissa); - - Tick : constant := 1.0 / 60.0; - - -- Storage-related Declarations - - type Address is private; - pragma Preelaborable_Initialization (Address); - Null_Address : constant Address; - - Storage_Unit : constant := 8; - Word_Size : constant := 32; - Memory_Size : constant := 2 ** 32; - - -- Address comparison - - function "<" (Left, Right : Address) return Boolean; - function "<=" (Left, Right : Address) return Boolean; - function ">" (Left, Right : Address) return Boolean; - function ">=" (Left, Right : Address) return Boolean; - function "=" (Left, Right : Address) return Boolean; - - pragma Import (Intrinsic, "<"); - pragma Import (Intrinsic, "<="); - pragma Import (Intrinsic, ">"); - pragma Import (Intrinsic, ">="); - pragma Import (Intrinsic, "="); - - -- Other System-Dependent Declarations - - type Bit_Order is (High_Order_First, Low_Order_First); - Default_Bit_Order : constant Bit_Order := Low_Order_First; - pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning - - -- Priority-related Declarations (RM D.1) - - -- Ada priorities are mapped to VxWorks priorities using the following - -- transformation: 255 - Ada Priority - - -- Ada priorities are used as follows: - - -- 256 is reserved for the VxWorks kernel - -- 248 - 255 correspond to hardware interrupt levels 0 .. 7 - -- 247 is a catchall default "interrupt" priority for signals, - -- allowing higher priority than normal tasks, but lower than - -- hardware priority levels. Protected Object ceilings can - -- override these values. - -- 246 is used by the Interrupt_Manager task - - Max_Priority : constant Positive := 245; - Max_Interrupt_Priority : constant Positive := 255; - - subtype Any_Priority is Integer range 0 .. 255; - subtype Priority is Any_Priority range 0 .. 245; - subtype Interrupt_Priority is Any_Priority range 246 .. 255; - - Default_Priority : constant Priority := 122; - -private - - pragma Linker_Options ("--specs=vxworks-x86-link.spec"); - -- Setup proper set of -L's for this configuration - - type Address is mod Memory_Size; - Null_Address : constant Address := 0; - - -------------------------------------- - -- System Implementation Parameters -- - -------------------------------------- - - -- These parameters provide information about the target that is used - -- by the compiler. They are in the private part of System, where they - -- can be accessed using the special circuitry in the Targparm unit - -- whose source should be consulted for more detailed descriptions - -- of the individual switch values. - - Backend_Divide_Checks : constant Boolean := False; - Backend_Overflow_Checks : constant Boolean := True; - Command_Line_Args : constant Boolean := False; - Configurable_Run_Time : constant Boolean := False; - Denorm : constant Boolean := True; - Duration_32_Bits : constant Boolean := False; - Exit_Status_Supported : constant Boolean := True; - Machine_Overflows : constant Boolean := False; - Machine_Rounds : constant Boolean := True; - Preallocated_Stacks : constant Boolean := False; - Signed_Zeros : constant Boolean := True; - Stack_Check_Default : constant Boolean := False; - Stack_Check_Probes : constant Boolean := False; - Stack_Check_Limits : constant Boolean := True; - Support_Aggregates : constant Boolean := True; - Support_Atomic_Primitives : constant Boolean := True; - Support_Composite_Assign : constant Boolean := True; - Support_Composite_Compare : constant Boolean := True; - Support_Long_Shifts : constant Boolean := True; - Always_Compatible_Rep : constant Boolean := False; - Suppress_Standard_Library : constant Boolean := False; - Use_Ada_Main_Program_Name : constant Boolean := True; - Frontend_Exceptions : constant Boolean := True; - ZCX_By_Default : constant Boolean := False; - - Executable_Extension : constant String := ".out"; - -end System; diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index 084ca91..83d9681 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -367,46 +367,48 @@ package body Repinfo is null; else - -- If Esize and RM_Size are the same, list as Size. This is a common - -- case, which we may as well list in simple form. + if Known_Esize (Ent) and then Known_RM_Size (Ent) then + -- If Esize and RM_Size are the same, list as Size. This is a + -- common case, which we may as well list in simple form. - if Esize (Ent) = RM_Size (Ent) then - if List_Representation_Info_To_JSON then - Write_Str (" ""Size"": "); - Write_Val (Esize (Ent)); - Write_Line (","); - else - Write_Str ("for "); - List_Name (Ent); - Write_Str ("'Size use "); - Write_Val (Esize (Ent)); - Write_Line (";"); - end if; + if Esize (Ent) = RM_Size (Ent) then + if List_Representation_Info_To_JSON then + Write_Str (" ""Size"": "); + Write_Val (Esize (Ent)); + Write_Line (","); + else + Write_Str ("for "); + List_Name (Ent); + Write_Str ("'Size use "); + Write_Val (Esize (Ent)); + Write_Line (";"); + end if; - -- Otherwise list size values separately + -- Otherwise list size values separately - else - if List_Representation_Info_To_JSON then - Write_Str (" ""Object_Size"": "); - Write_Val (Esize (Ent)); - Write_Line (","); + else + if List_Representation_Info_To_JSON then + Write_Str (" ""Object_Size"": "); + Write_Val (Esize (Ent)); + Write_Line (","); - Write_Str (" ""Value_Size"": "); - Write_Val (RM_Size (Ent)); - Write_Line (","); + Write_Str (" ""Value_Size"": "); + Write_Val (RM_Size (Ent)); + Write_Line (","); - else - Write_Str ("for "); - List_Name (Ent); - Write_Str ("'Object_Size use "); - Write_Val (Esize (Ent)); - Write_Line (";"); - - Write_Str ("for "); - List_Name (Ent); - Write_Str ("'Value_Size use "); - Write_Val (RM_Size (Ent)); - Write_Line (";"); + else + Write_Str ("for "); + List_Name (Ent); + Write_Str ("'Object_Size use "); + Write_Val (Esize (Ent)); + Write_Line (";"); + + Write_Str ("for "); + List_Name (Ent); + Write_Str ("'Value_Size use "); + Write_Val (RM_Size (Ent)); + Write_Line (";"); + end if; end if; end if; end if; diff --git a/gcc/ada/sem.adb b/gcc/ada/sem.adb index 3eee2ee..ee5c7cf 100644 --- a/gcc/ada/sem.adb +++ b/gcc/ada/sem.adb @@ -1022,16 +1022,20 @@ package body Sem is Scop : Entity_Id; begin - -- Entity is global if defined outside of current outer_generic_scope: - -- Either the entity has a smaller depth that the outer generic, or it + -- Entity is global if defined outside of current Outer_Generic_Scope: + -- Either the entity has a smaller depth than the outer generic, or it -- is in a different compilation unit, or it is defined within a unit - -- in the same compilation, that is not within the outer_generic. + -- in the same compilation, that is not within the outer generic. if No (Outer_Generic_Scope) then return False; - elsif Scope_Depth (Scope (E)) < Scope_Depth (Outer_Generic_Scope) - or else not In_Same_Source_Unit (E, Outer_Generic_Scope) + -- It makes no sense to compare depths if not in same unit. Scope_Depth + -- is not set for inherited operations. + + elsif not In_Same_Source_Unit (E, Outer_Generic_Scope) + or else not Scope_Depth_Set (Scope (E)) + or else Scope_Depth (Scope (E)) < Scope_Depth (Outer_Generic_Scope) then return True; diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb index 527342f..42fb610 100644 --- a/gcc/ada/sem_aggr.adb +++ b/gcc/ada/sem_aggr.adb @@ -3384,9 +3384,8 @@ package body Sem_Aggr is function Nested_In (V1 : Node_Id; V2 : Node_Id) return Boolean; -- Determine whether variant V1 is within variant V2 - function Variant_Depth (N : Node_Id) return Integer; - -- Determine the distance of a variant to the enclosing type - -- declaration. + function Variant_Depth (N : Node_Id) return Natural; + -- Determine the distance of a variant to the enclosing type declaration -------------------- -- Check_Variant -- @@ -3492,8 +3491,8 @@ package body Sem_Aggr is -- Variant_Depth -- ------------------- - function Variant_Depth (N : Node_Id) return Integer is - Depth : Integer; + function Variant_Depth (N : Node_Id) return Natural is + Depth : Natural; Par : Node_Id; begin @@ -3546,7 +3545,19 @@ package body Sem_Aggr is end loop; pragma Assert (Present (Comp_Type)); - Analyze_And_Resolve (Expression (Assoc), Comp_Type); + + -- A record_component_association in record_delta_aggregate shall not + -- use the box compound delimiter <> rather than an expression; see + -- RM 4.3.1(17.3/5). + + pragma Assert (Present (Expression (Assoc)) xor Box_Present (Assoc)); + + if Box_Present (Assoc) then + Error_Msg_N + ("'<'> in record delta aggregate is not allowed", Assoc); + else + Analyze_And_Resolve (Expression (Assoc), Comp_Type); + end if; Next (Assoc); end loop; end Resolve_Delta_Record_Aggregate; diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb index 32c5d37..f2bb12d 100644 --- a/gcc/ada/sem_attr.adb +++ b/gcc/ada/sem_attr.adb @@ -9251,14 +9251,12 @@ package body Sem_Attr is -- Machine -- ------------- - -- We use the same rounding mode as the one used for RM 4.9(38) + -- We use the same rounding as the one used for RM 4.9(38/2) when Attribute_Machine => Fold_Ureal - (N, - Eval_Fat.Machine - (P_Base_Type, Expr_Value_R (E1), Eval_Fat.Round_Even, N), - Static); + (N, Machine_Number (P_Base_Type, Expr_Value_R (E1), N), Static); + Set_Is_Machine_Number (N); ------------------ -- Machine_Emax -- diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index e4cb7e3..a62eb7c 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -5802,6 +5802,7 @@ package body Sem_Ch12 is if Is_Intrinsic_Subprogram (Gen_Unit) then Set_Is_Intrinsic_Subprogram (Anon_Id); + Set_Interface_Name (Anon_Id, Interface_Name (Gen_Unit)); end if; Analyze_Instance_And_Renamings; @@ -5818,14 +5819,13 @@ package body Sem_Ch12 is end if; -- If the generic is marked Import (Intrinsic), then so is the - -- instance. This indicates that there is no body to instantiate. If - -- generic is marked inline, so it the instance, and the anonymous - -- subprogram it renames. If inlined, or else if inlining is enabled - -- for the compilation, we generate the instance body even if it is - -- not within the main unit. + -- instance; this indicates that there is no body to instantiate. + -- We also copy the interface name in case this is handled by the + -- back-end and deal with an instance of unchecked conversion. if Is_Intrinsic_Subprogram (Gen_Unit) then Set_Is_Intrinsic_Subprogram (Act_Decl_Id); + Set_Interface_Name (Act_Decl_Id, Interface_Name (Gen_Unit)); if Chars (Gen_Unit) = Name_Unchecked_Conversion then Validate_Unchecked_Conversion (N, Act_Decl_Id); @@ -8090,7 +8090,9 @@ package body Sem_Ch12 is (Scope (Ent) = Current_Instantiated_Parent.Gen_Id and then not Is_Child_Unit (Ent)) or else - (Scope_Depth (Scope (Ent)) > + (Scope_Depth_Set (Scope (Ent)) + and then + Scope_Depth (Scope (Ent)) > Scope_Depth (Current_Instantiated_Parent.Gen_Id) and then Get_Source_Unit (Ent) = diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index c60dd97..3374e8b 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -7960,7 +7960,7 @@ package body Sem_Ch13 is ("stream size for elementary type must be 8, 16, 24, " & "32 or 64", N); - elsif RM_Size (U_Ent) > Size then + elsif Known_RM_Size (U_Ent) and then RM_Size (U_Ent) > Size then Error_Msg_Uint_1 := RM_Size (U_Ent); Error_Msg_N ("stream size for elementary type must be 8, 16, 24, " & @@ -17569,7 +17569,9 @@ package body Sem_Ch13 is Source_Siz := RM_Size (Source); Target_Siz := RM_Size (Target); - if Source_Siz /= Target_Siz then + if Present (Source_Siz) and then Present (Target_Siz) + and then Source_Siz /= Target_Siz + then Error_Msg ("?z?types for unchecked conversion have different sizes!", Eloc, Act_Unit); diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 57db637..c8d4ec1 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -6343,7 +6343,7 @@ package body Sem_Ch3 is -- Complete setup of implicit base type - Set_Component_Size (Implicit_Base, Uint_0); + pragma Assert (not Known_Component_Size (Implicit_Base)); Set_Component_Type (Implicit_Base, Element_Type); Set_Finalize_Storage_Only (Implicit_Base, @@ -6372,7 +6372,7 @@ package body Sem_Ch3 is Reinit_Size_Align (T); Set_Etype (T, T); Set_Scope (T, Current_Scope); - Set_Component_Size (T, Uint_0); + pragma Assert (not Known_Component_Size (T)); Set_Is_Constrained (T, False); Set_Is_Fixed_Lower_Bound_Array_Subtype (T, Has_FLB_Index); @@ -17585,7 +17585,7 @@ package body Sem_Ch3 is Set_High_Bound (R_Node, B_Node); -- Initialize various fields of the type. Some of this information - -- may be overwritten later through rep.clauses. + -- may be overwritten later through rep. clauses. Set_Scalar_Range (T, R_Node); Set_RM_Size (T, UI_From_Int (Minimum_Size (T))); @@ -18517,7 +18517,12 @@ package body Sem_Ch3 is Set_Size_Info (T, Implicit_Base); Set_RM_Size (T, RM_Size (Implicit_Base)); Inherit_Rep_Item_Chain (T, Implicit_Base); - Set_Digits_Value (T, Digs_Val); + + if Digs_Val >= Uint_1 then + Set_Digits_Value (T, Digs_Val); + else + pragma Assert (Serious_Errors_Detected > 0); null; + end if; end Floating_Point_Type_Declaration; ---------------------------- @@ -19641,8 +19646,8 @@ package body Sem_Ch3 is return; end if; - -- If the range bounds are "T'Low .. T'High" where T is a name of - -- a discrete type, then use T as the type of the index. + -- If the range bounds are "T'First .. T'Last" where T is a name of a + -- discrete type, then use T as the type of the index. if Nkind (Low_Bound (N)) = N_Attribute_Reference and then Attribute_Name (Low_Bound (N)) = Name_First @@ -21747,141 +21752,130 @@ package body Sem_Ch3 is -- represent the null range the Constraint_Error exception should -- not be raised. - -- ??? The Is_Null_Range (Lo, Hi) test should disappear since it - -- is done in the call to Range_Check (R, T); below. + -- Capture values of bounds and generate temporaries for them + -- if needed, before applying checks, since checks may cause + -- duplication of the expression without forcing evaluation. - if Is_Null_Range (Lo, Hi) then - null; + -- The forced evaluation removes side effects from expressions, + -- which should occur also in GNATprove mode. Otherwise, we end up + -- with unexpected insertions of actions at places where this is + -- not supposed to occur, e.g. on default parameters of a call. - else - -- Capture values of bounds and generate temporaries for them - -- if needed, before applying checks, since checks may cause - -- duplication of the expression without forcing evaluation. - - -- The forced evaluation removes side effects from expressions, - -- which should occur also in GNATprove mode. Otherwise, we end up - -- with unexpected insertions of actions at places where this is - -- not supposed to occur, e.g. on default parameters of a call. - - if Expander_Active or GNATprove_Mode then - - -- Call Force_Evaluation to create declarations as needed - -- to deal with side effects, and also create typ_FIRST/LAST - -- entities for bounds if we have a subtype name. - - -- Note: we do this transformation even if expansion is not - -- active if we are in GNATprove_Mode since the transformation - -- is in general required to ensure that the resulting tree has - -- proper Ada semantics. - - Force_Evaluation - (Lo, Related_Id => Subtyp, Is_Low_Bound => True); - Force_Evaluation - (Hi, Related_Id => Subtyp, Is_High_Bound => True); - end if; + if Expander_Active or GNATprove_Mode then - -- We use a flag here instead of suppressing checks on the type - -- because the type we check against isn't necessarily the place - -- where we put the check. + -- Call Force_Evaluation to create declarations as needed + -- to deal with side effects, and also create typ_FIRST/LAST + -- entities for bounds if we have a subtype name. - R_Checks := Get_Range_Checks (R, T); + -- Note: we do this transformation even if expansion is not + -- active if we are in GNATprove_Mode since the transformation + -- is in general required to ensure that the resulting tree has + -- proper Ada semantics. - -- Look up tree to find an appropriate insertion point. We can't - -- just use insert_actions because later processing depends on - -- the insertion node. Prior to Ada 2012 the insertion point could - -- only be a declaration or a loop, but quantified expressions can - -- appear within any context in an expression, and the insertion - -- point can be any statement, pragma, or declaration. + Force_Evaluation + (Lo, Related_Id => Subtyp, Is_Low_Bound => True); + Force_Evaluation + (Hi, Related_Id => Subtyp, Is_High_Bound => True); + end if; - Insert_Node := Parent (R); - while Present (Insert_Node) loop - exit when - Nkind (Insert_Node) in N_Declaration - and then - Nkind (Insert_Node) not in N_Component_Declaration - | N_Loop_Parameter_Specification - | N_Function_Specification - | N_Procedure_Specification; - - exit when Nkind (Insert_Node) in - N_Later_Decl_Item | - N_Statement_Other_Than_Procedure_Call | - N_Procedure_Call_Statement | - N_Pragma; - - Insert_Node := Parent (Insert_Node); - end loop; + -- We use a flag here instead of suppressing checks on the type + -- because the type we check against isn't necessarily the place + -- where we put the check. - -- Why would Type_Decl not be present??? Without this test, - -- short regression tests fail. + R_Checks := Get_Range_Checks (R, T); - if Present (Insert_Node) then + -- Look up tree to find an appropriate insertion point. We can't + -- just use insert_actions because later processing depends on + -- the insertion node. Prior to Ada 2012 the insertion point could + -- only be a declaration or a loop, but quantified expressions can + -- appear within any context in an expression, and the insertion + -- point can be any statement, pragma, or declaration. - -- Case of loop statement. Verify that the range is part of the - -- subtype indication of the iteration scheme. + Insert_Node := Parent (R); + while Present (Insert_Node) loop + exit when + Nkind (Insert_Node) in N_Declaration + and then + Nkind (Insert_Node) not in N_Component_Declaration + | N_Loop_Parameter_Specification + | N_Function_Specification + | N_Procedure_Specification; + + exit when Nkind (Insert_Node) in + N_Later_Decl_Item | + N_Statement_Other_Than_Procedure_Call | + N_Procedure_Call_Statement | + N_Pragma; + + Insert_Node := Parent (Insert_Node); + end loop; - if Nkind (Insert_Node) = N_Loop_Statement then - declare - Indic : Node_Id; + if Present (Insert_Node) then - begin - Indic := Parent (R); - while Present (Indic) - and then Nkind (Indic) /= N_Subtype_Indication - loop - Indic := Parent (Indic); - end loop; + -- Case of loop statement. Verify that the range is part of the + -- subtype indication of the iteration scheme. - if Present (Indic) then - Def_Id := Etype (Subtype_Mark (Indic)); + if Nkind (Insert_Node) = N_Loop_Statement then + declare + Indic : Node_Id; - Insert_Range_Checks - (R_Checks, - Insert_Node, - Def_Id, - Sloc (Insert_Node), - Do_Before => True); - end if; - end; + begin + Indic := Parent (R); + while Present (Indic) + and then Nkind (Indic) /= N_Subtype_Indication + loop + Indic := Parent (Indic); + end loop; - -- Case of declarations. If the declaration is for a type and - -- involves discriminants, the checks are premature at the - -- declaration point and need to wait for the expansion of the - -- initialization procedure, which will pass in the list to put - -- them on; otherwise, the checks are done at the declaration - -- point and there is no need to do them again in the - -- initialization procedure. + if Present (Indic) then + Def_Id := Etype (Subtype_Mark (Indic)); - elsif Nkind (Insert_Node) in N_Declaration then - Def_Id := Defining_Identifier (Insert_Node); + Insert_Range_Checks + (R_Checks, + Insert_Node, + Def_Id, + Sloc (Insert_Node), + Do_Before => True); + end if; + end; - if (Ekind (Def_Id) = E_Record_Type - and then Depends_On_Discriminant (R)) - or else - (Ekind (Def_Id) = E_Protected_Type - and then Has_Discriminants (Def_Id)) - then - if Present (Check_List) then - Append_Range_Checks - (R_Checks, - Check_List, Def_Id, Sloc (Insert_Node)); - end if; + -- Case of declarations. If the declaration is for a type and + -- involves discriminants, the checks are premature at the + -- declaration point and need to wait for the expansion of the + -- initialization procedure, which will pass in the list to put + -- them on; otherwise, the checks are done at the declaration + -- point and there is no need to do them again in the + -- initialization procedure. - else - if No (Check_List) then - Insert_Range_Checks - (R_Checks, - Insert_Node, Def_Id, Sloc (Insert_Node)); - end if; - end if; + elsif Nkind (Insert_Node) in N_Declaration then + Def_Id := Defining_Identifier (Insert_Node); - -- Case of statements. Drop the checks, as the range appears in - -- the context of a quantified expression. Insertion will take - -- place when expression is expanded. + if (Ekind (Def_Id) = E_Record_Type + and then Depends_On_Discriminant (R)) + or else + (Ekind (Def_Id) = E_Protected_Type + and then Has_Discriminants (Def_Id)) + then + if Present (Check_List) then + Append_Range_Checks + (R_Checks, + Check_List, Def_Id, Sloc (Insert_Node)); + end if; else - null; + if No (Check_List) then + Insert_Range_Checks + (R_Checks, + Insert_Node, Def_Id, Sloc (Insert_Node)); + end if; end if; + + -- Case of statements. Drop the checks, as the range appears in + -- the context of a quantified expression. Insertion will take + -- place when expression is expanded. + + else + null; end if; end if; diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index 169b01b..fecc060a 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -4299,21 +4299,67 @@ package body Sem_Ch4 is Loop_Id := Defining_Identifier (Loop_Parameter_Specification (N)); end if; - if Warn_On_Suspicious_Contract - and then not Referenced (Loop_Id, Cond) - and then not Is_Internal_Name (Chars (Loop_Id)) - then - -- Generating C, this check causes spurious warnings on inlined - -- postconditions; we can safely disable it because this check - -- was previously performed when analyzing the internally built - -- postconditions procedure. + declare + type Subexpr_Kind is (Full, Conjunct, Disjunct); - if Modify_Tree_For_C and then In_Inlined_Body then - null; - else - Error_Msg_N ("?T?unused variable &", Loop_Id); + procedure Check_Subexpr (Expr : Node_Id; Kind : Subexpr_Kind); + -- Check that the quantified variable appears in every sub-expression + -- of the quantified expression. If Kind is Full, Expr is the full + -- expression. If Kind is Conjunct (resp. Disjunct), Expr is a + -- conjunct (resp. disjunct) of the full expression. + + ------------------- + -- Check_Subexpr -- + ------------------- + + procedure Check_Subexpr (Expr : Node_Id; Kind : Subexpr_Kind) is + begin + if Nkind (Expr) in N_Op_And | N_And_Then + and then Kind /= Disjunct + then + Check_Subexpr (Left_Opnd (Expr), Conjunct); + Check_Subexpr (Right_Opnd (Expr), Conjunct); + + elsif Nkind (Expr) in N_Op_Or | N_Or_Else + and then Kind /= Conjunct + then + Check_Subexpr (Left_Opnd (Expr), Disjunct); + Check_Subexpr (Right_Opnd (Expr), Disjunct); + + elsif Kind /= Full + and then not Referenced (Loop_Id, Expr) + then + declare + Sub : constant String := + (if Kind = Conjunct then "conjunct" else "disjunct"); + begin + Error_Msg_NE + ("?T?unused variable & in " & Sub, Expr, Loop_Id); + Error_Msg_NE + ("\consider extracting " & Sub & " from quantified " + & "expression", Expr, Loop_Id); + end; + end if; + end Check_Subexpr; + + begin + if Warn_On_Suspicious_Contract + and then not Is_Internal_Name (Chars (Loop_Id)) + + -- Generating C, this check causes spurious warnings on inlined + -- postconditions; we can safely disable it because this check + -- was previously performed when analyzing the internally built + -- postconditions procedure. + + and then not (Modify_Tree_For_C and In_Inlined_Body) + then + if not Referenced (Loop_Id, Cond) then + Error_Msg_N ("?T?unused variable &", Loop_Id); + else + Check_Subexpr (Cond, Kind => Full); + end if; end if; - end if; + end; -- Diagnose a possible misuse of the SOME existential quantifier. When -- we have a quantified expression of the form: diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index e32c4ad..1486918 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -90,6 +90,7 @@ with Tbuild; use Tbuild; with Uintp; use Uintp; with Urealp; use Urealp; with Validsw; use Validsw; +with Warnsw; use Warnsw; package body Sem_Ch6 is @@ -806,6 +807,7 @@ package body Sem_Ch6 is Assoc_Expr : Node_Id; Assoc_Present : Boolean := False; + Check_Cond : Node_Id; Unseen_Disc_Count : Nat := 0; Seen_Discs : Elist_Id; Disc : Entity_Id; @@ -1179,36 +1181,39 @@ package body Sem_Ch6 is and then Present (Disc) and then Ekind (Etype (Disc)) = E_Anonymous_Access_Type then - -- Perform a static check first, if possible + -- Generate a dynamic check based on the extra accessibility of + -- the result or the scope. + + Check_Cond := + Make_Op_Gt (Loc, + Left_Opnd => Accessibility_Level + (Expr => Assoc_Expr, + Level => Dynamic_Level, + In_Return_Context => True), + Right_Opnd => (if Present + (Extra_Accessibility_Of_Result + (Scope_Id)) + then + Extra_Accessibility_Of_Result (Scope_Id) + else + Make_Integer_Literal + (Loc, Scope_Depth (Scope (Scope_Id))))); + + Insert_Before_And_Analyze (Return_Stmt, + Make_Raise_Program_Error (Loc, + Condition => Check_Cond, + Reason => PE_Accessibility_Check_Failed)); + + -- If constant folding has happened on the condition for the + -- generated error, then warn about it being unconditional when + -- we know an error will be raised. - if Static_Accessibility_Level - (Expr => Assoc_Expr, - Level => Zero_On_Dynamic_Level, - In_Return_Context => True) - > Scope_Depth (Scope (Scope_Id)) + if Nkind (Check_Cond) = N_Identifier + and then Entity (Check_Cond) = Standard_True then Error_Msg_N ("access discriminant in return object would be a dangling" & " reference", Return_Stmt); - - exit; - end if; - - -- Otherwise, generate a dynamic check based on the extra - -- accessibility of the result. - - if Present (Extra_Accessibility_Of_Result (Scope_Id)) then - Insert_Before_And_Analyze (Return_Stmt, - Make_Raise_Program_Error (Loc, - Condition => - Make_Op_Gt (Loc, - Left_Opnd => Accessibility_Level - (Expr => Assoc_Expr, - Level => Dynamic_Level, - In_Return_Context => True), - Right_Opnd => Extra_Accessibility_Of_Result - (Scope_Id)), - Reason => PE_Accessibility_Check_Failed)); end if; end if; @@ -5962,6 +5967,17 @@ package body Sem_Ch6 is -- True if the null exclusions of two formals of anonymous access type -- match. + function Subprogram_Subtypes_Have_Same_Declaration + (Subp : Entity_Id; + Decl_Subtype : Entity_Id; + Body_Subtype : Entity_Id) return Boolean; + -- Checks whether corresponding subtypes named within a subprogram + -- declaration and body originate from the same declaration, and returns + -- True when they do. In the case of anonymous access-to-object types, + -- checks the designated types. Also returns True when GNAT_Mode is + -- enabled, or when the subprogram is marked Is_Internal or occurs + -- within a generic instantiation or internal unit (GNAT library unit). + ----------------------- -- Conformance_Error -- ----------------------- @@ -6094,6 +6110,86 @@ package body Sem_Ch6 is end if; end Null_Exclusions_Match; + function Subprogram_Subtypes_Have_Same_Declaration + (Subp : Entity_Id; + Decl_Subtype : Entity_Id; + Body_Subtype : Entity_Id) return Boolean + is + + function Nonlimited_View_Of_Subtype + (Subt : Entity_Id) return Entity_Id; + -- Returns the nonlimited view of a type or subtype that is an + -- incomplete or class-wide type that comes from a limited view of + -- a package (From_Limited_With is True for the entity), or the + -- full view when the subtype is an incomplete type. Otherwise + -- returns the entity passed in. + + function Nonlimited_View_Of_Subtype + (Subt : Entity_Id) return Entity_Id + is + Subt_Temp : Entity_Id := Subt; + begin + if Ekind (Subt) in Incomplete_Kind | E_Class_Wide_Type + and then From_Limited_With (Subt) + then + Subt_Temp := Non_Limited_View (Subt); + end if; + + -- If the subtype is incomplete, return full view if present + -- (and accounts for the case where a type from a limited view + -- is itself an incomplete type). + + if Ekind (Subt_Temp) in Incomplete_Kind + and then Present (Full_View (Subt_Temp)) + then + Subt_Temp := Full_View (Subt_Temp); + end if; + + return Subt_Temp; + end Nonlimited_View_Of_Subtype; + + -- Start of processing for Subprogram_Subtypes_Have_Same_Declaration + + begin + if not In_Instance + and then not In_Internal_Unit (Subp) + and then not Is_Internal (Subp) + and then not GNAT_Mode + and then + Ekind (Etype (Decl_Subtype)) not in Access_Subprogram_Kind + then + if Ekind (Etype (Decl_Subtype)) = E_Anonymous_Access_Type then + if Nonlimited_View_Of_Subtype (Designated_Type (Decl_Subtype)) + /= Nonlimited_View_Of_Subtype (Designated_Type (Body_Subtype)) + then + return False; + end if; + + elsif Nonlimited_View_Of_Subtype (Decl_Subtype) + /= Nonlimited_View_Of_Subtype (Body_Subtype) + then + -- Avoid returning False (and a false-positive warning) for + -- the case of "not null" itypes, which will appear to be + -- different subtypes even when the subtype_marks denote + -- the same subtype. + + if Ekind (Decl_Subtype) = E_Access_Subtype + and then Ekind (Body_Subtype) = E_Access_Subtype + and then Is_Itype (Body_Subtype) + and then Can_Never_Be_Null (Body_Subtype) + and then Etype (Decl_Subtype) = Etype (Body_Subtype) + then + return True; + + else + return False; + end if; + end if; + end if; + + return True; + end Subprogram_Subtypes_Have_Same_Declaration; + -- Local Variables Old_Type : constant Entity_Id := Etype (Old_Id); @@ -6147,6 +6243,18 @@ package body Sem_Ch6 is end if; return; + + -- If the result subtypes conform and pedantic checks are enabled, + -- check to see whether the subtypes originate from different + -- declarations, and issue a warning when they do. + + elsif Ctype = Fully_Conformant + and then Warn_On_Pedantic_Checks + and then not Subprogram_Subtypes_Have_Same_Declaration + (Old_Id, Old_Type, New_Type) + then + Error_Msg_N ("result subtypes conform but come from different " + & "declarations??", New_Id); end if; -- Ada 2005 (AI-231): In case of anonymous access types check the @@ -6343,6 +6451,18 @@ package body Sem_Ch6 is end if; return; + + -- If the formals' subtypes conform and pedantic checks are enabled, + -- check to see whether the subtypes originate from different + -- declarations, and issue a warning when they do. + + elsif Ctype = Fully_Conformant + and then Warn_On_Pedantic_Checks + and then not Subprogram_Subtypes_Have_Same_Declaration + (Old_Id, Old_Formal_Base, New_Formal_Base) + then + Error_Msg_N ("formal subtypes conform but come from " + & "different declarations??", New_Formal); end if; -- For mode conformance, mode must match diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index 494ec64..7b3dfa6 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -7279,8 +7279,10 @@ package body Sem_Ch8 is if Within (It.Nam, Inst) then if Within (Old_S, Inst) then declare - It_D : constant Uint := Scope_Depth (It.Nam); - Old_D : constant Uint := Scope_Depth (Old_S); + It_D : constant Uint := + Scope_Depth_Default_0 (It.Nam); + Old_D : constant Uint := + Scope_Depth_Default_0 (Old_S); N_Ent : Entity_Id; begin -- Choose the innermost subprogram, which @@ -9057,10 +9059,12 @@ package body Sem_Ch8 is Set_Scope_Depth_Value (S, Uint_1); elsif not Is_Record_Type (Current_Scope) then - if Ekind (S) = E_Loop then - Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope)); - else - Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope) + 1); + if Scope_Depth_Set (Current_Scope) then + if Ekind (S) = E_Loop then + Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope)); + else + Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope) + 1); + end if; end if; end if; end if; diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb index 20bc03a..7270172 100644 --- a/gcc/ada/sem_eval.adb +++ b/gcc/ada/sem_eval.adb @@ -523,8 +523,8 @@ package body Sem_Eval is and then Nkind (Parent (N)) in N_Subexpr then Rewrite (N, New_Copy (N)); - Set_Realval - (N, Machine (Base_Type (T), Realval (N), Round_Even, N)); + Set_Realval (N, Machine_Number (Base_Type (T), Realval (N), N)); + Set_Is_Machine_Number (N); end if; end if; @@ -575,18 +575,7 @@ package body Sem_Eval is (N, Corresponding_Integer_Value (N) * Small_Value (T)); elsif not UR_Is_Zero (Realval (N)) then - - -- Note: even though RM 4.9(38) specifies biased rounding, this - -- has been modified by AI-100 in order to prevent confusing - -- differences in rounding between static and non-static - -- expressions. AI-100 specifies that the effect of such rounding - -- is implementation dependent, and in GNAT we round to nearest - -- even to match the run-time behavior. Note that this applies - -- to floating point literals, not fixed points ones, even though - -- their compiler representation is also as a universal real. - - Set_Realval - (N, Machine (Base_Type (T), Realval (N), Round_Even, N)); + Set_Realval (N, Machine_Number (Base_Type (T), Realval (N), N)); Set_Is_Machine_Number (N); end if; @@ -2845,7 +2834,7 @@ package body Sem_Eval is -- the expander that do not correspond to static expressions. procedure Eval_Integer_Literal (N : Node_Id) is - function In_Any_Integer_Context (Context : Node_Id) return Boolean; + function In_Any_Integer_Context (K : Node_Kind) return Boolean; -- If the literal is resolved with a specific type in a context where -- the expected type is Any_Integer, there are no range checks on the -- literal. By the time the literal is evaluated, it carries the type @@ -2856,23 +2845,21 @@ package body Sem_Eval is -- In_Any_Integer_Context -- ---------------------------- - function In_Any_Integer_Context (Context : Node_Id) return Boolean is + function In_Any_Integer_Context (K : Node_Kind) return Boolean is begin -- Any_Integer also appears in digits specifications for real types, -- but those have bounds smaller that those of any integer base type, -- so we can safely ignore these cases. - return - Nkind (Context) in N_Attribute_Definition_Clause - | N_Attribute_Reference - | N_Modular_Type_Definition - | N_Number_Declaration - | N_Signed_Integer_Type_Definition; + return K in N_Attribute_Definition_Clause + | N_Modular_Type_Definition + | N_Number_Declaration + | N_Signed_Integer_Type_Definition; end In_Any_Integer_Context; -- Local variables - Par : constant Node_Id := Parent (N); + PK : constant Node_Kind := Nkind (Parent (N)); Typ : constant Entity_Id := Etype (N); -- Start of processing for Eval_Integer_Literal @@ -2890,12 +2877,11 @@ package body Sem_Eval is -- Check_Non_Static_Context on an expanded literal may lead to spurious -- and misleading warnings. - if (Nkind (Par) in N_Case_Expression_Alternative | N_If_Expression - or else Nkind (Par) not in N_Subexpr) - and then (Nkind (Par) not in N_Case_Expression_Alternative - | N_If_Expression - or else Comes_From_Source (N)) - and then not In_Any_Integer_Context (Par) + if (PK not in N_Subexpr + or else (PK in N_Case_Expression_Alternative | N_If_Expression + and then + Comes_From_Source (N))) + and then not In_Any_Integer_Context (PK) then Check_Non_Static_Context (N); end if; @@ -4366,7 +4352,25 @@ package body Sem_Eval is Fold_Uint (N, Expr_Value (Operand), Stat); end if; - if Is_Out_Of_Range (N, Etype (N), Assume_Valid => True) then + -- If the target is a static floating-point subtype, then its bounds + -- are machine numbers so we must consider the machine-rounded value. + + if Is_Floating_Point_Type (Target_Type) + and then Nkind (N) = N_Real_Literal + and then not Is_Machine_Number (N) + then + declare + Lo : constant Node_Id := Type_Low_Bound (Target_Type); + Hi : constant Node_Id := Type_High_Bound (Target_Type); + Valr : constant Ureal := + Machine_Number (Target_Type, Expr_Value_R (N), N); + begin + if Valr < Expr_Value_R (Lo) or else Valr > Expr_Value_R (Hi) then + Out_Of_Range (N); + end if; + end; + + elsif Is_Out_Of_Range (N, Etype (N), Assume_Valid => True) then Out_Of_Range (N); end if; end Eval_Type_Conversion; @@ -6049,6 +6053,27 @@ package body Sem_Eval is end Is_Statically_Unevaluated; -------------------- + -- Machine_Number -- + -------------------- + + -- Historical note: RM 4.9(38) originally specified biased rounding but + -- this has been modified by AI-268 to prevent confusing differences in + -- rounding between static and nonstatic expressions. This AI specifies + -- that the effect of such rounding is implementation-dependent instead, + -- and in GNAT we round to nearest even to match the run-time behavior. + -- Note that this applies to floating-point literals, not fixed-point + -- ones, even though their representation is also a universal real. + + function Machine_Number + (Typ : Entity_Id; + Val : Ureal; + N : Node_Id) return Ureal + is + begin + return Machine (Typ, Val, Round_Even, N); + end Machine_Number; + + -------------------- -- Not_Null_Range -- -------------------- @@ -7335,19 +7360,12 @@ package body Sem_Eval is elsif Compile_Time_Known_Value (N) then declare - Lo : Node_Id; - Hi : Node_Id; - - LB_Known : Boolean; - HB_Known : Boolean; + Lo : constant Node_Id := Type_Low_Bound (Typ); + Hi : constant Node_Id := Type_High_Bound (Typ); + LB_Known : constant Boolean := Compile_Time_Known_Value (Lo); + HB_Known : constant Boolean := Compile_Time_Known_Value (Hi); begin - Lo := Type_Low_Bound (Typ); - Hi := Type_High_Bound (Typ); - - LB_Known := Compile_Time_Known_Value (Lo); - HB_Known := Compile_Time_Known_Value (Hi); - -- Fixed point types should be considered as such only if flag -- Fixed_Int is set to False. diff --git a/gcc/ada/sem_eval.ads b/gcc/ada/sem_eval.ads index 5e1c2cb..c2e08b6 100644 --- a/gcc/ada/sem_eval.ads +++ b/gcc/ada/sem_eval.ads @@ -149,10 +149,9 @@ package Sem_Eval is -- -- Note: most cases of non-static context checks are handled within -- Sem_Eval itself, including all cases of expressions at the outer level - -- (i.e. those that are not a subexpression). Currently the only outside - -- customer for this procedure is Sem_Attr (because Eval_Attribute is - -- there). There is also one special case arising from ranges (see body of - -- Resolve_Range). + -- (i.e. those that are not a subexpression). The outside customers for + -- this procedure are Sem_Aggr, Sem_Attr (because Eval_Attribute is there) + -- and Sem_Res (for a special case arising from ranges, see Resolve_Range). -- -- Note: this procedure is also called by GNATprove on real literals -- that are not sub-expressions of static expressions, to convert them to @@ -487,6 +486,13 @@ package Sem_Eval is -- it cannot be determined at compile time. Flag Fixed_Int is used as in -- routine Is_In_Range above. + function Machine_Number + (Typ : Entity_Id; + Val : Ureal; + N : Node_Id) return Ureal; + -- Return the machine number of Typ corresponding to the specified Val as + -- per RM 4.9(38/2). N is a node only used to post warnings. + function Not_Null_Range (Lo : Node_Id; Hi : Node_Id) return Boolean; -- Returns True if it can guarantee that Lo .. Hi is not a null range. If -- it cannot (because the value of Lo or Hi is not known at compile time) @@ -575,5 +581,6 @@ private pragma Inline (Eval_Unchecked_Conversion); pragma Inline (Is_OK_Static_Expression); + pragma Inline (Machine_Number); end Sem_Eval; diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index b3fa32a..1e6397f 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -4144,8 +4144,10 @@ package body Sem_Prag is -- than library level instantiations these can appear in contexts which -- would normally be invalid (they only apply to the original template -- and to library level instantiations), and they are simply ignored, - -- which is implemented by rewriting them as null statements and raising - -- exception to terminate analysis. + -- which is implemented by rewriting them as null statements and + -- optionally raising Pragma_Exit to terminate analysis. An exception + -- is not always raised to avoid exception propagation during the + -- bootstrap, so all callers should check whether N has been rewritten. procedure Check_Variant (Variant : Node_Id; UU_Typ : Entity_Id); -- Check an Unchecked_Union variant for lack of nested variants and @@ -6652,8 +6654,14 @@ package body Sem_Prag is Sindex := Source_Index (Current_Sem_Unit); if Loc not in Source_First (Sindex) .. Source_Last (Sindex) then + -- We do not want to raise an exception here since this code + -- is part of the bootstrap path where we cannot rely on + -- exception proapgation working. + -- Instead the caller should check for N being rewritten as + -- a null statement. + -- This code triggers when compiling a-except.adb. + Rewrite (N, Make_Null_Statement (Loc)); - raise Pragma_Exit; -- If before first declaration, the pragma applies to the -- enclosing unit, and the name if present must be this name. @@ -12719,6 +12727,13 @@ package body Sem_Prag is Check_Ada_83_Warning; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + Lib_Entity := Find_Lib_Unit_Name; -- A pragma that applies to a Ghost entity becomes Ghost for the @@ -15967,6 +15982,13 @@ package body Sem_Prag is Check_Ada_83_Warning; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + Cunit_Node := Cunit (Current_Sem_Unit); Cunit_Ent := Cunit_Entity (Current_Sem_Unit); @@ -19650,6 +19672,13 @@ package body Sem_Prag is GNAT_Pragma; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + -- Must appear for a spec or generic spec if Nkind (Unit (Cunit (Current_Sem_Unit))) not in @@ -21436,6 +21465,13 @@ package body Sem_Prag is Check_Ada_83_Warning; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + Ent := Find_Lib_Unit_Name; -- A pragma that applies to a Ghost entity becomes Ghost for the @@ -22072,8 +22108,15 @@ package body Sem_Prag is if Is_Wrapper_Package (Current_Scope) then return; - else - Check_Valid_Library_Unit_Pragma; + end if; + + Check_Valid_Library_Unit_Pragma; + + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; end if; Ent := Find_Lib_Unit_Name; @@ -22612,6 +22655,13 @@ package body Sem_Prag is Check_Ada_83_Warning; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + Cunit_Node := Cunit (Current_Sem_Unit); K := Nkind (Unit (Cunit_Node)); Cunit_Ent := Cunit_Entity (Current_Sem_Unit); @@ -22651,6 +22701,13 @@ package body Sem_Prag is Check_Ada_83_Warning; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + Cunit_Node := Cunit (Current_Sem_Unit); Cunit_Ent := Cunit_Entity (Current_Sem_Unit); @@ -22847,6 +22904,13 @@ package body Sem_Prag is Check_Ada_83_Warning; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + Cunit_Node := Cunit (Current_Sem_Unit); Cunit_Ent := Cunit_Entity (Current_Sem_Unit); diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index e79c534..db4d55a 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -315,7 +315,8 @@ package body Sem_Util is -- Ignore transient scopes made during expansion if Comes_From_Source (Node_Par) then - return Scope_Depth (Encl_Scop) + Master_Lvl_Modifier; + return + Scope_Depth_Default_0 (Encl_Scop) + Master_Lvl_Modifier; end if; -- For a return statement within a function, return @@ -627,9 +628,9 @@ package body Sem_Util is -- caller. if Is_Explicitly_Aliased (E) - and then Level /= Dynamic_Level - and then (In_Return_Value (Expr) - or else In_Return_Context) + and then (In_Return_Context + or else (Level /= Dynamic_Level + and then In_Return_Value (Expr))) then return Make_Level_Literal (Scope_Depth (Standard_Standard)); @@ -1137,6 +1138,10 @@ package body Sem_Util is function Addressable (V : Uint) return Boolean is begin + if No (V) then + return False; + end if; + return V = Uint_8 or else V = Uint_16 or else V = Uint_32 or else diff --git a/gcc/ada/sinfo-utils.adb b/gcc/ada/sinfo-utils.adb index cf0ecc1..79269a5 100644 --- a/gcc/ada/sinfo-utils.adb +++ b/gcc/ada/sinfo-utils.adb @@ -242,15 +242,28 @@ package body Sinfo.Utils is use Seinfo; function Is_In_Union_Id (F_Kind : Field_Kind) return Boolean is - (F_Kind in Node_Id_Field - | List_Id_Field - | Elist_Id_Field - | Name_Id_Field - | String_Id_Field - | Uint_Field - | Ureal_Field - | Union_Id_Field); -- True if the field type is one that can be converted to Types.Union_Id + (case F_Kind is + when Node_Id_Field + | List_Id_Field + | Elist_Id_Field + | Name_Id_Field + | String_Id_Field + | Valid_Uint_Field + | Unat_Field + | Upos_Field + | Nonzero_Uint_Field + | Uint_Field + | Ureal_Field + | Union_Id_Field => True, + when Flag_Field + | Node_Kind_Type_Field + | Entity_Kind_Type_Field + | Source_Ptr_Field + | Small_Paren_Count_Type_Field + | Convention_Id_Field + | Component_Alignment_Kind_Field + | Mechanism_Type_Field => False); ----------------------- -- Walk_Sinfo_Fields -- diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb index 9b78ada..69996cb 100644 --- a/gcc/ada/sprint.adb +++ b/gcc/ada/sprint.adb @@ -4394,7 +4394,12 @@ package body Sprint is when E_Modular_Integer_Type => Write_Header; Write_Str ("mod "); - Write_Uint_With_Col_Check (Modulus (Typ), Auto); + + if No (Modulus (Typ)) then + Write_Uint_With_Col_Check (Uint_0, Auto); + else + Write_Uint_With_Col_Check (Modulus (Typ), Auto); + end if; -- Floating-point types and subtypes diff --git a/gcc/ada/treepr.adb b/gcc/ada/treepr.adb index 2e9d2c2..d36042c 100644 --- a/gcc/ada/treepr.adb +++ b/gcc/ada/treepr.adb @@ -885,14 +885,13 @@ package body Treepr is Val : constant Uint := Get_Uint (N, FD.Offset); function Cast is new Unchecked_Conversion (Uint, Int); begin - -- Do this even if Val = No_Uint, because Uint fields default - -- to Uint_0. - - Print_Initial; - UI_Write (Val, Format); - Write_Str (" (Uint = "); - Write_Int (Cast (Val)); - Write_Char (')'); + if Present (Val) then + Print_Initial; + UI_Write (Val, Format); + Write_Str (" (Uint = "); + Write_Int (Cast (Val)); + Write_Char (')'); + end if; end; when Valid_Uint_Field | Unat_Field | Upos_Field diff --git a/gcc/ada/types.h b/gcc/ada/types.h index 2806e50..0938365 100644 --- a/gcc/ada/types.h +++ b/gcc/ada/types.h @@ -261,10 +261,10 @@ typedef Int String_Id; /* Type used for representation of universal integers. */ typedef Int Uint; -typedef Int Valid_Uint; -typedef Int Unat; -typedef Int Upos; -typedef Int Nonzero_Uint; +typedef Uint Valid_Uint; +typedef Uint Unat; +typedef Uint Upos; +typedef Uint Nonzero_Uint; /* Used to indicate missing Uint value. */ #define No_Uint Uint_Low_Bound diff --git a/gcc/ada/uintp.adb b/gcc/ada/uintp.adb index 29d409b..5d1dec1 100644 --- a/gcc/ada/uintp.adb +++ b/gcc/ada/uintp.adb @@ -282,7 +282,10 @@ package body Uintp is -- value is returned from a correctness point of view. procedure Image_Char (C : Character); - -- Internal procedure to output one character + -- Output one character + + procedure Image_String (S : String); + -- Output characters procedure Image_Exponent (N : Natural); -- Output non-zero exponent. Note that we only use the exponent form in @@ -371,6 +374,17 @@ package body Uintp is Character'Val (Character'Pos ('0') + N mod 10); end Image_Exponent; + ------------------ + -- Image_String -- + ------------------ + + procedure Image_String (S : String) is + begin + for X in S'Range loop + Image_Char (S (X)); + end loop; + end Image_String; + ---------------- -- Image_Uint -- ---------------- @@ -401,7 +415,7 @@ package body Uintp is begin if No (Input) then - Image_Char ('?'); + Image_String ("No_Uint"); return; end if; diff --git a/gcc/ada/usage.adb b/gcc/ada/usage.adb index bca3527..207303b 100644 --- a/gcc/ada/usage.adb +++ b/gcc/ada/usage.adb @@ -557,6 +557,8 @@ begin "order"); Write_Line (" .P* turn off warnings for suspicious parameter " & "order"); + Write_Line (" _p turn on warnings for pedantic checks"); + Write_Line (" _P turn off warnings for pedantic checks"); Write_Line (" q*+ turn on warnings for questionable " & "missing parenthesis"); Write_Line (" Q turn off warnings for questionable " & diff --git a/gcc/ada/vxworks7-cert-rtp-link.spec b/gcc/ada/vxworks7-cert-rtp-link.spec index 0e0440f..4bbf376 100644 --- a/gcc/ada/vxworks7-cert-rtp-link.spec +++ b/gcc/ada/vxworks7-cert-rtp-link.spec @@ -5,5 +5,6 @@ + %{!nostdlib:%{mrtp:%{!shared: \ -l:certRtp.o \ -L%:getenv(VSB_DIR /usr/lib/common/objcert) \ + --defsym=__wrs_rtp_base=0x80000000 \ -T%:getenv(VSB_DIR /usr/ldscripts/rtp.ld) \ }}} diff --git a/gcc/ada/warnsw.adb b/gcc/ada/warnsw.adb index 912ceea..149e2fd 100644 --- a/gcc/ada/warnsw.adb +++ b/gcc/ada/warnsw.adb @@ -76,6 +76,7 @@ package body Warnsw is Warn_On_Overlap := Setting; Warn_On_Overridden_Size := Setting; Warn_On_Parameter_Order := Setting; + Warn_On_Pedantic_Checks := Setting; Warn_On_Questionable_Layout := Setting; Warn_On_Questionable_Missing_Parens := Setting; Warn_On_Record_Holes := Setting; @@ -172,6 +173,8 @@ package body Warnsw is W.Warn_On_Overridden_Size; Warn_On_Parameter_Order := W.Warn_On_Parameter_Order; + Warn_On_Pedantic_Checks := + W.Warn_On_Pedantic_Checks; Warn_On_Questionable_Layout := W.Warn_On_Questionable_Layout; Warn_On_Questionable_Missing_Parens := @@ -284,6 +287,8 @@ package body Warnsw is Warn_On_Overridden_Size; W.Warn_On_Parameter_Order := Warn_On_Parameter_Order; + W.Warn_On_Pedantic_Checks := + Warn_On_Pedantic_Checks; W.Warn_On_Questionable_Layout := Warn_On_Questionable_Layout; W.Warn_On_Questionable_Missing_Parens := @@ -505,6 +510,12 @@ package body Warnsw is when 'C' => Warn_On_Unknown_Compile_Time_Warning := False; + when 'p' => + Warn_On_Pedantic_Checks := True; + + when 'P' => + Warn_On_Pedantic_Checks := False; + when 'r' => Warn_On_Component_Order := True; diff --git a/gcc/ada/warnsw.ads b/gcc/ada/warnsw.ads index 340a752..6113538 100644 --- a/gcc/ada/warnsw.ads +++ b/gcc/ada/warnsw.ads @@ -58,6 +58,13 @@ package Warnsw is -- set with an explicit size clause. Off by default, modified by use of -- -gnatw.s/.S (but not -gnatwa). + Warn_On_Pedantic_Checks : Boolean := False; + -- Warn for violation of miscellaneous pedantic rules (such as when the + -- subtype of a formal parameter given in a subprogram body's specification + -- comes from a different subtype declaration that the subtype of the + -- formal in the subprogram declaration). Off by default, and set by + -- -gnatw_p (but not -gnatwa). + Warn_On_Questionable_Layout : Boolean := False; -- Warn when default layout of a record type is questionable for run-time -- efficiency reasons and would be improved by reordering the components. @@ -128,6 +135,7 @@ package Warnsw is Warn_On_Overlap : Boolean; Warn_On_Overridden_Size : Boolean; Warn_On_Parameter_Order : Boolean; + Warn_On_Pedantic_Checks : Boolean; Warn_On_Questionable_Layout : Boolean; Warn_On_Questionable_Missing_Parens : Boolean; Warn_On_Record_Holes : Boolean; diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index af9eba8..5625be7 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -2860,13 +2860,44 @@ c_omp_predefined_variable (tree decl) { if (VAR_P (decl) && DECL_ARTIFICIAL (decl) - && TREE_READONLY (decl) && TREE_STATIC (decl) - && DECL_NAME (decl) - && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME] - || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME] - || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME])) - return true; + && DECL_NAME (decl)) + { + if (TREE_READONLY (decl) + && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME] + || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME] + || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME])) + return true; + /* For UBSan handle the same also ubsan_create_data created + variables. There is no magic flag for those, but user variables + shouldn't be DECL_ARTIFICIAL or have TYPE_ARTIFICIAL type with + such names. */ + if ((flag_sanitize & (SANITIZE_UNDEFINED + | SANITIZE_UNDEFINED_NONDEFAULT)) != 0 + && DECL_IGNORED_P (decl) + && !TREE_READONLY (decl) + && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE + && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE + && TYPE_ARTIFICIAL (TREE_TYPE (decl)) + && TYPE_NAME (TREE_TYPE (decl)) + && TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) == TYPE_DECL + && DECL_NAME (TYPE_NAME (TREE_TYPE (decl))) + && (TREE_CODE (DECL_NAME (TYPE_NAME (TREE_TYPE (decl)))) + == IDENTIFIER_NODE)) + { + tree id1 = DECL_NAME (decl); + tree id2 = DECL_NAME (TYPE_NAME (TREE_TYPE (decl))); + if (IDENTIFIER_LENGTH (id1) >= sizeof ("ubsan_data") - 1 + && IDENTIFIER_LENGTH (id2) >= sizeof ("__ubsan__data") + && !memcmp (IDENTIFIER_POINTER (id2), "__ubsan_", + sizeof ("__ubsan_") - 1) + && !memcmp (IDENTIFIER_POINTER (id2) + IDENTIFIER_LENGTH (id2) + - sizeof ("_data") + 1, "_data", + sizeof ("_data") - 1) + && strstr (IDENTIFIER_POINTER (id1), "ubsan_data")) + return true; + } + } return false; } diff --git a/gcc/calls.c b/gcc/calls.c index e50d3fc..27b59f2 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1287,8 +1287,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, args_size->constant = 0; args_size->var = 0; - bitmap_obstack_initialize (NULL); - /* In this loop, we consider args in the order they are written. We fill up ARGS from the back. */ @@ -1297,7 +1295,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, int j = i; call_expr_arg_iterator iter; tree arg; - bitmap slots = NULL; if (struct_value_addr_value) { @@ -1324,13 +1321,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, j--; argpos++; } - - if (slots) - BITMAP_FREE (slots); } - bitmap_obstack_release (NULL); - /* I counts args in order (to be) pushed; ARGPOS counts in order written. */ for (argpos = 0; argpos < num_actuals; i--, argpos++) { @@ -1493,9 +1485,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, args[i].reg = targetm.calls.function_arg (args_so_far, arg); - if (args[i].reg && CONST_INT_P (args[i].reg)) - args[i].reg = NULL; - /* If this is a sibling call and the machine has register windows, the register window has to be unwinded before calling the routine, so arguments have to go into the incoming registers. */ diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 03260b0..8b067f9 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -6090,7 +6090,7 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) /* Expand implicit goto and convert goto_locus. */ FOR_EACH_EDGE (e, ei, bb->succs) { - if (e->goto_locus != UNKNOWN_LOCATION || !stmt) + if (e->goto_locus != UNKNOWN_LOCATION || !stmt || is_gimple_debug (stmt)) set_curr_insn_location (e->goto_locus); if ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb) { diff --git a/gcc/config.gcc b/gcc/config.gcc index 3675e06..fb1f06f 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -490,6 +490,7 @@ powerpc*-*-*) extra_headers="${extra_headers} xmmintrin.h mm_malloc.h emmintrin.h" extra_headers="${extra_headers} mmintrin.h x86intrin.h" extra_headers="${extra_headers} pmmintrin.h tmmintrin.h smmintrin.h" + extra_headers="${extra_headers} nmmintrin.h" extra_headers="${extra_headers} ppu_intrinsics.h spu2vmx.h vec_types.h si2vmx.h" extra_headers="${extra_headers} amo.h" case x$with_cpu in diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c index 1a507ea..a815e4c 100644 --- a/gcc/config/aarch64/aarch64-builtins.c +++ b/gcc/config/aarch64/aarch64-builtins.c @@ -46,6 +46,7 @@ #include "emit-rtl.h" #include "stringpool.h" #include "attribs.h" +#include "gimple-fold.h" #define v8qi_UP E_V8QImode #define v4hi_UP E_V4HImode @@ -2399,11 +2400,65 @@ aarch64_general_fold_builtin (unsigned int fcode, tree type, return NULL_TREE; } +enum aarch64_simd_type +get_mem_type_for_load_store (unsigned int fcode) +{ + switch (fcode) + { + VAR1 (LOAD1, ld1 , 0, LOAD, v8qi) + VAR1 (STORE1, st1 , 0, STORE, v8qi) + return Int8x8_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v16qi) + VAR1 (STORE1, st1 , 0, STORE, v16qi) + return Int8x16_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v4hi) + VAR1 (STORE1, st1 , 0, STORE, v4hi) + return Int16x4_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v8hi) + VAR1 (STORE1, st1 , 0, STORE, v8hi) + return Int16x8_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v2si) + VAR1 (STORE1, st1 , 0, STORE, v2si) + return Int32x2_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v4si) + VAR1 (STORE1, st1 , 0, STORE, v4si) + return Int32x4_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v2di) + VAR1 (STORE1, st1 , 0, STORE, v2di) + return Int64x2_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v4hf) + VAR1 (STORE1, st1 , 0, STORE, v4hf) + return Float16x4_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v8hf) + VAR1 (STORE1, st1 , 0, STORE, v8hf) + return Float16x8_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v4bf) + VAR1 (STORE1, st1 , 0, STORE, v4bf) + return Bfloat16x4_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v8bf) + VAR1 (STORE1, st1 , 0, STORE, v8bf) + return Bfloat16x8_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v2sf) + VAR1 (STORE1, st1 , 0, STORE, v2sf) + return Float32x2_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v4sf) + VAR1 (STORE1, st1 , 0, STORE, v4sf) + return Float32x4_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v2df) + VAR1 (STORE1, st1 , 0, STORE, v2df) + return Float64x2_t; + default: + gcc_unreachable (); + break; + } +} + /* Try to fold STMT, given that it's a call to the built-in function with subcode FCODE. Return the new statement on success and null on failure. */ gimple * -aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt) +aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt, + gimple_stmt_iterator *gsi) { gimple *new_stmt = NULL; unsigned nargs = gimple_call_num_args (stmt); @@ -2421,6 +2476,52 @@ aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt) 1, args[0]); gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt)); break; + + /*lower store and load neon builtins to gimple. */ + BUILTIN_VALL_F16 (LOAD1, ld1, 0, LOAD) + if (!BYTES_BIG_ENDIAN) + { + enum aarch64_simd_type mem_type + = get_mem_type_for_load_store(fcode); + aarch64_simd_type_info simd_type + = aarch64_simd_types[mem_type]; + tree elt_ptr_type = build_pointer_type (simd_type.eltype); + tree zero = build_zero_cst (elt_ptr_type); + gimple_seq stmts = NULL; + tree base = gimple_convert (&stmts, elt_ptr_type, + args[0]); + if (stmts) + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + new_stmt + = gimple_build_assign (gimple_get_lhs (stmt), + fold_build2 (MEM_REF, + simd_type.itype, + base, zero)); + } + break; + + BUILTIN_VALL_F16 (STORE1, st1, 0, STORE) + if (!BYTES_BIG_ENDIAN) + { + enum aarch64_simd_type mem_type + = get_mem_type_for_load_store(fcode); + aarch64_simd_type_info simd_type + = aarch64_simd_types[mem_type]; + tree elt_ptr_type = build_pointer_type (simd_type.eltype); + tree zero = build_zero_cst (elt_ptr_type); + gimple_seq stmts = NULL; + tree base = gimple_convert (&stmts, elt_ptr_type, + args[0]); + if (stmts) + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + new_stmt + = gimple_build_assign (fold_build2 (MEM_REF, + simd_type.itype, + base, + zero), args[1]); + } + break; + BUILTIN_VDQIF (UNOP, reduc_smax_scal_, 10, ALL) BUILTIN_VDQ_BHSI (UNOPU, reduc_umax_scal_, 10, ALL) new_stmt = gimple_build_call_internal (IFN_REDUC_MAX, diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index b91eeeb..768e8fa 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -962,7 +962,8 @@ void aarch64_override_options_internal (struct gcc_options *); const char *aarch64_general_mangle_builtin_type (const_tree); void aarch64_general_init_builtins (void); tree aarch64_general_fold_builtin (unsigned int, tree, unsigned int, tree *); -gimple *aarch64_general_gimple_fold_builtin (unsigned int, gcall *); +gimple *aarch64_general_gimple_fold_builtin (unsigned int, gcall *, + gimple_stmt_iterator *); rtx aarch64_general_expand_builtin (unsigned int, tree, rtx, int); tree aarch64_general_builtin_decl (unsigned, bool); tree aarch64_general_builtin_rsqrt (unsigned int); diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def index 35dc075..be1c5b5 100644 --- a/gcc/config/aarch64/aarch64-simd-builtins.def +++ b/gcc/config/aarch64/aarch64-simd-builtins.def @@ -506,7 +506,7 @@ BUILTIN_VHSDF (UNOP, nearbyint, 2, FP) BUILTIN_VHSDF (UNOP, rint, 2, FP) BUILTIN_VHSDF (UNOP, round, 2, FP) - BUILTIN_VHSDF_HSDF (UNOP, frintn, 2, FP) + BUILTIN_VHSDF_HSDF (UNOP, roundeven, 2, FP) VAR1 (UNOP, btrunc, 2, FP, hf) VAR1 (UNOP, ceil, 2, FP, hf) diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 48eddf6..29f3817 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -1127,12 +1127,14 @@ ) (define_insn "aarch64_simd_ashr<mode>" - [(set (match_operand:VDQ_I 0 "register_operand" "=w") - (ashiftrt:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w") - (match_operand:VDQ_I 2 "aarch64_simd_rshift_imm" "Dr")))] + [(set (match_operand:VDQ_I 0 "register_operand" "=w,w") + (ashiftrt:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w,w") + (match_operand:VDQ_I 2 "aarch64_simd_rshift_imm" "D1,Dr")))] "TARGET_SIMD" - "sshr\t%0.<Vtype>, %1.<Vtype>, %2" - [(set_attr "type" "neon_shift_imm<q>")] + "@ + cmlt\t%0.<Vtype>, %1.<Vtype>, #0 + sshr\t%0.<Vtype>, %1.<Vtype>, %2" + [(set_attr "type" "neon_compare<q>,neon_shift_imm<q>")] ) (define_insn "*aarch64_simd_sra<mode>" @@ -1751,6 +1753,23 @@ } ) +(define_insn "*aarch64_narrow_trunc<mode>" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (truncate:<VNARROWQ> + (match_operand:VQN 1 "register_operand" "w")) + (truncate:<VNARROWQ> + (match_operand:VQN 2 "register_operand" "w"))))] + "TARGET_SIMD" +{ + if (!BYTES_BIG_ENDIAN) + return "uzp1\\t%0.<V2ntype>, %1.<V2ntype>, %2.<V2ntype>"; + else + return "uzp1\\t%0.<V2ntype>, %2.<V2ntype>, %1.<V2ntype>"; +} + [(set_attr "type" "neon_permute<q>")] +) + ;; Packing doubles. (define_expand "vec_pack_trunc_<mode>" @@ -1818,6 +1837,100 @@ [(set_attr "type" "neon_shift_imm_narrow_q")] ) +(define_insn "*aarch64_<srn_op>shrn<mode>_vect" + [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w") + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 1 "register_operand" "w") + (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_<vn_mode>"))))] + "TARGET_SIMD" + "shrn\\t%0.<Vntype>, %1.<Vtype>, %2" + [(set_attr "type" "neon_shift_imm_narrow_q")] +) + +(define_insn "*aarch64_<srn_op>shrn<mode>2_vect_le" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (match_operand:<VNARROWQ> 1 "register_operand" "0") + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 2 "register_operand" "w") + (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>")))))] + "TARGET_SIMD && !BYTES_BIG_ENDIAN" + "shrn2\\t%0.<V2ntype>, %2.<Vtype>, %3" + [(set_attr "type" "neon_shift_imm_narrow_q")] +) + +(define_insn "*aarch64_<srn_op>shrn<mode>2_vect_be" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 2 "register_operand" "w") + (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>"))) + (match_operand:<VNARROWQ> 1 "register_operand" "0")))] + "TARGET_SIMD && BYTES_BIG_ENDIAN" + "shrn2\\t%0.<V2ntype>, %2.<Vtype>, %3" + [(set_attr "type" "neon_shift_imm_narrow_q")] +) + +(define_insn "*aarch64_<srn_op>topbits_shuffle<mode>_le" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 1 "register_operand" "w") + (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_exact_top"))) + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 3 "register_operand" "w") + (match_dup 2)))))] + "TARGET_SIMD && !BYTES_BIG_ENDIAN" + "uzp2\\t%0.<V2ntype>, %1.<V2ntype>, %3.<V2ntype>" + [(set_attr "type" "neon_permute<q>")] +) + +(define_insn "*aarch64_topbits_shuffle<mode>_le" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (unspec:<VNARROWQ> [ + (match_operand:VQN 1 "register_operand" "w") + (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_exact_top") + ] UNSPEC_RSHRN) + (unspec:<VNARROWQ> [ + (match_operand:VQN 3 "register_operand" "w") + (match_dup 2) + ] UNSPEC_RSHRN)))] + "TARGET_SIMD && !BYTES_BIG_ENDIAN" + "uzp2\\t%0.<V2ntype>, %1.<V2ntype>, %3.<V2ntype>" + [(set_attr "type" "neon_permute<q>")] +) + +(define_insn "*aarch64_<srn_op>topbits_shuffle<mode>_be" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 3 "register_operand" "w") + (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_exact_top"))) + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 1 "register_operand" "w") + (match_dup 2)))))] + "TARGET_SIMD && BYTES_BIG_ENDIAN" + "uzp2\\t%0.<V2ntype>, %1.<V2ntype>, %3.<V2ntype>" + [(set_attr "type" "neon_permute<q>")] +) + +(define_insn "*aarch64_topbits_shuffle<mode>_be" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (unspec:<VNARROWQ> [ + (match_operand:VQN 3 "register_operand" "w") + (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_exact_top") + ] UNSPEC_RSHRN) + (unspec:<VNARROWQ> [ + (match_operand:VQN 1 "register_operand" "w") + (match_dup 2) + ] UNSPEC_RSHRN)))] + "TARGET_SIMD && BYTES_BIG_ENDIAN" + "uzp2\\t%0.<V2ntype>, %1.<V2ntype>, %3.<V2ntype>" + [(set_attr "type" "neon_permute<q>")] +) + (define_expand "aarch64_shrn<mode>" [(set (match_operand:<VNARROWQ> 0 "register_operand") (truncate:<VNARROWQ> @@ -6507,6 +6620,23 @@ [(set_attr "type" "neon_tst<q>")] ) +;; One can also get a cmtsts by having to combine a +;; not (neq (eq x 0)) in which case you rewrite it to +;; a comparison against itself + +(define_insn "*aarch64_cmtst_same_<mode>" + [(set (match_operand:<V_INT_EQUIV> 0 "register_operand" "=w") + (plus:<V_INT_EQUIV> + (eq:<V_INT_EQUIV> + (match_operand:VDQ_I 1 "register_operand" "w") + (match_operand:VDQ_I 2 "aarch64_simd_imm_zero")) + (match_operand:<V_INT_EQUIV> 3 "aarch64_simd_imm_minus_one"))) + ] + "TARGET_SIMD" + "cmtst\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>1<Vmtype>" + [(set_attr "type" "neon_tst<q>")] +) + (define_insn_and_split "aarch64_cmtstdi" [(set (match_operand:DI 0 "register_operand" "=w,r") (neg:DI diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 76d99d2..699c105 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -1839,7 +1839,8 @@ static const struct tune_params neoversev1_tunings = tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ (AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS - | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ + | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT + | AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ &generic_prefetch_tune }; @@ -1995,7 +1996,7 @@ static const struct tune_params neoversen2_tunings = 2, /* min_div_recip_mul_df. */ 0, /* max_case_values. */ tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ &generic_prefetch_tune }; @@ -9499,8 +9500,8 @@ aarch64_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x) The expansion for a table switch is quite expensive due to the number of instructions, the table lookup and hard to predict indirect jump. When optimizing for speed, and -O3 enabled, use the per-core tuning if - set, otherwise use tables for > 16 cases as a tradeoff between size and - performance. When optimizing for size, use the default setting. */ + set, otherwise use tables for >= 11 cases as a tradeoff between size and + performance. When optimizing for size, use 8 for smallest codesize. */ static unsigned int aarch64_case_values_threshold (void) @@ -9511,7 +9512,7 @@ aarch64_case_values_threshold (void) && selected_cpu->tune->max_case_values != 0) return selected_cpu->tune->max_case_values; else - return optimize_size ? default_case_values_threshold () : 17; + return optimize_size ? 8 : 11; } /* Return true if register REGNO is a valid index register. @@ -14156,7 +14157,7 @@ aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi) switch (code & AARCH64_BUILTIN_CLASS) { case AARCH64_BUILTIN_GENERAL: - new_stmt = aarch64_general_gimple_fold_builtin (subcode, stmt); + new_stmt = aarch64_general_gimple_fold_builtin (subcode, stmt, gsi); break; case AARCH64_BUILTIN_SVE: diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 7085cd4..1a39470 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -5920,7 +5920,7 @@ ;; ------------------------------------------------------------------- ;; frint floating-point round to integral standard patterns. -;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn. +;; Expands to btrunc, ceil, floor, nearbyint, rint, round, roundeven. (define_insn "<frint_pattern><mode>2" [(set (match_operand:GPF_F16 0 "register_operand" "=w") diff --git a/gcc/config/aarch64/arm_fp16.h b/gcc/config/aarch64/arm_fp16.h index 2633953..c223546 100644 --- a/gcc/config/aarch64/arm_fp16.h +++ b/gcc/config/aarch64/arm_fp16.h @@ -383,7 +383,7 @@ __extension__ extern __inline float16_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndnh_f16 (float16_t __a) { - return __builtin_aarch64_frintnhf (__a); + return __builtin_aarch64_roundevenhf (__a); } __extension__ extern __inline float16_t diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h index 24068f8..1768c6b 100644 --- a/gcc/config/aarch64/arm_neon.h +++ b/gcc/config/aarch64/arm_neon.h @@ -26359,35 +26359,35 @@ __extension__ extern __inline float32_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndns_f32 (float32_t __a) { - return __builtin_aarch64_frintnsf (__a); + return __builtin_aarch64_roundevensf (__a); } __extension__ extern __inline float32x2_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndn_f32 (float32x2_t __a) { - return __builtin_aarch64_frintnv2sf (__a); + return __builtin_aarch64_roundevenv2sf (__a); } __extension__ extern __inline float64x1_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndn_f64 (float64x1_t __a) { - return (float64x1_t) {__builtin_aarch64_frintndf (__a[0])}; + return (float64x1_t) {__builtin_aarch64_roundevendf (__a[0])}; } __extension__ extern __inline float32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndnq_f32 (float32x4_t __a) { - return __builtin_aarch64_frintnv4sf (__a); + return __builtin_aarch64_roundevenv4sf (__a); } __extension__ extern __inline float64x2_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndnq_f64 (float64x2_t __a) { - return __builtin_aarch64_frintnv2df (__a); + return __builtin_aarch64_roundevenv2df (__a); } /* vrndp */ @@ -32792,14 +32792,14 @@ __extension__ extern __inline float16x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndn_f16 (float16x4_t __a) { - return __builtin_aarch64_frintnv4hf (__a); + return __builtin_aarch64_roundevenv4hf (__a); } __extension__ extern __inline float16x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndnq_f16 (float16x8_t __a) { - return __builtin_aarch64_frintnv8hf (__a); + return __builtin_aarch64_roundevenv8hf (__a); } __extension__ extern __inline float16x4_t diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md index 3b49b45..1863081 100644 --- a/gcc/config/aarch64/constraints.md +++ b/gcc/config/aarch64/constraints.md @@ -437,6 +437,14 @@ (match_test "aarch64_simd_shift_imm_p (op, GET_MODE (op), true)"))) +(define_constraint "D1" + "@internal + A constraint that matches vector of immediates that is bits(mode)-1." + (and (match_code "const,const_vector") + (match_test "aarch64_const_vec_all_same_in_range_p (op, + GET_MODE_UNIT_BITSIZE (mode) - 1, + GET_MODE_UNIT_BITSIZE (mode) - 1)"))) + (define_constraint "Dr" "@internal A constraint that matches vector of immediates for right shifts." diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index caa42f8..aee32dc 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -2003,6 +2003,9 @@ ;; Op prefix for shift right and accumulate. (define_code_attr sra_op [(ashiftrt "s") (lshiftrt "u")]) +;; op prefix for shift right and narrow. +(define_code_attr srn_op [(ashiftrt "r") (lshiftrt "")]) + ;; Map shift operators onto underlying bit-field instructions (define_code_attr bfshift [(ashift "ubfiz") (ashiftrt "sbfx") (lshiftrt "ubfx") (rotatert "extr")]) @@ -3084,7 +3087,7 @@ (UNSPEC_FRINTI "nearbyint") (UNSPEC_FRINTX "rint") (UNSPEC_FRINTA "round") - (UNSPEC_FRINTN "frintn")]) + (UNSPEC_FRINTN "roundeven")]) ;; frint suffix for floating-point rounding instructions. (define_int_attr frint_suffix [(UNSPEC_FRINTZ "z") (UNSPEC_FRINTP "p") diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index 49f02ae..7fd4f9e 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -545,6 +545,12 @@ (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 1, 64)"))) +(define_predicate "aarch64_simd_shift_imm_vec_exact_top" + (and (match_code "const_vector") + (match_test "aarch64_const_vec_all_same_in_range_p (op, + GET_MODE_UNIT_BITSIZE (GET_MODE (op)) / 2, + GET_MODE_UNIT_BITSIZE (GET_MODE (op)) / 2)"))) + (define_predicate "aarch64_simd_shift_imm_vec_qi" (and (match_code "const_vector") (match_test "aarch64_const_vec_all_same_in_range_p (op, 1, 8)"))) diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index e51f60a..c4ff06b 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -838,8 +838,6 @@ static char * minipool_startobj; will be conditionalised if possible. */ static int max_insns_skipped = 5; -extern FILE * asm_out_file; - /* True if we are currently building a constant table. */ int making_const_table; @@ -29408,7 +29406,7 @@ arm_dwarf_register_span (rtx rtl) epilogue. */ static void -arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) +arm_unwind_emit_sequence (FILE * out_file, rtx p) { int i; HOST_WIDE_INT offset; @@ -29452,14 +29450,14 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) padlast = offset - 4; gcc_assert (padlast == 0 || padlast == 4); if (padlast == 4) - fprintf (asm_out_file, "\t.pad #4\n"); + fprintf (out_file, "\t.pad #4\n"); reg_size = 4; - fprintf (asm_out_file, "\t.save {"); + fprintf (out_file, "\t.save {"); } else if (IS_VFP_REGNUM (reg)) { reg_size = 8; - fprintf (asm_out_file, "\t.vsave {"); + fprintf (out_file, "\t.vsave {"); } else /* Unknown register type. */ @@ -29485,13 +29483,13 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) gcc_assert (reg >= lastreg); if (i != 1) - fprintf (asm_out_file, ", "); + fprintf (out_file, ", "); /* We can't use %r for vfp because we need to use the double precision register names. */ if (IS_VFP_REGNUM (reg)) - asm_fprintf (asm_out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2); + asm_fprintf (out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2); else - asm_fprintf (asm_out_file, "%r", reg); + asm_fprintf (out_file, "%r", reg); if (flag_checking) { @@ -29509,15 +29507,15 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) offset += reg_size; } } - fprintf (asm_out_file, "}\n"); + fprintf (out_file, "}\n"); if (padfirst) - fprintf (asm_out_file, "\t.pad #%d\n", padfirst); + fprintf (out_file, "\t.pad #%d\n", padfirst); } /* Emit unwind directives for a SET. */ static void -arm_unwind_emit_set (FILE * asm_out_file, rtx p) +arm_unwind_emit_set (FILE * out_file, rtx p) { rtx e0; rtx e1; @@ -29534,12 +29532,12 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) || REGNO (XEXP (XEXP (e0, 0), 0)) != SP_REGNUM) abort (); - asm_fprintf (asm_out_file, "\t.save "); + asm_fprintf (out_file, "\t.save "); if (IS_VFP_REGNUM (REGNO (e1))) - asm_fprintf(asm_out_file, "{d%d}\n", + asm_fprintf(out_file, "{d%d}\n", (REGNO (e1) - FIRST_VFP_REGNUM) / 2); else - asm_fprintf(asm_out_file, "{%r}\n", REGNO (e1)); + asm_fprintf(out_file, "{%r}\n", REGNO (e1)); break; case REG: @@ -29552,7 +29550,7 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) || !CONST_INT_P (XEXP (e1, 1))) abort (); - asm_fprintf (asm_out_file, "\t.pad #%wd\n", + asm_fprintf (out_file, "\t.pad #%wd\n", -INTVAL (XEXP (e1, 1))); } else if (REGNO (e0) == HARD_FRAME_POINTER_REGNUM) @@ -29566,14 +29564,14 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) abort (); reg = REGNO (XEXP (e1, 0)); offset = INTVAL (XEXP (e1, 1)); - asm_fprintf (asm_out_file, "\t.setfp %r, %r, #%wd\n", + asm_fprintf (out_file, "\t.setfp %r, %r, #%wd\n", HARD_FRAME_POINTER_REGNUM, reg, offset); } else if (REG_P (e1)) { reg = REGNO (e1); - asm_fprintf (asm_out_file, "\t.setfp %r, %r\n", + asm_fprintf (out_file, "\t.setfp %r, %r\n", HARD_FRAME_POINTER_REGNUM, reg); } else @@ -29582,7 +29580,7 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) else if (REG_P (e1) && REGNO (e1) == SP_REGNUM) { /* Move from sp to reg. */ - asm_fprintf (asm_out_file, "\t.movsp %r\n", REGNO (e0)); + asm_fprintf (out_file, "\t.movsp %r\n", REGNO (e0)); } else if (GET_CODE (e1) == PLUS && REG_P (XEXP (e1, 0)) @@ -29590,7 +29588,7 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) && CONST_INT_P (XEXP (e1, 1))) { /* Set reg to offset from sp. */ - asm_fprintf (asm_out_file, "\t.movsp %r, #%d\n", + asm_fprintf (out_file, "\t.movsp %r, #%d\n", REGNO (e0), (int)INTVAL(XEXP (e1, 1))); } else @@ -29606,7 +29604,7 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) /* Emit unwind directives for the given insn. */ static void -arm_unwind_emit (FILE * asm_out_file, rtx_insn *insn) +arm_unwind_emit (FILE * out_file, rtx_insn *insn) { rtx note, pat; bool handled_one = false; @@ -29649,7 +29647,7 @@ arm_unwind_emit (FILE * asm_out_file, rtx_insn *insn) gcc_assert (src == stack_pointer_rtx); reg = REGNO (dest); - asm_fprintf (asm_out_file, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n", + asm_fprintf (out_file, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n", reg + 0x90, reg); } handled_one = true; @@ -29682,12 +29680,12 @@ arm_unwind_emit (FILE * asm_out_file, rtx_insn *insn) switch (GET_CODE (pat)) { case SET: - arm_unwind_emit_set (asm_out_file, pat); + arm_unwind_emit_set (out_file, pat); break; case SEQUENCE: /* Store multiple. */ - arm_unwind_emit_sequence (asm_out_file, pat); + arm_unwind_emit_sequence (out_file, pat); break; default: diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 8b311f3..fd65f4d 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -3018,19 +3018,6 @@ (define_insn "addsubv2hi3" [(set (match_operand:V2HI 0 "register_operand" "=d") (vec_concat:V2HI - (plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)]))) - (minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %1 +|- %2%!" - [(set_attr "type" "dsp32")]) - -(define_insn "subaddv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (vec_concat:V2HI (minus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") (parallel [(const_int 0)])) (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") @@ -3038,23 +3025,23 @@ (plus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] "" - "%0 = %1 -|+ %2%!" + "%0 = %1 +|- %2%!" [(set_attr "type" "dsp32")]) -(define_insn "ssaddsubv2hi3" +(define_insn "subaddv2hi3" [(set (match_operand:V2HI 0 "register_operand" "=d") (vec_concat:V2HI - (ss_plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)]))) - (ss_minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] + (plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") + (parallel [(const_int 0)])) + (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") + (parallel [(const_int 0)]))) + (minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) + (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] "" - "%0 = %1 +|- %2 (S)%!" + "%0 = %1 -|+ %2%!" [(set_attr "type" "dsp32")]) -(define_insn "sssubaddv2hi3" +(define_insn "ssaddsubv2hi3" [(set (match_operand:V2HI 0 "register_operand" "=d") (vec_concat:V2HI (ss_minus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") @@ -3064,6 +3051,19 @@ (ss_plus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] "" + "%0 = %1 +|- %2 (S)%!" + [(set_attr "type" "dsp32")]) + +(define_insn "sssubaddv2hi3" + [(set (match_operand:V2HI 0 "register_operand" "=d") + (vec_concat:V2HI + (ss_plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") + (parallel [(const_int 0)])) + (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") + (parallel [(const_int 0)]))) + (ss_minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) + (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] + "" "%0 = %1 -|+ %2 (S)%!" [(set_attr "type" "dsp32")]) diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index 28dc55d..204114c 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -1059,7 +1059,7 @@ machopic_legitimize_pic_address (rtx orig, machine_mode mode, rtx reg) int machopic_output_data_section_indirection (machopic_indirection **slot, - FILE *asm_out_file) + FILE *out_file) { machopic_indirection *p = *slot; @@ -1074,7 +1074,7 @@ machopic_output_data_section_indirection (machopic_indirection **slot, switch_to_section (data_section); assemble_align (GET_MODE_ALIGNMENT (Pmode)); - assemble_label (asm_out_file, ptr_name); + assemble_label (out_file, ptr_name); assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name), GET_MODE_SIZE (Pmode), GET_MODE_ALIGNMENT (Pmode), 1); @@ -1084,7 +1084,7 @@ machopic_output_data_section_indirection (machopic_indirection **slot, int machopic_output_stub_indirection (machopic_indirection **slot, - FILE *asm_out_file) + FILE *out_file) { machopic_indirection *p = *slot; @@ -1122,13 +1122,13 @@ machopic_output_stub_indirection (machopic_indirection **slot, else sprintf (stub, "%s%s", user_label_prefix, ptr_name); - machopic_output_stub (asm_out_file, sym, stub); + machopic_output_stub (out_file, sym, stub); return 1; } int -machopic_output_indirection (machopic_indirection **slot, FILE *asm_out_file) +machopic_output_indirection (machopic_indirection **slot, FILE *out_file) { machopic_indirection *p = *slot; @@ -1160,18 +1160,18 @@ machopic_output_indirection (machopic_indirection **slot, FILE *asm_out_file) storage has been allocated. */ && !TREE_STATIC (decl)) { - fputs ("\t.weak_reference ", asm_out_file); - assemble_name (asm_out_file, sym_name); - fputc ('\n', asm_out_file); + fputs ("\t.weak_reference ", out_file); + assemble_name (out_file, sym_name); + fputc ('\n', out_file); } } - assemble_name (asm_out_file, ptr_name); - fprintf (asm_out_file, ":\n"); + assemble_name (out_file, ptr_name); + fprintf (out_file, ":\n"); - fprintf (asm_out_file, "\t.indirect_symbol "); - assemble_name (asm_out_file, sym_name); - fprintf (asm_out_file, "\n"); + fprintf (out_file, "\t.indirect_symbol "); + assemble_name (out_file, sym_name); + fprintf (out_file, "\n"); /* Variables that are marked with MACHO_SYMBOL_FLAG_STATIC need to have their symbol name instead of 0 in the second entry of @@ -1191,7 +1191,7 @@ machopic_output_indirection (machopic_indirection **slot, FILE *asm_out_file) } static void -machopic_finish (FILE *asm_out_file) +machopic_finish (FILE *out_file) { if (!machopic_indirections) return; @@ -1199,13 +1199,13 @@ machopic_finish (FILE *asm_out_file) /* First output an symbol indirections that have been placed into .data (we don't expect these now). */ machopic_indirections->traverse_noresize - <FILE *, machopic_output_data_section_indirection> (asm_out_file); + <FILE *, machopic_output_data_section_indirection> (out_file); machopic_indirections->traverse_noresize - <FILE *, machopic_output_stub_indirection> (asm_out_file); + <FILE *, machopic_output_stub_indirection> (out_file); machopic_indirections->traverse_noresize - <FILE *, machopic_output_indirection> (asm_out_file); + <FILE *, machopic_output_indirection> (out_file); } int diff --git a/gcc/config/i386/avx512fp16intrin.h b/gcc/config/i386/avx512fp16intrin.h index 5e49447..44c5e24 100644 --- a/gcc/config/i386/avx512fp16intrin.h +++ b/gcc/config/i386/avx512fp16intrin.h @@ -7149,6 +7149,19 @@ _mm512_permutexvar_ph (__m512i __A, __m512h __B) (__mmask32)-1); } +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set1_pch (_Float16 _Complex __A) +{ + union + { + _Float16 _Complex a; + float b; + } u = { .a = __A}; + + return (__m512h) _mm512_set1_ps (u.b); +} + #ifdef __DISABLE_AVX512FP16__ #undef __DISABLE_AVX512FP16__ #pragma GCC pop_options diff --git a/gcc/config/i386/avx512fp16vlintrin.h b/gcc/config/i386/avx512fp16vlintrin.h index 0b1f1cb..11f34bb 100644 --- a/gcc/config/i386/avx512fp16vlintrin.h +++ b/gcc/config/i386/avx512fp16vlintrin.h @@ -3311,6 +3311,32 @@ _mm_permutexvar_ph (__m128i __A, __m128h __B) (__mmask8)-1); } +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set1_pch (_Float16 _Complex __A) +{ + union + { + _Float16 _Complex a; + float b; + } u = { .a = __A }; + + return (__m256h) _mm256_set1_ps (u.b); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_pch (_Float16 _Complex __A) +{ + union + { + _Float16 _Complex a; + float b; + } u = { .a = __A }; + + return (__m128h) _mm_set1_ps (u.b); +} + #ifdef __DISABLE_AVX512FP16VL__ #undef __DISABLE_AVX512FP16VL__ #pragma GCC pop_options diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 3c3336d..299e1ab 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1567,7 +1567,7 @@ ix86_function_naked (const_tree fn) /* Write the extra assembler code needed to declare a function properly. */ void -ix86_asm_output_function_label (FILE *asm_out_file, const char *fname, +ix86_asm_output_function_label (FILE *out_file, const char *fname, tree decl) { bool is_ms_hook = ix86_function_ms_hook_prologue (decl); @@ -1581,14 +1581,14 @@ ix86_asm_output_function_label (FILE *asm_out_file, const char *fname, unsigned int filler_cc = 0xcccccccc; for (i = 0; i < filler_count; i += 4) - fprintf (asm_out_file, ASM_LONG " %#x\n", filler_cc); + fprintf (out_file, ASM_LONG " %#x\n", filler_cc); } #ifdef SUBTARGET_ASM_UNWIND_INIT - SUBTARGET_ASM_UNWIND_INIT (asm_out_file); + SUBTARGET_ASM_UNWIND_INIT (out_file); #endif - ASM_OUTPUT_LABEL (asm_out_file, fname); + ASM_OUTPUT_LABEL (out_file, fname); /* Output magic byte marker, if hot-patch attribute is set. */ if (is_ms_hook) @@ -1597,14 +1597,14 @@ ix86_asm_output_function_label (FILE *asm_out_file, const char *fname, { /* leaq [%rsp + 0], %rsp */ fputs (ASM_BYTE "0x48, 0x8d, 0xa4, 0x24, 0x00, 0x00, 0x00, 0x00\n", - asm_out_file); + out_file); } else { /* movl.s %edi, %edi push %ebp movl.s %esp, %ebp */ - fputs (ASM_BYTE "0x8b, 0xff, 0x55, 0x8b, 0xec\n", asm_out_file); + fputs (ASM_BYTE "0x8b, 0xff, 0x55, 0x8b, 0xec\n", out_file); } } } @@ -5399,9 +5399,18 @@ ix86_get_ssemov (rtx *operands, unsigned size, switch (scalar_mode) { case E_HFmode: - opcode = (misaligned_p - ? (TARGET_AVX512BW ? "vmovdqu16" : "vmovdqu64") - : "vmovdqa64"); + if (evex_reg_p) + opcode = (misaligned_p + ? (TARGET_AVX512BW + ? "vmovdqu16" + : "vmovdqu64") + : "vmovdqa64"); + else + opcode = (misaligned_p + ? (TARGET_AVX512BW + ? "vmovdqu16" + : "%vmovdqu") + : "%vmovdqa"); break; case E_SFmode: opcode = misaligned_p ? "%vmovups" : "%vmovaps"; @@ -13921,7 +13930,10 @@ ix86_print_operand_address_as (FILE *file, rtx addr, static void ix86_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr) { - ix86_print_operand_address_as (file, addr, ADDR_SPACE_GENERIC, false); + if (this_is_asm_operands && ! address_operand (addr, VOIDmode)) + output_operand_lossage ("invalid constraints for operand"); + else + ix86_print_operand_address_as (file, addr, ADDR_SPACE_GENERIC, false); } /* Implementation of TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */ diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c index 4158a45..7c0ea4f 100644 --- a/gcc/config/i386/winnt.c +++ b/gcc/config/i386/winnt.c @@ -1231,7 +1231,7 @@ seh_frame_related_expr (FILE *f, struct seh_frame_state *seh, rtx pat) required for unwind of this insn. */ void -i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx_insn *insn) +i386_pe_seh_unwind_emit (FILE *out_file, rtx_insn *insn) { rtx note, pat; bool handled_one = false; @@ -1246,8 +1246,8 @@ i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx_insn *insn) /* See ix86_seh_fixup_eh_fallthru for the rationale. */ rtx_insn *prev = prev_active_insn (insn); if (prev && !insn_nothrow_p (prev)) - fputs ("\tnop\n", asm_out_file); - fputs ("\t.seh_endproc\n", asm_out_file); + fputs ("\tnop\n", out_file); + fputs ("\t.seh_endproc\n", out_file); seh->in_cold_section = true; return; } @@ -1286,7 +1286,7 @@ i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx_insn *insn) if (GET_CODE (pat) == PARALLEL) pat = XVECEXP (pat, 0, 0); } - seh_cfa_adjust_cfa (asm_out_file, seh, pat); + seh_cfa_adjust_cfa (out_file, seh, pat); handled_one = true; break; @@ -1294,7 +1294,7 @@ i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx_insn *insn) pat = XEXP (note, 0); if (pat == NULL) pat = single_set (insn); - seh_cfa_offset (asm_out_file, seh, pat); + seh_cfa_offset (out_file, seh, pat); handled_one = true; break; @@ -1306,7 +1306,7 @@ i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx_insn *insn) return; pat = PATTERN (insn); found: - seh_frame_related_expr (asm_out_file, seh, pat); + seh_frame_related_expr (out_file, seh, pat); } void diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 39a0e07..96c0efb 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -10044,7 +10044,7 @@ static bool need_copy_state; /* The function emits unwind directives for the start of an epilogue. */ static void -process_epilogue (FILE *asm_out_file, rtx insn ATTRIBUTE_UNUSED, +process_epilogue (FILE *out_file, rtx insn ATTRIBUTE_UNUSED, bool unwind, bool frame ATTRIBUTE_UNUSED) { /* If this isn't the last block of the function, then we need to label the @@ -10053,19 +10053,19 @@ process_epilogue (FILE *asm_out_file, rtx insn ATTRIBUTE_UNUSED, if (!last_block) { if (unwind) - fprintf (asm_out_file, "\t.label_state %d\n", + fprintf (out_file, "\t.label_state %d\n", ++cfun->machine->state_num); need_copy_state = true; } if (unwind) - fprintf (asm_out_file, "\t.restore sp\n"); + fprintf (out_file, "\t.restore sp\n"); } /* This function processes a SET pattern for REG_CFA_ADJUST_CFA. */ static void -process_cfa_adjust_cfa (FILE *asm_out_file, rtx pat, rtx insn, +process_cfa_adjust_cfa (FILE *out_file, rtx pat, rtx insn, bool unwind, bool frame) { rtx dest = SET_DEST (pat); @@ -10084,17 +10084,17 @@ process_cfa_adjust_cfa (FILE *asm_out_file, rtx pat, rtx insn, { gcc_assert (!frame_pointer_needed); if (unwind) - fprintf (asm_out_file, + fprintf (out_file, "\t.fframe " HOST_WIDE_INT_PRINT_DEC"\n", -INTVAL (op1)); } else - process_epilogue (asm_out_file, insn, unwind, frame); + process_epilogue (out_file, insn, unwind, frame); } else { gcc_assert (src == hard_frame_pointer_rtx); - process_epilogue (asm_out_file, insn, unwind, frame); + process_epilogue (out_file, insn, unwind, frame); } } else if (dest == hard_frame_pointer_rtx) @@ -10103,7 +10103,7 @@ process_cfa_adjust_cfa (FILE *asm_out_file, rtx pat, rtx insn, gcc_assert (frame_pointer_needed); if (unwind) - fprintf (asm_out_file, "\t.vframe r%d\n", + fprintf (out_file, "\t.vframe r%d\n", ia64_dbx_register_number (REGNO (dest))); } else @@ -10113,7 +10113,7 @@ process_cfa_adjust_cfa (FILE *asm_out_file, rtx pat, rtx insn, /* This function processes a SET pattern for REG_CFA_REGISTER. */ static void -process_cfa_register (FILE *asm_out_file, rtx pat, bool unwind) +process_cfa_register (FILE *out_file, rtx pat, bool unwind) { rtx dest = SET_DEST (pat); rtx src = SET_SRC (pat); @@ -10124,7 +10124,7 @@ process_cfa_register (FILE *asm_out_file, rtx pat, bool unwind) { /* Saving return address pointer. */ if (unwind) - fprintf (asm_out_file, "\t.save rp, r%d\n", + fprintf (out_file, "\t.save rp, r%d\n", ia64_dbx_register_number (dest_regno)); return; } @@ -10136,21 +10136,21 @@ process_cfa_register (FILE *asm_out_file, rtx pat, bool unwind) case PR_REG (0): gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]); if (unwind) - fprintf (asm_out_file, "\t.save pr, r%d\n", + fprintf (out_file, "\t.save pr, r%d\n", ia64_dbx_register_number (dest_regno)); break; case AR_UNAT_REGNUM: gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]); if (unwind) - fprintf (asm_out_file, "\t.save ar.unat, r%d\n", + fprintf (out_file, "\t.save ar.unat, r%d\n", ia64_dbx_register_number (dest_regno)); break; case AR_LC_REGNUM: gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]); if (unwind) - fprintf (asm_out_file, "\t.save ar.lc, r%d\n", + fprintf (out_file, "\t.save ar.lc, r%d\n", ia64_dbx_register_number (dest_regno)); break; @@ -10163,7 +10163,7 @@ process_cfa_register (FILE *asm_out_file, rtx pat, bool unwind) /* This function processes a SET pattern for REG_CFA_OFFSET. */ static void -process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) +process_cfa_offset (FILE *out_file, rtx pat, bool unwind) { rtx dest = SET_DEST (pat); rtx src = SET_SRC (pat); @@ -10203,35 +10203,35 @@ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) case BR_REG (0): gcc_assert (!current_frame_info.r[reg_save_b0]); if (unwind) - fprintf (asm_out_file, "\t%s rp, " HOST_WIDE_INT_PRINT_DEC "\n", + fprintf (out_file, "\t%s rp, " HOST_WIDE_INT_PRINT_DEC "\n", saveop, off); break; case PR_REG (0): gcc_assert (!current_frame_info.r[reg_save_pr]); if (unwind) - fprintf (asm_out_file, "\t%s pr, " HOST_WIDE_INT_PRINT_DEC "\n", + fprintf (out_file, "\t%s pr, " HOST_WIDE_INT_PRINT_DEC "\n", saveop, off); break; case AR_LC_REGNUM: gcc_assert (!current_frame_info.r[reg_save_ar_lc]); if (unwind) - fprintf (asm_out_file, "\t%s ar.lc, " HOST_WIDE_INT_PRINT_DEC "\n", + fprintf (out_file, "\t%s ar.lc, " HOST_WIDE_INT_PRINT_DEC "\n", saveop, off); break; case AR_PFS_REGNUM: gcc_assert (!current_frame_info.r[reg_save_ar_pfs]); if (unwind) - fprintf (asm_out_file, "\t%s ar.pfs, " HOST_WIDE_INT_PRINT_DEC "\n", + fprintf (out_file, "\t%s ar.pfs, " HOST_WIDE_INT_PRINT_DEC "\n", saveop, off); break; case AR_UNAT_REGNUM: gcc_assert (!current_frame_info.r[reg_save_ar_unat]); if (unwind) - fprintf (asm_out_file, "\t%s ar.unat, " HOST_WIDE_INT_PRINT_DEC "\n", + fprintf (out_file, "\t%s ar.unat, " HOST_WIDE_INT_PRINT_DEC "\n", saveop, off); break; @@ -10240,7 +10240,7 @@ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) case GR_REG (6): case GR_REG (7): if (unwind) - fprintf (asm_out_file, "\t.save.g 0x%x\n", + fprintf (out_file, "\t.save.g 0x%x\n", 1 << (src_regno - GR_REG (4))); break; @@ -10250,7 +10250,7 @@ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) case BR_REG (4): case BR_REG (5): if (unwind) - fprintf (asm_out_file, "\t.save.b 0x%x\n", + fprintf (out_file, "\t.save.b 0x%x\n", 1 << (src_regno - BR_REG (1))); break; @@ -10259,7 +10259,7 @@ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) case FR_REG (4): case FR_REG (5): if (unwind) - fprintf (asm_out_file, "\t.save.f 0x%x\n", + fprintf (out_file, "\t.save.f 0x%x\n", 1 << (src_regno - FR_REG (2))); break; @@ -10268,7 +10268,7 @@ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27): case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31): if (unwind) - fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n", + fprintf (out_file, "\t.save.gf 0x0, 0x%x\n", 1 << (src_regno - FR_REG (12))); break; @@ -10283,7 +10283,7 @@ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) required to unwind this insn. */ static void -ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) +ia64_asm_unwind_emit (FILE *out_file, rtx_insn *insn) { bool unwind = ia64_except_unwind_info (&global_options) == UI_TARGET; bool frame = dwarf2out_do_frame (); @@ -10303,8 +10303,8 @@ ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) { if (unwind) { - fprintf (asm_out_file, "\t.body\n"); - fprintf (asm_out_file, "\t.copy_state %d\n", + fprintf (out_file, "\t.body\n"); + fprintf (out_file, "\t.copy_state %d\n", cfun->machine->state_num); } need_copy_state = false; @@ -10325,7 +10325,7 @@ ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) if (dest_regno == current_frame_info.r[reg_save_ar_pfs]) { if (unwind) - fprintf (asm_out_file, "\t.save ar.pfs, r%d\n", + fprintf (out_file, "\t.save ar.pfs, r%d\n", ia64_dbx_register_number (dest_regno)); } else @@ -10338,9 +10338,9 @@ ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) sp" now. */ if (current_frame_info.total_size == 0 && !frame_pointer_needed) /* if haven't done process_epilogue() yet, do it now */ - process_epilogue (asm_out_file, insn, unwind, frame); + process_epilogue (out_file, insn, unwind, frame); if (unwind) - fprintf (asm_out_file, "\t.prologue\n"); + fprintf (out_file, "\t.prologue\n"); } return; } @@ -10353,7 +10353,7 @@ ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) pat = XEXP (note, 0); if (pat == NULL) pat = PATTERN (insn); - process_cfa_adjust_cfa (asm_out_file, pat, insn, unwind, frame); + process_cfa_adjust_cfa (out_file, pat, insn, unwind, frame); handled_one = true; break; @@ -10361,7 +10361,7 @@ ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) pat = XEXP (note, 0); if (pat == NULL) pat = PATTERN (insn); - process_cfa_offset (asm_out_file, pat, unwind); + process_cfa_offset (out_file, pat, unwind); handled_one = true; break; @@ -10369,7 +10369,7 @@ ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) pat = XEXP (note, 0); if (pat == NULL) pat = PATTERN (insn); - process_cfa_register (asm_out_file, pat, unwind); + process_cfa_register (out_file, pat, unwind); handled_one = true; break; diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 93d23715..51a4760 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -145,8 +145,6 @@ UNSPEC_VUPKHU_V4SF UNSPEC_VUPKLU_V4SF UNSPEC_VGBBD - UNSPEC_VMRGH_DIRECT - UNSPEC_VMRGL_DIRECT UNSPEC_VSPLT_DIRECT UNSPEC_VMRGEW_DIRECT UNSPEC_VMRGOW_DIRECT @@ -1101,19 +1099,17 @@ (use (match_operand:V16QI 2 "register_operand"))] "TARGET_ALTIVEC" { - rtvec v = gen_rtvec (16, GEN_INT (0), GEN_INT (16), GEN_INT (1), GEN_INT (17), - GEN_INT (2), GEN_INT (18), GEN_INT (3), GEN_INT (19), - GEN_INT (4), GEN_INT (20), GEN_INT (5), GEN_INT (21), - GEN_INT (6), GEN_INT (22), GEN_INT (7), GEN_INT (23)); - rtx x = gen_rtx_VEC_CONCAT (V32QImode, operands[1], operands[2]); - x = gen_rtx_VEC_SELECT (V16QImode, x, gen_rtx_PARALLEL (VOIDmode, v)); - emit_insn (gen_rtx_SET (operands[0], x)); + rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrghb_direct + : gen_altivec_vmrglb_direct; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); DONE; }) -(define_insn "*altivec_vmrghb_internal" +(define_insn "altivec_vmrghb_direct" [(set (match_operand:V16QI 0 "register_operand" "=v") - (vec_select:V16QI + (vec_select:V16QI (vec_concat:V32QI (match_operand:V16QI 1 "register_operand" "v") (match_operand:V16QI 2 "register_operand" "v")) @@ -1126,20 +1122,6 @@ (const_int 6) (const_int 22) (const_int 7) (const_int 23)])))] "TARGET_ALTIVEC" -{ - if (BYTES_BIG_ENDIAN) - return "vmrghb %0,%1,%2"; - else - return "vmrglb %0,%2,%1"; -} - [(set_attr "type" "vecperm")]) - -(define_insn "altivec_vmrghb_direct" - [(set (match_operand:V16QI 0 "register_operand" "=v") - (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v") - (match_operand:V16QI 2 "register_operand" "v")] - UNSPEC_VMRGH_DIRECT))] - "TARGET_ALTIVEC" "vmrghb %0,%1,%2" [(set_attr "type" "vecperm")]) @@ -1149,16 +1131,15 @@ (use (match_operand:V8HI 2 "register_operand"))] "TARGET_ALTIVEC" { - rtvec v = gen_rtvec (8, GEN_INT (0), GEN_INT (8), GEN_INT (1), GEN_INT (9), - GEN_INT (2), GEN_INT (10), GEN_INT (3), GEN_INT (11)); - rtx x = gen_rtx_VEC_CONCAT (V16HImode, operands[1], operands[2]); - - x = gen_rtx_VEC_SELECT (V8HImode, x, gen_rtx_PARALLEL (VOIDmode, v)); - emit_insn (gen_rtx_SET (operands[0], x)); + rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrghh_direct + : gen_altivec_vmrglh_direct; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); DONE; }) -(define_insn "*altivec_vmrghh_internal" +(define_insn "altivec_vmrghh_direct" [(set (match_operand:V8HI 0 "register_operand" "=v") (vec_select:V8HI (vec_concat:V16HI @@ -1169,20 +1150,6 @@ (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))] "TARGET_ALTIVEC" -{ - if (BYTES_BIG_ENDIAN) - return "vmrghh %0,%1,%2"; - else - return "vmrglh %0,%2,%1"; -} - [(set_attr "type" "vecperm")]) - -(define_insn "altivec_vmrghh_direct" - [(set (match_operand:V8HI 0 "register_operand" "=v") - (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v") - (match_operand:V8HI 2 "register_operand" "v")] - UNSPEC_VMRGH_DIRECT))] - "TARGET_ALTIVEC" "vmrghh %0,%1,%2" [(set_attr "type" "vecperm")]) @@ -1192,35 +1159,23 @@ (use (match_operand:V4SI 2 "register_operand"))] "VECTOR_MEM_ALTIVEC_P (V4SImode)" { - rtvec v = gen_rtvec (4, GEN_INT (0), GEN_INT (4), GEN_INT (1), GEN_INT (5)); - rtx x = gen_rtx_VEC_CONCAT (V8SImode, operands[1], operands[2]); - x = gen_rtx_VEC_SELECT (V4SImode, x, gen_rtx_PARALLEL (VOIDmode, v)); - emit_insn (gen_rtx_SET (operands[0], x)); + rtx (*fun) (rtx, rtx, rtx); + fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrghw_direct_v4si + : gen_altivec_vmrglw_direct_v4si; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); DONE; }) -(define_insn "*altivec_vmrghw_internal" - [(set (match_operand:V4SI 0 "register_operand" "=v") - (vec_select:V4SI - (vec_concat:V8SI - (match_operand:V4SI 1 "register_operand" "v") - (match_operand:V4SI 2 "register_operand" "v")) +(define_insn "altivec_vmrghw_direct_<mode>" + [(set (match_operand:VSX_W 0 "register_operand" "=wa,v") + (vec_select:VSX_W + (vec_concat:<VS_double> + (match_operand:VSX_W 1 "register_operand" "wa,v") + (match_operand:VSX_W 2 "register_operand" "wa,v")) (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))] - "VECTOR_MEM_ALTIVEC_P (V4SImode)" -{ - if (BYTES_BIG_ENDIAN) - return "vmrghw %0,%1,%2"; - else - return "vmrglw %0,%2,%1"; -} - [(set_attr "type" "vecperm")]) - -(define_insn "altivec_vmrghw_direct" - [(set (match_operand:V4SI 0 "register_operand" "=wa,v") - (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "wa,v") - (match_operand:V4SI 2 "register_operand" "wa,v")] - UNSPEC_VMRGH_DIRECT))] "TARGET_ALTIVEC" "@ xxmrghw %x0,%x1,%x2 @@ -1250,19 +1205,17 @@ (use (match_operand:V16QI 2 "register_operand"))] "TARGET_ALTIVEC" { - rtvec v = gen_rtvec (16, GEN_INT (8), GEN_INT (24), GEN_INT (9), GEN_INT (25), - GEN_INT (10), GEN_INT (26), GEN_INT (11), GEN_INT (27), - GEN_INT (12), GEN_INT (28), GEN_INT (13), GEN_INT (29), - GEN_INT (14), GEN_INT (30), GEN_INT (15), GEN_INT (31)); - rtx x = gen_rtx_VEC_CONCAT (V32QImode, operands[1], operands[2]); - x = gen_rtx_VEC_SELECT (V16QImode, x, gen_rtx_PARALLEL (VOIDmode, v)); - emit_insn (gen_rtx_SET (operands[0], x)); + rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrglb_direct + : gen_altivec_vmrghb_direct; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); DONE; }) -(define_insn "*altivec_vmrglb_internal" +(define_insn "altivec_vmrglb_direct" [(set (match_operand:V16QI 0 "register_operand" "=v") - (vec_select:V16QI + (vec_select:V16QI (vec_concat:V32QI (match_operand:V16QI 1 "register_operand" "v") (match_operand:V16QI 2 "register_operand" "v")) @@ -1275,20 +1228,6 @@ (const_int 14) (const_int 30) (const_int 15) (const_int 31)])))] "TARGET_ALTIVEC" -{ - if (BYTES_BIG_ENDIAN) - return "vmrglb %0,%1,%2"; - else - return "vmrghb %0,%2,%1"; -} - [(set_attr "type" "vecperm")]) - -(define_insn "altivec_vmrglb_direct" - [(set (match_operand:V16QI 0 "register_operand" "=v") - (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v") - (match_operand:V16QI 2 "register_operand" "v")] - UNSPEC_VMRGL_DIRECT))] - "TARGET_ALTIVEC" "vmrglb %0,%1,%2" [(set_attr "type" "vecperm")]) @@ -1298,15 +1237,15 @@ (use (match_operand:V8HI 2 "register_operand"))] "TARGET_ALTIVEC" { - rtvec v = gen_rtvec (8, GEN_INT (4), GEN_INT (12), GEN_INT (5), GEN_INT (13), - GEN_INT (6), GEN_INT (14), GEN_INT (7), GEN_INT (15)); - rtx x = gen_rtx_VEC_CONCAT (V16HImode, operands[1], operands[2]); - x = gen_rtx_VEC_SELECT (V8HImode, x, gen_rtx_PARALLEL (VOIDmode, v)); - emit_insn (gen_rtx_SET (operands[0], x)); + rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrglh_direct + : gen_altivec_vmrghh_direct; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); DONE; }) -(define_insn "*altivec_vmrglh_internal" +(define_insn "altivec_vmrglh_direct" [(set (match_operand:V8HI 0 "register_operand" "=v") (vec_select:V8HI (vec_concat:V16HI @@ -1317,20 +1256,6 @@ (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))] "TARGET_ALTIVEC" -{ - if (BYTES_BIG_ENDIAN) - return "vmrglh %0,%1,%2"; - else - return "vmrghh %0,%2,%1"; -} - [(set_attr "type" "vecperm")]) - -(define_insn "altivec_vmrglh_direct" - [(set (match_operand:V8HI 0 "register_operand" "=v") - (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v") - (match_operand:V8HI 2 "register_operand" "v")] - UNSPEC_VMRGL_DIRECT))] - "TARGET_ALTIVEC" "vmrglh %0,%1,%2" [(set_attr "type" "vecperm")]) @@ -1340,35 +1265,23 @@ (use (match_operand:V4SI 2 "register_operand"))] "VECTOR_MEM_ALTIVEC_P (V4SImode)" { - rtvec v = gen_rtvec (4, GEN_INT (2), GEN_INT (6), GEN_INT (3), GEN_INT (7)); - rtx x = gen_rtx_VEC_CONCAT (V8SImode, operands[1], operands[2]); - x = gen_rtx_VEC_SELECT (V4SImode, x, gen_rtx_PARALLEL (VOIDmode, v)); - emit_insn (gen_rtx_SET (operands[0], x)); + rtx (*fun) (rtx, rtx, rtx); + fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrglw_direct_v4si + : gen_altivec_vmrghw_direct_v4si; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); DONE; }) -(define_insn "*altivec_vmrglw_internal" - [(set (match_operand:V4SI 0 "register_operand" "=v") - (vec_select:V4SI - (vec_concat:V8SI - (match_operand:V4SI 1 "register_operand" "v") - (match_operand:V4SI 2 "register_operand" "v")) +(define_insn "altivec_vmrglw_direct_<mode>" + [(set (match_operand:VSX_W 0 "register_operand" "=wa,v") + (vec_select:VSX_W + (vec_concat:<VS_double> + (match_operand:VSX_W 1 "register_operand" "wa,v") + (match_operand:VSX_W 2 "register_operand" "wa,v")) (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))] - "VECTOR_MEM_ALTIVEC_P (V4SImode)" -{ - if (BYTES_BIG_ENDIAN) - return "vmrglw %0,%1,%2"; - else - return "vmrghw %0,%2,%1"; -} - [(set_attr "type" "vecperm")]) - -(define_insn "altivec_vmrglw_direct" - [(set (match_operand:V4SI 0 "register_operand" "=wa,v") - (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "wa,v") - (match_operand:V4SI 2 "register_operand" "wa,v")] - UNSPEC_VMRGL_DIRECT))] "TARGET_ALTIVEC" "@ xxmrglw %x0,%x1,%x2 @@ -3842,13 +3755,13 @@ { emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw_direct (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrghw_direct_v4si (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw_direct (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrghw_direct_v4si (operands[0], vo, ve)); } DONE; }) @@ -3867,13 +3780,13 @@ { emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglw_direct (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrglw_direct_v4si (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglw_direct (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrglw_direct_v4si (operands[0], vo, ve)); } DONE; }) @@ -3892,13 +3805,13 @@ { emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw_direct (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrghw_direct_v4si (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw_direct (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrghw_direct_v4si (operands[0], vo, ve)); } DONE; }) @@ -3917,13 +3830,13 @@ { emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglw_direct (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrglw_direct_v4si (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglw_direct (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrglw_direct_v4si (operands[0], vo, ve)); } DONE; }) diff --git a/gcc/config/rs6000/emmintrin.h b/gcc/config/rs6000/emmintrin.h index ce1287e..32ad72b 100644 --- a/gcc/config/rs6000/emmintrin.h +++ b/gcc/config/rs6000/emmintrin.h @@ -430,20 +430,10 @@ _mm_cmpnge_pd (__m128d __A, __m128d __B) extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_cmpord_pd (__m128d __A, __m128d __B) { -#if _ARCH_PWR8 __v2du c, d; /* Compare against self will return false (0's) if NAN. */ c = (__v2du)vec_cmpeq (__A, __A); d = (__v2du)vec_cmpeq (__B, __B); -#else - __v2du a, b; - __v2du c, d; - const __v2du double_exp_mask = {0x7ff0000000000000, 0x7ff0000000000000}; - a = (__v2du)vec_abs ((__v2df)__A); - b = (__v2du)vec_abs ((__v2df)__B); - c = (__v2du)vec_cmpgt (double_exp_mask, a); - d = (__v2du)vec_cmpgt (double_exp_mask, b); -#endif /* A != NAN and B != NAN. */ return ((__m128d)vec_and(c, d)); } @@ -1472,6 +1462,7 @@ _mm_mul_su32 (__m64 __A, __m64 __B) return ((__m64)a * (__m64)b); } +#ifdef _ARCH_PWR8 extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_mul_epu32 (__m128i __A, __m128i __B) { @@ -1498,6 +1489,7 @@ _mm_mul_epu32 (__m128i __A, __m128i __B) return (__m128i) vec_mule ((__v4su)__A, (__v4su)__B); #endif } +#endif extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_slli_epi16 (__m128i __A, int __B) diff --git a/gcc/config/rs6000/pmmintrin.h b/gcc/config/rs6000/pmmintrin.h index eab712f..83dff1d 100644 --- a/gcc/config/rs6000/pmmintrin.h +++ b/gcc/config/rs6000/pmmintrin.h @@ -123,17 +123,21 @@ _mm_hsub_pd (__m128d __X, __m128d __Y) vec_mergel ((__v2df) __X, (__v2df)__Y)); } +#ifdef _ARCH_PWR8 extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_movehdup_ps (__m128 __X) { return (__m128)vec_mergeo ((__v4su)__X, (__v4su)__X); } +#endif +#ifdef _ARCH_PWR8 extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_moveldup_ps (__m128 __X) { return (__m128)vec_mergee ((__v4su)__X, (__v4su)__X); } +#endif extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_loaddup_pd (double const *__P) diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c index 2eceb2c7..6d8727c 100644 --- a/gcc/config/rs6000/rs6000-call.c +++ b/gcc/config/rs6000/rs6000-call.c @@ -9959,7 +9959,7 @@ altivec_expand_lxvr_builtin (enum insn_code icode, tree exp, rtx target, bool bl if (sign_extend) { - rtx discratch = gen_reg_rtx (DImode); + rtx discratch = gen_reg_rtx (V2DImode); rtx tiscratch = gen_reg_rtx (TImode); /* Emit the lxvr*x insn. */ @@ -9968,20 +9968,31 @@ altivec_expand_lxvr_builtin (enum insn_code icode, tree exp, rtx target, bool bl return 0; emit_insn (pat); - /* Emit a sign extension from QI,HI,WI to double (DI). */ - rtx scratch = gen_lowpart (smode, tiscratch); + /* Emit a sign extension from V16QI,V8HI,V4SI to V2DI. */ + rtx temp1, temp2; if (icode == CODE_FOR_vsx_lxvrbx) - emit_insn (gen_extendqidi2 (discratch, scratch)); + { + temp1 = simplify_gen_subreg (V16QImode, tiscratch, TImode, 0); + emit_insn (gen_vsx_sign_extend_qi_v2di (discratch, temp1)); + } else if (icode == CODE_FOR_vsx_lxvrhx) - emit_insn (gen_extendhidi2 (discratch, scratch)); + { + temp1 = simplify_gen_subreg (V8HImode, tiscratch, TImode, 0); + emit_insn (gen_vsx_sign_extend_hi_v2di (discratch, temp1)); + } else if (icode == CODE_FOR_vsx_lxvrwx) - emit_insn (gen_extendsidi2 (discratch, scratch)); - /* Assign discratch directly if scratch is already DI. */ - if (icode == CODE_FOR_vsx_lxvrdx) - discratch = scratch; + { + temp1 = simplify_gen_subreg (V4SImode, tiscratch, TImode, 0); + emit_insn (gen_vsx_sign_extend_si_v2di (discratch, temp1)); + } + else if (icode == CODE_FOR_vsx_lxvrdx) + discratch = simplify_gen_subreg (V2DImode, tiscratch, TImode, 0); + else + gcc_unreachable (); - /* Emit the sign extension from DI (double) to TI (quad). */ - emit_insn (gen_extendditi2 (target, discratch)); + /* Emit the sign extension from V2DI (double) to TI (quad). */ + temp2 = simplify_gen_subreg (TImode, discratch, V2DImode, 0); + emit_insn (gen_extendditi2_vector (target, temp2)); return target; } diff --git a/gcc/config/rs6000/rs6000-p8swap.c b/gcc/config/rs6000/rs6000-p8swap.c index 6b559aa..0a84072 100644 --- a/gcc/config/rs6000/rs6000-p8swap.c +++ b/gcc/config/rs6000/rs6000-p8swap.c @@ -766,8 +766,6 @@ rtx_is_swappable_p (rtx op, unsigned int *special) default: break; case UNSPEC_VBPERMQ: - case UNSPEC_VMRGH_DIRECT: - case UNSPEC_VMRGL_DIRECT: case UNSPEC_VPACK_SIGN_SIGN_SAT: case UNSPEC_VPACK_SIGN_UNS_SAT: case UNSPEC_VPACK_UNS_UNS_MOD: diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 01a9559..bac959f 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -21626,17 +21626,17 @@ static void rs6000_xcoff_file_end (void) { switch_to_section (text_section); + if (xcoff_tls_exec_model_detected) + { + /* Add a .ref to __tls_get_addr to force libpthread dependency. */ + fputs ("\t.extern __tls_get_addr\n\t.ref __tls_get_addr\n", asm_out_file); + } fputs ("_section_.text:\n", asm_out_file); switch_to_section (data_section); fputs (TARGET_32BIT ? "\t.long _section_.text\n" : "\t.llong _section_.text\n", asm_out_file); - if (xcoff_tls_exec_model_detected) - { - /* Add a .ref to __tls_get_addr to force libpthread dependency. */ - fputs ("\t.extern __tls_get_addr\n\t.ref __tls_get_addr\n", asm_out_file); - } } struct declare_alias_data @@ -23313,43 +23313,44 @@ altivec_expand_vec_perm_const (rtx target, rtx op0, rtx op1, unsigned char perm[16]; }; static const struct altivec_perm_insn patterns[] = { - { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum_direct, - { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 } }, - { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum_direct, - { 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 } }, - { OPTION_MASK_ALTIVEC, - (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghb_direct - : CODE_FOR_altivec_vmrglb_direct), - { 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23 } }, - { OPTION_MASK_ALTIVEC, - (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh_direct - : CODE_FOR_altivec_vmrglh_direct), - { 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23 } }, - { OPTION_MASK_ALTIVEC, - (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghw_direct - : CODE_FOR_altivec_vmrglw_direct), - { 0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23 } }, - { OPTION_MASK_ALTIVEC, - (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglb_direct - : CODE_FOR_altivec_vmrghb_direct), - { 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31 } }, - { OPTION_MASK_ALTIVEC, - (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh_direct - : CODE_FOR_altivec_vmrghh_direct), - { 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31 } }, - { OPTION_MASK_ALTIVEC, - (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglw_direct - : CODE_FOR_altivec_vmrghw_direct), - { 8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31 } }, - { OPTION_MASK_P8_VECTOR, - (BYTES_BIG_ENDIAN ? CODE_FOR_p8_vmrgew_v4sf_direct - : CODE_FOR_p8_vmrgow_v4sf_direct), - { 0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 24, 25, 26, 27 } }, - { OPTION_MASK_P8_VECTOR, - (BYTES_BIG_ENDIAN ? CODE_FOR_p8_vmrgow_v4sf_direct - : CODE_FOR_p8_vmrgew_v4sf_direct), - { 4, 5, 6, 7, 20, 21, 22, 23, 12, 13, 14, 15, 28, 29, 30, 31 } } - }; + {OPTION_MASK_ALTIVEC, + CODE_FOR_altivec_vpkuhum_direct, + {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}}, + {OPTION_MASK_ALTIVEC, + CODE_FOR_altivec_vpkuwum_direct, + {2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31}}, + {OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghb_direct + : CODE_FOR_altivec_vmrglb_direct, + {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}}, + {OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh_direct + : CODE_FOR_altivec_vmrglh_direct, + {0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23}}, + {OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghw_direct_v4si + : CODE_FOR_altivec_vmrglw_direct_v4si, + {0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23}}, + {OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglb_direct + : CODE_FOR_altivec_vmrghb_direct, + {8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31}}, + {OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh_direct + : CODE_FOR_altivec_vmrghh_direct, + {8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31}}, + {OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglw_direct_v4si + : CODE_FOR_altivec_vmrghw_direct_v4si, + {8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31}}, + {OPTION_MASK_P8_VECTOR, + BYTES_BIG_ENDIAN ? CODE_FOR_p8_vmrgew_v4sf_direct + : CODE_FOR_p8_vmrgow_v4sf_direct, + {0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 24, 25, 26, 27}}, + {OPTION_MASK_P8_VECTOR, + BYTES_BIG_ENDIAN ? CODE_FOR_p8_vmrgow_v4sf_direct + : CODE_FOR_p8_vmrgew_v4sf_direct, + {4, 5, 6, 7, 20, 21, 22, 23, 12, 13, 14, 15, 28, 29, 30, 31}}}; unsigned int i, j, elt, which; unsigned char perm[16]; diff --git a/gcc/config/rs6000/smmintrin.h b/gcc/config/rs6000/smmintrin.h index 90ce03d..b732fbc 100644 --- a/gcc/config/rs6000/smmintrin.h +++ b/gcc/config/rs6000/smmintrin.h @@ -96,6 +96,7 @@ _mm_extract_ps (__m128 __X, const int __N) return ((__v4si)__X)[__N & 3]; } +#ifdef _ARCH_PWR8 extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_blend_epi16 (__m128i __A, __m128i __B, const int __imm8) { @@ -107,6 +108,7 @@ _mm_blend_epi16 (__m128i __A, __m128i __B, const int __imm8) #endif return (__m128i) vec_sel ((__v8hu) __A, (__v8hu) __B, __shortmask); } +#endif extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_blendv_epi8 (__m128i __A, __m128i __B, __m128i __mask) @@ -167,6 +169,7 @@ _mm_blend_pd (__m128d __A, __m128d __B, const int __imm8) return (__m128d) __r; } +#ifdef _ARCH_PWR8 __inline __m128d __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm_blendv_pd (__m128d __A, __m128d __B, __m128d __mask) @@ -175,6 +178,7 @@ _mm_blendv_pd (__m128d __A, __m128d __B, __m128d __mask) const __vector __bool long long __boolmask = vec_cmplt ((__v2di) __mask, __zero); return (__m128d) vec_sel ((__v2du) __A, (__v2du) __B, (__v2du) __boolmask); } +#endif __inline int __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) diff --git a/gcc/config/rs6000/tmmintrin.h b/gcc/config/rs6000/tmmintrin.h index 9715112..a67d88c 100644 --- a/gcc/config/rs6000/tmmintrin.h +++ b/gcc/config/rs6000/tmmintrin.h @@ -350,6 +350,7 @@ _mm_shuffle_pi8 (__m64 __A, __m64 __B) return (__m64) ((__v2du) (__C))[0]; } +#ifdef _ARCH_PWR8 extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_sign_epi8 (__m128i __A, __m128i __B) @@ -361,7 +362,9 @@ _mm_sign_epi8 (__m128i __A, __m128i __B) __v16qi __conv = vec_add (__selectneg, __selectpos); return (__m128i) vec_mul ((__v16qi) __A, (__v16qi) __conv); } +#endif +#ifdef _ARCH_PWR8 extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_sign_epi16 (__m128i __A, __m128i __B) @@ -373,7 +376,9 @@ _mm_sign_epi16 (__m128i __A, __m128i __B) __v8hi __conv = vec_add (__selectneg, __selectpos); return (__m128i) vec_mul ((__v8hi) __A, (__v8hi) __conv); } +#endif +#ifdef _ARCH_PWR8 extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_sign_epi32 (__m128i __A, __m128i __B) @@ -385,7 +390,9 @@ _mm_sign_epi32 (__m128i __A, __m128i __B) __v4si __conv = vec_add (__selectneg, __selectpos); return (__m128i) vec_mul ((__v4si) __A, (__v4si) __conv); } +#endif +#ifdef _ARCH_PWR8 extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_sign_pi8 (__m64 __A, __m64 __B) @@ -396,7 +403,9 @@ _mm_sign_pi8 (__m64 __A, __m64 __B) __C = (__v16qi) _mm_sign_epi8 ((__m128i) __C, (__m128i) __D); return (__m64) ((__v2du) (__C))[0]; } +#endif +#ifdef _ARCH_PWR8 extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_sign_pi16 (__m64 __A, __m64 __B) @@ -407,7 +416,9 @@ _mm_sign_pi16 (__m64 __A, __m64 __B) __C = (__v8hi) _mm_sign_epi16 ((__m128i) __C, (__m128i) __D); return (__m64) ((__v2du) (__C))[0]; } +#endif +#ifdef _ARCH_PWR8 extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_sign_pi32 (__m64 __A, __m64 __B) @@ -418,6 +429,7 @@ _mm_sign_pi32 (__m64 __A, __m64 __B) __C = (__v4si) _mm_sign_epi32 ((__m128i) __C, (__m128i) __D); return (__m64) ((__v2du) (__C))[0]; } +#endif extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index bf033e3..346f1a9 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -4688,7 +4688,7 @@ [(set_attr "type" "vecperm")]) ;; V4SF/V4SI interleave -(define_insn "vsx_xxmrghw_<mode>" +(define_expand "vsx_xxmrghw_<mode>" [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa") (vec_select:VSX_W (vec_concat:<VS_double> @@ -4698,14 +4698,17 @@ (const_int 1) (const_int 5)])))] "VECTOR_MEM_VSX_P (<MODE>mode)" { - if (BYTES_BIG_ENDIAN) - return "xxmrghw %x0,%x1,%x2"; - else - return "xxmrglw %x0,%x2,%x1"; + rtx (*fun) (rtx, rtx, rtx); + fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrghw_direct_<mode> + : gen_altivec_vmrglw_direct_<mode>; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); + DONE; } [(set_attr "type" "vecperm")]) -(define_insn "vsx_xxmrglw_<mode>" +(define_expand "vsx_xxmrglw_<mode>" [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa") (vec_select:VSX_W (vec_concat:<VS_double> @@ -4715,10 +4718,13 @@ (const_int 3) (const_int 7)])))] "VECTOR_MEM_VSX_P (<MODE>mode)" { - if (BYTES_BIG_ENDIAN) - return "xxmrglw %x0,%x1,%x2"; - else - return "xxmrghw %x0,%x2,%x1"; + rtx (*fun) (rtx, rtx, rtx); + fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrglw_direct_<mode> + : gen_altivec_vmrghw_direct_<mode>; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); + DONE; } [(set_attr "type" "vecperm")]) diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 85dd78c..b2f2f64 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -7808,7 +7808,7 @@ s390_asm_declare_function_size (FILE *asm_out_file, /* Write the extra assembler code needed to declare a function properly. */ void -s390_asm_output_function_label (FILE *asm_out_file, const char *fname, +s390_asm_output_function_label (FILE *out_file, const char *fname, tree decl) { int hw_before, hw_after; @@ -7822,11 +7822,11 @@ s390_asm_output_function_label (FILE *asm_out_file, const char *fname, /* Add a trampoline code area before the function label and initialize it with two-byte nop instructions. This area can be overwritten with code that jumps to a patched version of the function. */ - asm_fprintf (asm_out_file, "\tnopr\t%%r0" + asm_fprintf (out_file, "\tnopr\t%%r0" "\t# pre-label NOPs for hotpatch (%d halfwords)\n", hw_before); for (i = 1; i < hw_before; i++) - fputs ("\tnopr\t%r0\n", asm_out_file); + fputs ("\tnopr\t%r0\n", out_file); /* Note: The function label must be aligned so that (a) the bytes of the following nop do not cross a cacheline boundary, and (b) a jump address @@ -7843,35 +7843,35 @@ s390_asm_output_function_label (FILE *asm_out_file, const char *fname, function_alignment = MAX (function_alignment, (unsigned int) align_functions.levels[0].get_value ()); - fputs ("\t# alignment for hotpatch\n", asm_out_file); - ASM_OUTPUT_ALIGN (asm_out_file, align_functions.levels[0].log); + fputs ("\t# alignment for hotpatch\n", out_file); + ASM_OUTPUT_ALIGN (out_file, align_functions.levels[0].log); } if (S390_USE_TARGET_ATTRIBUTE && TARGET_DEBUG_ARG) { - asm_fprintf (asm_out_file, "\t# fn:%s ar%d\n", fname, s390_arch); - asm_fprintf (asm_out_file, "\t# fn:%s tu%d\n", fname, s390_tune); - asm_fprintf (asm_out_file, "\t# fn:%s sg%d\n", fname, s390_stack_guard); - asm_fprintf (asm_out_file, "\t# fn:%s ss%d\n", fname, s390_stack_size); - asm_fprintf (asm_out_file, "\t# fn:%s bc%d\n", fname, s390_branch_cost); - asm_fprintf (asm_out_file, "\t# fn:%s wf%d\n", fname, + asm_fprintf (out_file, "\t# fn:%s ar%d\n", fname, s390_arch); + asm_fprintf (out_file, "\t# fn:%s tu%d\n", fname, s390_tune); + asm_fprintf (out_file, "\t# fn:%s sg%d\n", fname, s390_stack_guard); + asm_fprintf (out_file, "\t# fn:%s ss%d\n", fname, s390_stack_size); + asm_fprintf (out_file, "\t# fn:%s bc%d\n", fname, s390_branch_cost); + asm_fprintf (out_file, "\t# fn:%s wf%d\n", fname, s390_warn_framesize); - asm_fprintf (asm_out_file, "\t# fn:%s ba%d\n", fname, TARGET_BACKCHAIN); - asm_fprintf (asm_out_file, "\t# fn:%s hd%d\n", fname, TARGET_HARD_DFP); - asm_fprintf (asm_out_file, "\t# fn:%s hf%d\n", fname, !TARGET_SOFT_FLOAT); - asm_fprintf (asm_out_file, "\t# fn:%s ht%d\n", fname, TARGET_OPT_HTM); - asm_fprintf (asm_out_file, "\t# fn:%s vx%d\n", fname, TARGET_OPT_VX); - asm_fprintf (asm_out_file, "\t# fn:%s ps%d\n", fname, + asm_fprintf (out_file, "\t# fn:%s ba%d\n", fname, TARGET_BACKCHAIN); + asm_fprintf (out_file, "\t# fn:%s hd%d\n", fname, TARGET_HARD_DFP); + asm_fprintf (out_file, "\t# fn:%s hf%d\n", fname, !TARGET_SOFT_FLOAT); + asm_fprintf (out_file, "\t# fn:%s ht%d\n", fname, TARGET_OPT_HTM); + asm_fprintf (out_file, "\t# fn:%s vx%d\n", fname, TARGET_OPT_VX); + asm_fprintf (out_file, "\t# fn:%s ps%d\n", fname, TARGET_PACKED_STACK); - asm_fprintf (asm_out_file, "\t# fn:%s se%d\n", fname, TARGET_SMALL_EXEC); - asm_fprintf (asm_out_file, "\t# fn:%s mv%d\n", fname, TARGET_MVCLE); - asm_fprintf (asm_out_file, "\t# fn:%s zv%d\n", fname, TARGET_ZVECTOR); - asm_fprintf (asm_out_file, "\t# fn:%s wd%d\n", fname, + asm_fprintf (out_file, "\t# fn:%s se%d\n", fname, TARGET_SMALL_EXEC); + asm_fprintf (out_file, "\t# fn:%s mv%d\n", fname, TARGET_MVCLE); + asm_fprintf (out_file, "\t# fn:%s zv%d\n", fname, TARGET_ZVECTOR); + asm_fprintf (out_file, "\t# fn:%s wd%d\n", fname, s390_warn_dynamicstack_p); } - ASM_OUTPUT_LABEL (asm_out_file, fname); + ASM_OUTPUT_LABEL (out_file, fname); if (hw_after > 0) - asm_fprintf (asm_out_file, + asm_fprintf (out_file, "\t# post-label NOPs for hotpatch (%d halfwords)\n", hw_after); } diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ffdb690..08ba25e1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,27 @@ +2021-10-20 Jason Merrill <jason@redhat.com> + + * parser.c (cp_parser_parse_and_diagnose_invalid_type_name): + Pass true for declarator_p. + (cp_parser_nested_name_specifier_opt): Only look through + TYPENAME_TYPE if check_dependency_p is false. + +2021-10-20 Jakub Jelinek <jakub@redhat.com> + + PR c++/102642 + * name-lookup.c (push_local_extern_decl_alias): Don't call + set_decl_tls_model on error_mark_node. + * decl.c (make_rtl_for_nonlocal_decl): Don't call + set_user_assembler_name on error_mark_node. + * parser.c (cp_parser_oacc_declare): Ignore DECL_LOCAL_DECL_ALIAS + if it is error_mark_node. + (cp_parser_omp_declare_target): Likewise. + +2021-10-19 Jakub Jelinek <jakub@redhat.com> + + PR c++/102786 + * constexpr.c (cxx_eval_constant_expression): Don't reject + INTEGER_CSTs with type POINTER_TYPE to METHOD_TYPE. + 2021-10-15 Jason Merrill <jason@redhat.com> PR c++/51851 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index c5f01b9..6f83d30 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -6191,6 +6191,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (TREE_CODE (t) == INTEGER_CST && TYPE_PTR_P (TREE_TYPE (t)) + /* INTEGER_CST with pointer-to-method type is only used + for a virtual method in a pointer to member function. + Don't reject those. */ + && TREE_CODE (TREE_TYPE (TREE_TYPE (t))) != METHOD_TYPE && !integer_zerop (t)) { if (!ctx->quiet) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 242429d..8a45411 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7373,7 +7373,8 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec) This is horrible, as we're affecting a possibly-shared decl. Again, a one-true-decl model breaks down. */ - set_user_assembler_name (ns_decl, asmspec); + if (ns_decl != error_mark_node) + set_user_assembler_name (ns_decl, asmspec); } } diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index c414a10..035bcf5 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3474,7 +3474,9 @@ push_local_extern_decl_alias (tree decl) push_nested_namespace (ns); alias = do_pushdecl (alias, /* hiding= */true); pop_nested_namespace (ns); - if (VAR_P (decl) && CP_DECL_THREAD_LOCAL_P (decl)) + if (VAR_P (decl) + && CP_DECL_THREAD_LOCAL_P (decl) + && alias != error_mark_node) set_decl_tls_model (alias, DECL_TLS_MODEL (decl)); } } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 865778e..49d951c 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -3693,7 +3693,7 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser) /*template_keyword_p=*/false, /*check_dependency_p=*/true, /*template_p=*/NULL, - /*declarator_p=*/false, + /*declarator_p=*/true, /*optional_p=*/false); /* If the next token is a (, this is a function with no explicit return type, i.e. constructor, destructor or conversion op. */ @@ -6605,6 +6605,8 @@ check_template_keyword_in_nested_name_spec (tree name) it unchanged if there is no nested-name-specifier. Returns the new scope iff there is a nested-name-specifier, or NULL_TREE otherwise. + If CHECK_DEPENDENCY_P is FALSE, names are looked up in dependent scopes. + If IS_DECLARATION is TRUE, the nested-name-specifier is known to be part of a declaration and/or decl-specifier. */ @@ -6645,9 +6647,10 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, /* Grab the nested-name-specifier and continue the loop. */ cp_parser_pre_parsed_nested_name_specifier (parser); /* If we originally encountered this nested-name-specifier - with IS_DECLARATION set to false, we will not have + with CHECK_DEPENDENCY_P set to true, we will not have resolved TYPENAME_TYPEs, so we must do so here. */ if (is_declaration + && !check_dependency_p && TREE_CODE (parser->scope) == TYPENAME_TYPE) { new_scope = resolve_typename_type (parser->scope, @@ -6729,6 +6732,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, a template. So, if we have a typename at this point, we make an effort to look through it. */ if (is_declaration + && !check_dependency_p && !typename_keyword_p && parser->scope && TREE_CODE (parser->scope) == TYPENAME_TYPE) @@ -44437,7 +44441,8 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok) dependent local extern variable decls are as rare as hen's teeth. */ if (auto alias = DECL_LOCAL_DECL_ALIAS (decl)) - decl = alias; + if (alias != error_mark_node) + decl = alias; if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK) id = get_identifier ("omp declare target link"); @@ -45665,7 +45670,8 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) if (VAR_OR_FUNCTION_DECL_P (t) && DECL_LOCAL_DECL_P (t) && DECL_LANG_SPECIFIC (t) - && DECL_LOCAL_DECL_ALIAS (t)) + && DECL_LOCAL_DECL_ALIAS (t) + && DECL_LOCAL_DECL_ALIAS (t) != error_mark_node) handle_omp_declare_target_clause (c, DECL_LOCAL_DECL_ALIAS (t), device_type); } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 2b18155..171b7a8 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -9723,10 +9723,12 @@ A basic @code{asm} statement has the following syntax: asm @var{asm-qualifiers} ( @var{AssemblerInstructions} ) @end example -The @code{asm} keyword is a GNU extension. -When writing code that can be compiled with @option{-ansi} and the -various @option{-std} options, use @code{__asm__} instead of -@code{asm} (@pxref{Alternate Keywords}). +For the C language, the @code{asm} keyword is a GNU extension. +When writing C code that can be compiled with @option{-ansi} and the +@option{-std} options that select C dialects without GNU extensions, use +@code{__asm__} instead of @code{asm} (@pxref{Alternate Keywords}). For +the C++ language, @code{asm} is a standard keyword, but @code{__asm__} +can be used for code compiled with @option{-fno-asm}. @subsubheading Qualifiers @table @code @@ -17693,7 +17695,7 @@ macro @code{__BUILTIN_CPU_SUPPORTS__} if the @code{__builtin_cpu_supports} built-in function is fully supported. If GCC was configured to use a GLIBC before 2.23, the built-in -function @code{__builtin_cpu_suports} always returns a 0 and the +function @code{__builtin_cpu_supports} always returns a 0 and the compiler issues a warning. The following features can be diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index cdfbfdd..4f60e48 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -195,12 +195,6 @@ remove that directory when you do not need that specific version of GCC any longer, and, if shared libraries are installed there as well, no more binaries exist that use them. -@ifhtml -There are also some @uref{old.html,,old installation instructions}, -which are mostly obsolete but still contain some information which has -not yet been merged into the main part of this manual. -@end ifhtml - @html <hr /> <p> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 3663c2b..acfa766 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -2448,14 +2448,14 @@ supported for C as this construct is allowed by C++. Do not recognize @code{asm}, @code{inline} or @code{typeof} as a keyword, so that code can use these words as identifiers. You can use the keywords @code{__asm__}, @code{__inline__} and @code{__typeof__} -instead. @option{-ansi} implies @option{-fno-asm}. +instead. In C, @option{-ansi} implies @option{-fno-asm}. -In C++, this switch only affects the @code{typeof} keyword, since -@code{asm} and @code{inline} are standard keywords. You may want to -use the @option{-fno-gnu-keywords} flag instead, which has the same -effect. In C99 mode (@option{-std=c99} or @option{-std=gnu99}), this -switch only affects the @code{asm} and @code{typeof} keywords, since -@code{inline} is a standard keyword in ISO C99. +In C++, @code{inline} is a standard keyword and is not affected by +this switch. You may want to use the @option{-fno-gnu-keywords} flag +instead, which disables @code{typeof} but not @code{asm} and +@code{inline}. In C99 mode (@option{-std=c99} or @option{-std=gnu99}), +this switch only affects the @code{asm} and @code{typeof} keywords, +since @code{inline} is a standard keyword in ISO C99. @item -fno-builtin @itemx -fno-builtin-@var{function} @@ -14431,6 +14431,9 @@ Emit instrumentation calls to __tsan_func_entry() and __tsan_func_exit(). Maximum number of instructions to copy when duplicating blocks on a finite state automaton jump thread path. +@item max-fsm-thread-length +Maximum number of basic blocks on a jump thread path. + @item parloops-chunk-size Chunk size of omp schedule for loops parallelized by parloops. diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index b1fffd5..6a16576 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -1845,6 +1845,38 @@ Target supports loop vectorization with partial vectors and @item vect_partial_vectors Target supports loop vectorization with partial vectors and @code{vect-partial-vector-usage} is nonzero. + +@item vect_slp_v2qi_store +Target supports vectorization of 2-byte char stores with 2-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v4qi_store +Target supports vectorization of 4-byte char stores with 4-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v8qi_store +Target supports vectorization of 8-byte char stores with 8-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v16qi_store +Target supports vectorization of 16-byte char stores with 16-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v2hi_store +Target supports vectorization of 4-byte short stores with 4-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v4hi_store +Target supports vectorization of 8-byte short stores with 8-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v2si_store +Target supports vectorization of 8-byte int stores with 8-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v4si_store +Target supports vectorization of 16-byte int stores with 16-byte aligned +address at plain @option{-O2}. @end table @subsubsection Thread Local Storage attributes diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 9649695..fa66a09 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -4230,12 +4230,6 @@ The return value is usually either a @code{reg} RTX for the hard register in which to pass the argument, or zero to pass the argument on the stack. -The return value can be a @code{const_int} which means argument is -passed in a target specific slot with specified number. Target hooks -should be used to store or load argument in such case. See -@code{TARGET_STORE_BOUNDS_FOR_ARG} and @code{TARGET_LOAD_BOUNDS_FOR_ARG} -for more information. - The value of the expression can also be a @code{parallel} RTX@. This is used when an argument is passed in multiple locations. The mode of the @code{parallel} should be the mode of the entire argument. The @@ -5724,45 +5718,6 @@ Otherwise, you should not define this hook. @end deftypefn @c hook-end -@deftypefn {Target Hook} rtx TARGET_LOAD_BOUNDS_FOR_ARG (rtx @var{slot}, rtx @var{arg}, rtx @var{slot_no}) -@c hook-start:TARGET_LOAD_BOUNDS_FOR_ARG -This hook is used by expand pass to emit insn to load bounds of -@var{arg} passed in @var{slot}. Expand pass uses this hook in case -bounds of @var{arg} are not passed in register. If @var{slot} is a -memory, then bounds are loaded as for regular pointer loaded from -memory. If @var{slot} is not a memory then @var{slot_no} is an integer -constant holding number of the target dependent special slot which -should be used to obtain bounds. Hook returns RTX holding loaded bounds. -@end deftypefn -@c hook-end - -@deftypefn {Target Hook} void TARGET_STORE_BOUNDS_FOR_ARG (rtx @var{arg}, rtx @var{slot}, rtx @var{bounds}, rtx @var{slot_no}) -@c hook-start:TARGET_STORE_BOUNDS_FOR_ARG -This hook is used by expand pass to emit insns to store @var{bounds} of -@var{arg} passed in @var{slot}. Expand pass uses this hook in case -@var{bounds} of @var{arg} are not passed in register. If @var{slot} is a -memory, then @var{bounds} are stored as for regular pointer stored in -memory. If @var{slot} is not a memory then @var{slot_no} is an integer -constant holding number of the target dependent special slot which -should be used to store @var{bounds}. -@end deftypefn -@c hook-end - -@deftypefn {Target Hook} rtx TARGET_LOAD_RETURNED_BOUNDS (rtx @var{slot}) -@c hook-start:TARGET_LOAD_RETURNED_BOUNDS -This hook is used by expand pass to emit insn to load bounds -returned by function call in @var{slot}. Hook returns RTX holding -loaded bounds. -@end deftypefn -@c hook-end - -@deftypefn {Target Hook} void TARGET_STORE_RETURNED_BOUNDS (rtx @var{slot}, rtx @var{bounds}) -@c hook-start:TARGET_STORE_RETURNED_BOUNDS -This hook is used by expand pass to emit insn to store @var{bounds} -returned by function call into @var{slot}. -@end deftypefn -@c hook-end - @node Trampolines @section Support for Nested Functions @cindex support for nested functions diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 86352dc..193c9bd 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -3780,14 +3780,6 @@ These machine description macros help implement varargs: @hook TARGET_PRETEND_OUTGOING_VARARGS_NAMED -@hook TARGET_LOAD_BOUNDS_FOR_ARG - -@hook TARGET_STORE_BOUNDS_FOR_ARG - -@hook TARGET_LOAD_RETURNED_BOUNDS - -@hook TARGET_STORE_RETURNED_BOUNDS - @node Trampolines @section Support for Nested Functions @cindex support for nested functions diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 2d3d33a..f75b880 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,104 @@ +2021-10-20 Chung-Lin Tang <cltang@codesourcery.com> + + * openmp.c (gfc_match_omp_clause_reduction): Add 'openmp_target' default + false parameter. Add 'always,tofrom' map for OMP_LIST_IN_REDUCTION case. + (gfc_match_omp_clauses): Add 'openmp_target' default false parameter, + adjust call to gfc_match_omp_clause_reduction. + (match_omp): Adjust call to gfc_match_omp_clauses + * trans-openmp.c (gfc_trans_omp_taskgroup): Add call to + gfc_match_omp_clause, create and return block. + +2021-10-19 Tobias Burnus <tobias@codesourcery.com> + + * trans-types.c (create_fn_spec): For allocatable/pointer + character(len=:), use 'w' not 'R' as fn spec for the length dummy + argument. + +2021-10-19 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/92482 + * trans-expr.c (gfc_conv_procedure_call): Use TREE_OPERAND not + build_fold_indirect_ref_loc to undo an ADDR_EXPR. + +2021-10-18 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/102086 + PR fortran/92189 + PR fortran/92621 + PR fortran/101308 + PR fortran/101309 + PR fortran/101635 + PR fortran/92482 + * decl.c (gfc_verify_c_interop_param): Remove 'sorry' for + scalar allocatable/pointer and len=*. + * expr.c (is_CFI_desc): Return true for for those. + * gfortran.h (CFI_type_kind_shift, CFI_type_mask, + CFI_type_from_type_kind, CFI_VERSION, CFI_MAX_RANK, + CFI_attribute_pointer, CFI_attribute_allocatable, + CFI_attribute_other, CFI_type_Integer, CFI_type_Logical, + CFI_type_Real, CFI_type_Complex, CFI_type_Character, + CFI_type_ucs4_char, CFI_type_struct, CFI_type_cptr, + CFI_type_cfunptr, CFI_type_other): New #define. + * trans-array.c (CFI_FIELD_BASE_ADDR, CFI_FIELD_ELEM_LEN, + CFI_FIELD_VERSION, CFI_FIELD_RANK, CFI_FIELD_ATTRIBUTE, + CFI_FIELD_TYPE, CFI_FIELD_DIM, CFI_DIM_FIELD_LOWER_BOUND, + CFI_DIM_FIELD_EXTENT, CFI_DIM_FIELD_SM, + gfc_get_cfi_descriptor_field, gfc_get_cfi_desc_base_addr, + gfc_get_cfi_desc_elem_len, gfc_get_cfi_desc_version, + gfc_get_cfi_desc_rank, gfc_get_cfi_desc_type, + gfc_get_cfi_desc_attribute, gfc_get_cfi_dim_item, + gfc_get_cfi_dim_lbound, gfc_get_cfi_dim_extent, gfc_get_cfi_dim_sm): + New define/functions to access the CFI array descriptor. + (gfc_conv_descriptor_type): New function for the GFC descriptor. + (gfc_get_array_span): Handle expr of CFI descriptors and + assumed-type descriptors. + (gfc_trans_array_bounds): Remove 'static'. + (gfc_conv_expr_descriptor): For assumed type, use the dtype of + the actual argument. + (structure_alloc_comps): Remove ' ' inside tabs. + * trans-array.h (gfc_trans_array_bounds, gfc_conv_descriptor_type, + gfc_get_cfi_desc_base_addr, gfc_get_cfi_desc_elem_len, + gfc_get_cfi_desc_version, gfc_get_cfi_desc_rank, + gfc_get_cfi_desc_type, gfc_get_cfi_desc_attribute, + gfc_get_cfi_dim_lbound, gfc_get_cfi_dim_extent, gfc_get_cfi_dim_sm): + New prototypes. + * trans-decl.c (gfor_fndecl_cfi_to_gfc, gfor_fndecl_gfc_to_cfi): + Remove global vars. + (gfc_build_builtin_function_decls): Remove their initialization. + (gfc_get_symbol_decl, create_function_arglist, + gfc_trans_deferred_vars): Update for CFI. + (convert_CFI_desc): Remove and replace by ... + (gfc_conv_cfi_to_gfc): ... this function + (gfc_generate_function_code): Call it; create local GFC var for CFI. + * trans-expr.c (gfc_maybe_dereference_var): Handle CFI. + (gfc_conv_subref_array_arg): Handle the if-noncontigous-only copy in + when the result should be a descriptor. + (gfc_conv_gfc_desc_to_cfi_desc): Completely rewritten. + (gfc_conv_procedure_call): CFI fixes. + * trans-openmp.c (gfc_omp_is_optional_argument, + gfc_omp_check_optional_argument): Handle optional + CFI. + * trans-stmt.c (gfc_trans_select_rank_cases): Cleanup, avoid invalid + code for allocatable/pointer dummies, which cannot be assumed size. + * trans-types.c (gfc_cfi_descriptor_base): New global var. + (gfc_get_dtype_rank_type): Skip rank init for rank < 0. + (gfc_sym_type): Handle CFI dummies. + (gfc_get_function_type): Update call. + (gfc_get_cfi_dim_type, gfc_get_cfi_type): New. + * trans-types.h (gfc_sym_type): Update prototype. + (gfc_get_cfi_type): New prototype. + * trans.c (gfc_trans_runtime_check): Make conditions more consistent + to avoid '<logical> AND_THEN <long int>' in conditions. + * trans.h (gfor_fndecl_cfi_to_gfc, gfor_fndecl_gfc_to_cfi): Remove + global-var declaration. + +2021-10-18 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/102745 + * intrinsic.c (gfc_convert_type_warn): Fix checks by checking CLASS + and do typcheck in correct order for type extension. + * misc.c (gfc_typename): Print proper not internal CLASS type name. + 2021-10-15 Harald Anlauf <anlauf@gmx.de> Tobias Burnus <tobias@codesourcery.com> diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 6784b07..6043e10 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -8429,6 +8429,7 @@ gfc_match_end (gfc_statement *st) break; case COMP_BLOCK: + case COMP_OMP_STRICTLY_STRUCTURED_BLOCK: *st = ST_END_BLOCK; target = " block"; eos_ok = 0; diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index 66f24c6..b19d3a2 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -2205,7 +2205,8 @@ gfc_simplify_expr (gfc_expr *p, int type) (p->value.function.isym->id == GFC_ISYM_LBOUND || p->value.function.isym->id == GFC_ISYM_UBOUND || p->value.function.isym->id == GFC_ISYM_LCOBOUND - || p->value.function.isym->id == GFC_ISYM_UCOBOUND)) + || p->value.function.isym->id == GFC_ISYM_UCOBOUND + || p->value.function.isym->id == GFC_ISYM_SHAPE)) ap = ap->next; for ( ; ap; ap = ap->next) diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c index 2a161f3..dcf22ac 100644 --- a/gcc/fortran/openmp.c +++ b/gcc/fortran/openmp.c @@ -1202,7 +1202,7 @@ failed: static match gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc, - bool allow_derived) + bool allow_derived, bool openmp_target = false) { if (pc == 'r' && gfc_match ("reduction ( ") != MATCH_YES) return MATCH_NO; @@ -1349,6 +1349,19 @@ gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc, n->u2.udr = gfc_get_omp_namelist_udr (); n->u2.udr->udr = udr; } + if (openmp_target && list_idx == OMP_LIST_IN_REDUCTION) + { + gfc_omp_namelist *p = gfc_get_omp_namelist (), **tl; + p->sym = n->sym; + p->where = p->where; + p->u.map_op = OMP_MAP_ALWAYS_TOFROM; + + tl = &c->lists[OMP_LIST_MAP]; + while (*tl) + tl = &((*tl)->next); + *tl = p; + p->next = NULL; + } } return MATCH_YES; } @@ -1417,7 +1430,8 @@ gfc_match_dupl_atomic (bool not_dupl, const char *name) static match gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, bool first = true, bool needs_space = true, - bool openacc = false, bool context_selector = false) + bool openacc = false, bool context_selector = false, + bool openmp_target = false) { bool error = false; gfc_omp_clauses *c = gfc_get_omp_clauses (); @@ -2121,8 +2135,8 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, goto error; } if ((mask & OMP_CLAUSE_IN_REDUCTION) - && gfc_match_omp_clause_reduction (pc, c, openacc, - allow_derived) == MATCH_YES) + && gfc_match_omp_clause_reduction (pc, c, openacc, allow_derived, + openmp_target) == MATCH_YES) continue; if ((mask & OMP_CLAUSE_INBRANCH) && (m = gfc_match_dupl_check (!c->inbranch && !c->notinbranch, @@ -3578,7 +3592,8 @@ static match match_omp (gfc_exec_op op, const omp_mask mask) { gfc_omp_clauses *c; - if (gfc_match_omp_clauses (&c, mask) != MATCH_YES) + if (gfc_match_omp_clauses (&c, mask, true, true, false, false, + op == EXEC_OMP_TARGET) != MATCH_YES) return MATCH_ERROR; new_st.op = op; new_st.ext.omp_clauses = c; diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 2a454be..b1e73ee 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -5459,7 +5459,7 @@ parse_oacc_loop (gfc_statement acc_st) /* Parse the statements of an OpenMP structured block. */ -static void +static gfc_statement parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) { gfc_statement st, omp_end_st; @@ -5546,6 +5546,32 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) gcc_unreachable (); } + bool block_construct = false; + gfc_namespace *my_ns = NULL; + gfc_namespace *my_parent = NULL; + + st = next_statement (); + + if (st == ST_BLOCK) + { + /* Adjust state to a strictly-structured block, now that we found that + the body starts with a BLOCK construct. */ + s.state = COMP_OMP_STRICTLY_STRUCTURED_BLOCK; + + block_construct = true; + gfc_notify_std (GFC_STD_F2008, "BLOCK construct at %C"); + + my_ns = gfc_build_block_ns (gfc_current_ns); + gfc_current_ns = my_ns; + my_parent = my_ns->parent; + + new_st.op = EXEC_BLOCK; + new_st.ext.block.ns = my_ns; + new_st.ext.block.assoc = NULL; + accept_statement (ST_BLOCK); + st = parse_spec (ST_NONE); + } + do { if (workshare_stmts_only) @@ -5562,7 +5588,6 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) restrictions apply recursively. */ bool cycle = true; - st = next_statement (); for (;;) { switch (st) @@ -5588,13 +5613,13 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) case ST_OMP_PARALLEL_MASKED: case ST_OMP_PARALLEL_MASTER: case ST_OMP_PARALLEL_SECTIONS: - parse_omp_structured_block (st, false); - break; + st = parse_omp_structured_block (st, false); + continue; case ST_OMP_PARALLEL_WORKSHARE: case ST_OMP_CRITICAL: - parse_omp_structured_block (st, true); - break; + st = parse_omp_structured_block (st, true); + continue; case ST_OMP_PARALLEL_DO: case ST_OMP_PARALLEL_DO_SIMD: @@ -5617,7 +5642,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) } } else - st = parse_executable (ST_NONE); + st = parse_executable (st); if (st == ST_NONE) unexpected_eof (); else if (st == ST_OMP_SECTION @@ -5627,9 +5652,27 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) np = new_level (np); np->op = cp->op; np->block = NULL; + st = next_statement (); + } + else if (block_construct && st == ST_END_BLOCK) + { + accept_statement (st); + gfc_current_ns = my_parent; + pop_state (); + + st = next_statement (); + if (st == omp_end_st) + { + accept_statement (st); + st = next_statement (); + } + return st; } else if (st != omp_end_st) - unexpected_statement (st); + { + unexpected_statement (st); + st = next_statement (); + } } while (st != omp_end_st); @@ -5665,6 +5708,8 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) gfc_commit_symbols (); gfc_warning_check (); pop_state (); + st = next_statement (); + return st; } @@ -5805,13 +5850,13 @@ parse_executable (gfc_statement st) case ST_OMP_TEAMS: case ST_OMP_TASK: case ST_OMP_TASKGROUP: - parse_omp_structured_block (st, false); - break; + st = parse_omp_structured_block (st, false); + continue; case ST_OMP_WORKSHARE: case ST_OMP_PARALLEL_WORKSHARE: - parse_omp_structured_block (st, true); - break; + st = parse_omp_structured_block (st, true); + continue; case ST_OMP_DISTRIBUTE: case ST_OMP_DISTRIBUTE_PARALLEL_DO: diff --git a/gcc/fortran/parse.h b/gcc/fortran/parse.h index 55f0229..66b275d 100644 --- a/gcc/fortran/parse.h +++ b/gcc/fortran/parse.h @@ -31,7 +31,7 @@ enum gfc_compile_state COMP_STRUCTURE, COMP_UNION, COMP_MAP, COMP_DO, COMP_SELECT, COMP_FORALL, COMP_WHERE, COMP_CONTAINS, COMP_ENUM, COMP_SELECT_TYPE, COMP_SELECT_RANK, COMP_OMP_STRUCTURED_BLOCK, COMP_CRITICAL, - COMP_DO_CONCURRENT + COMP_DO_CONCURRENT, COMP_OMP_STRICTLY_STRUCTURED_BLOCK }; /* Stack element for the current compilation state. These structures diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index f8c087e..bceb8b2 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -4507,6 +4507,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop) case GFC_ISYM_UBOUND: case GFC_ISYM_LCOBOUND: case GFC_ISYM_UCOBOUND: + case GFC_ISYM_SHAPE: case GFC_ISYM_THIS_IMAGE: loop->dimen = ss->dimen; goto done; @@ -4558,12 +4559,14 @@ done: /* Fall through to supply start and stride. */ case GFC_ISYM_LBOUND: case GFC_ISYM_UBOUND: + /* This is the variant without DIM=... */ + gcc_assert (expr->value.function.actual->next->expr == NULL); + /* Fall through. */ + + case GFC_ISYM_SHAPE: { gfc_expr *arg; - /* This is the variant without DIM=... */ - gcc_assert (expr->value.function.actual->next->expr == NULL); - arg = expr->value.function.actual->expr; if (arg->rank == -1) { @@ -5350,10 +5353,13 @@ set_loop_bounds (gfc_loopinfo *loop) gfc_expr *expr = loopspec[n]->info->expr; /* The {l,u}bound of an assumed rank. */ - gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND - || expr->value.function.isym->id == GFC_ISYM_UBOUND) - && expr->value.function.actual->next->expr == NULL - && expr->value.function.actual->expr->rank == -1); + if (expr->value.function.isym->id == GFC_ISYM_SHAPE) + gcc_assert (expr->value.function.actual->expr->rank == -1); + else + gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND + || expr->value.function.isym->id == GFC_ISYM_UBOUND) + && expr->value.function.actual->next->expr == NULL + && expr->value.function.actual->expr->rank == -1); loop->to[n] = info->end[dim]; break; diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 0138937..29697e6 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -6640,7 +6640,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, { tmp = parmse.expr; if (TREE_CODE (tmp) == ADDR_EXPR) - tmp = build_fold_indirect_ref_loc (input_location, tmp); + tmp = TREE_OPERAND (tmp, 0); parmse.expr = gfc_conv_scalar_to_descriptor (&parmse, tmp, fsym->attr); parmse.expr = gfc_build_addr_expr (NULL_TREE, diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 2a2829c..0d91958 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -2922,7 +2922,7 @@ gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg) /* TODO: bound intrinsic generates way too much unnecessary code. */ static void -gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) +gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, enum gfc_isym_id op) { gfc_actual_arglist *arg; gfc_actual_arglist *arg2; @@ -2930,9 +2930,10 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) tree type; tree bound; tree tmp; - tree cond, cond1, cond3, cond4, size; + tree cond, cond1; tree ubound; tree lbound; + tree size; gfc_se argse; gfc_array_spec * as; bool assumed_rank_lb_one; @@ -2943,7 +2944,7 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) if (se->ss) { /* Create an implicit second parameter from the loop variable. */ - gcc_assert (!arg2->expr); + gcc_assert (!arg2->expr || op == GFC_ISYM_SHAPE); gcc_assert (se->loop->dimen == 1); gcc_assert (se->ss->info->expr == expr); gfc_advance_se_ss_chain (se); @@ -2979,12 +2980,14 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) if (INTEGER_CST_P (bound)) { + gcc_assert (op != GFC_ISYM_SHAPE); if (((!as || as->type != AS_ASSUMED_RANK) && wi::geu_p (wi::to_wide (bound), GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)))) || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS)) gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid " - "dimension index", upper ? "UBOUND" : "LBOUND", + "dimension index", + (op == GFC_ISYM_UBOUND) ? "UBOUND" : "LBOUND", &expr->where); } @@ -3008,8 +3011,8 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) } } - /* Take care of the lbound shift for assumed-rank arrays, which are - nonallocatable and nonpointers. Those has a lbound of 1. */ + /* Take care of the lbound shift for assumed-rank arrays that are + nonallocatable and nonpointers. Those have a lbound of 1. */ assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK && ((arg->expr->ts.type != BT_CLASS && !arg->expr->symtree->n.sym->attr.allocatable @@ -3020,6 +3023,10 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) ubound = gfc_conv_descriptor_ubound_get (desc, bound); lbound = gfc_conv_descriptor_lbound_get (desc, bound); + size = fold_build2_loc (input_location, MINUS_EXPR, + gfc_array_index_type, ubound, lbound); + size = fold_build2_loc (input_location, PLUS_EXPR, + gfc_array_index_type, size, gfc_index_one_node); /* 13.14.53: Result value for LBOUND @@ -3042,106 +3049,82 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) not have size zero and has value zero if dimension DIM has size zero. */ - if (!upper && assumed_rank_lb_one) + if (op == GFC_ISYM_LBOUND && assumed_rank_lb_one) se->expr = gfc_index_one_node; else if (as) { - tree stride = gfc_conv_descriptor_stride_get (desc, bound); - - cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node, - ubound, lbound); - cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node, - stride, gfc_index_zero_node); - cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR, - logical_type_node, cond3, cond1); - cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node, - stride, gfc_index_zero_node); - - if (upper) + if (op == GFC_ISYM_UBOUND) { - tree cond5; - cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, - logical_type_node, cond3, cond4); - cond5 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, - gfc_index_one_node, lbound); - cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR, - logical_type_node, cond4, cond5); - - cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, - logical_type_node, cond, cond5); - - if (assumed_rank_lb_one) + cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, + size, gfc_index_zero_node); + se->expr = fold_build3_loc (input_location, COND_EXPR, + gfc_array_index_type, cond, + (assumed_rank_lb_one ? size : ubound), + gfc_index_zero_node); + } + else if (op == GFC_ISYM_LBOUND) + { + cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, + size, gfc_index_zero_node); + if (as->type == AS_ASSUMED_SIZE) { - tmp = fold_build2_loc (input_location, MINUS_EXPR, - gfc_array_index_type, ubound, lbound); - tmp = fold_build2_loc (input_location, PLUS_EXPR, - gfc_array_index_type, tmp, gfc_index_one_node); + cond1 = fold_build2_loc (input_location, EQ_EXPR, + logical_type_node, bound, + build_int_cst (TREE_TYPE (bound), + arg->expr->rank - 1)); + cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, + logical_type_node, cond, cond1); } - else - tmp = ubound; - se->expr = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond, - tmp, gfc_index_zero_node); + lbound, gfc_index_one_node); } + else if (op == GFC_ISYM_SHAPE) + se->expr = size; else - { - if (as->type == AS_ASSUMED_SIZE) - cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, - bound, build_int_cst (TREE_TYPE (bound), - arg->expr->rank - 1)); - else - cond = logical_false_node; + gcc_unreachable (); - cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR, - logical_type_node, cond3, cond4); - cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, + /* According to F2018 16.9.172, para 5, an assumed rank object, + argument associated with and assumed size array, has the ubound + of the final dimension set to -1 and UBOUND must return this. + Similarly for the SHAPE intrinsic. */ + if (op != GFC_ISYM_LBOUND && assumed_rank_lb_one) + { + tree minus_one = build_int_cst (gfc_array_index_type, -1); + tree rank = fold_convert (gfc_array_index_type, + gfc_conv_descriptor_rank (desc)); + rank = fold_build2_loc (input_location, PLUS_EXPR, + gfc_array_index_type, rank, minus_one); + + /* Fix the expression to stop it from becoming even more + complicated. */ + se->expr = gfc_evaluate_now (se->expr, &se->pre); + + /* Descriptors for assumed-size arrays have ubound = -1 + in the last dimension. */ + cond1 = fold_build2_loc (input_location, EQ_EXPR, + logical_type_node, ubound, minus_one); + cond = fold_build2_loc (input_location, EQ_EXPR, + logical_type_node, bound, rank); + cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node, cond, cond1); - se->expr = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond, - lbound, gfc_index_one_node); + minus_one, se->expr); } } - else + else /* as is null; this is an old-fashioned 1-based array. */ { - if (upper) + if (op != GFC_ISYM_LBOUND) { - size = fold_build2_loc (input_location, MINUS_EXPR, - gfc_array_index_type, ubound, lbound); - se->expr = fold_build2_loc (input_location, PLUS_EXPR, - gfc_array_index_type, size, - gfc_index_one_node); se->expr = fold_build2_loc (input_location, MAX_EXPR, - gfc_array_index_type, se->expr, + gfc_array_index_type, size, gfc_index_zero_node); } else se->expr = gfc_index_one_node; } - /* According to F2018 16.9.172, para 5, an assumed rank object, argument - associated with and assumed size array, has the ubound of the final - dimension set to -1 and UBOUND must return this. */ - if (upper && as && as->type == AS_ASSUMED_RANK) - { - tree minus_one = build_int_cst (gfc_array_index_type, -1); - tree rank = fold_convert (gfc_array_index_type, - gfc_conv_descriptor_rank (desc)); - rank = fold_build2_loc (input_location, PLUS_EXPR, - gfc_array_index_type, rank, minus_one); - /* Fix the expression to stop it from becoming even more complicated. */ - se->expr = gfc_evaluate_now (se->expr, &se->pre); - cond = fold_build2_loc (input_location, NE_EXPR, - logical_type_node, bound, rank); - cond1 = fold_build2_loc (input_location, NE_EXPR, - logical_type_node, ubound, minus_one); - cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, - logical_type_node, cond, cond1); - se->expr = fold_build3_loc (input_location, COND_EXPR, - gfc_array_index_type, cond, - se->expr, minus_one); - } type = gfc_typenode_for_spec (&expr->ts); se->expr = convert (type, se->expr); @@ -6691,85 +6674,6 @@ gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr) } static void -gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr) -{ - gfc_actual_arglist *s, *k; - gfc_expr *e; - gfc_array_spec *as; - gfc_ss *ss; - symbol_attribute attr; - tree result_desc = se->expr; - - /* Remove the KIND argument, if present. */ - s = expr->value.function.actual; - k = s->next; - e = k->expr; - gfc_free_expr (e); - k->expr = NULL; - - gfc_conv_intrinsic_funcall (se, expr); - - /* According to F2018 16.9.172, para 5, an assumed rank entity, argument - associated with an assumed size array, has the ubound of the final - dimension set to -1 and SHAPE must return this. */ - - as = gfc_get_full_arrayspec_from_expr (s->expr); - if (!as || as->type != AS_ASSUMED_RANK) - return; - attr = gfc_expr_attr (s->expr); - ss = gfc_walk_expr (s->expr); - if (attr.pointer || attr.allocatable - || !ss || ss->info->type != GFC_SS_SECTION) - return; - if (se->expr) - result_desc = se->expr; - if (POINTER_TYPE_P (TREE_TYPE (result_desc))) - result_desc = build_fold_indirect_ref_loc (input_location, result_desc); - if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (result_desc))) - { - tree rank, minus_one, cond, ubound, tmp; - stmtblock_t block; - gfc_se ase; - - minus_one = build_int_cst (gfc_array_index_type, -1); - - /* Recover the descriptor for the array. */ - gfc_init_se (&ase, NULL); - ase.descriptor_only = 1; - gfc_conv_expr_lhs (&ase, ss->info->expr); - - /* Obtain rank-1 so that we can address both descriptors. */ - rank = gfc_conv_descriptor_rank (ase.expr); - rank = fold_convert (gfc_array_index_type, rank); - rank = fold_build2_loc (input_location, PLUS_EXPR, - gfc_array_index_type, - rank, minus_one); - rank = gfc_evaluate_now (rank, &se->pre); - - /* The ubound for the final dimension will be tested for being -1. */ - ubound = gfc_conv_descriptor_ubound_get (ase.expr, rank); - ubound = gfc_evaluate_now (ubound, &se->pre); - cond = fold_build2_loc (input_location, EQ_EXPR, - logical_type_node, - ubound, minus_one); - - /* Obtain the last element of the result from the library shape - intrinsic and set it to -1 if that is the value of ubound. */ - tmp = gfc_conv_array_data (result_desc); - tmp = build_fold_indirect_ref_loc (input_location, tmp); - tmp = gfc_build_array_ref (tmp, rank, NULL, NULL); - - gfc_init_block (&block); - gfc_add_modify (&block, tmp, build_int_cst (TREE_TYPE (tmp), -1)); - - cond = build3_v (COND_EXPR, cond, - gfc_finish_block (&block), - build_empty_stmt (input_location)); - gfc_add_expr_to_block (&se->pre, cond); - } -} - -static void gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift, bool arithmetic) { @@ -10178,10 +10082,6 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR); break; - case GFC_ISYM_SHAPE: - gfc_conv_intrinsic_shape (se, expr); - break; - default: gfc_conv_intrinsic_funcall (se, expr); break; @@ -10575,7 +10475,7 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) break; case GFC_ISYM_LBOUND: - gfc_conv_intrinsic_bound (se, expr, 0); + gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_LBOUND); break; case GFC_ISYM_LCOBOUND: @@ -10710,6 +10610,10 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_scale (se, expr); break; + case GFC_ISYM_SHAPE: + gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_SHAPE); + break; + case GFC_ISYM_SIGN: gfc_conv_intrinsic_sign (se, expr); break; @@ -10756,7 +10660,7 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) break; case GFC_ISYM_UBOUND: - gfc_conv_intrinsic_bound (se, expr, 1); + gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_UBOUND); break; case GFC_ISYM_UCOBOUND: @@ -11030,6 +10934,7 @@ gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss) case GFC_ISYM_UCOBOUND: case GFC_ISYM_LCOBOUND: case GFC_ISYM_THIS_IMAGE: + case GFC_ISYM_SHAPE: break; default: @@ -11038,8 +10943,8 @@ gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss) } -/* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter - are expanded into code inside the scalarization loop. */ +/* The LBOUND, LCOBOUND, UBOUND, UCOBOUND, and SHAPE intrinsics with + one parameter are expanded into code inside the scalarization loop. */ static gfc_ss * gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr) @@ -11048,7 +10953,8 @@ gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr) gfc_add_class_array_ref (expr->value.function.actual->expr); /* The two argument version returns a scalar. */ - if (expr->value.function.actual->next->expr) + if (expr->value.function.isym->id != GFC_ISYM_SHAPE + && expr->value.function.actual->next->expr) return ss; return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC); @@ -11148,7 +11054,6 @@ gfc_is_intrinsic_libcall (gfc_expr * expr) case GFC_ISYM_PARITY: case GFC_ISYM_PRODUCT: case GFC_ISYM_SUM: - case GFC_ISYM_SHAPE: case GFC_ISYM_SPREAD: case GFC_ISYM_YN2: /* Ignore absent optional parameters. */ @@ -11198,6 +11103,7 @@ gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr, case GFC_ISYM_UBOUND: case GFC_ISYM_UCOBOUND: case GFC_ISYM_THIS_IMAGE: + case GFC_ISYM_SHAPE: return gfc_walk_intrinsic_bound (ss, expr); case GFC_ISYM_TRANSFER: diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index 4f1b346..e81c558 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -6407,12 +6407,17 @@ gfc_trans_omp_task (gfc_code *code) static tree gfc_trans_omp_taskgroup (gfc_code *code) { + stmtblock_t block; + gfc_start_block (&block); tree body = gfc_trans_code (code->block->next); tree stmt = make_node (OMP_TASKGROUP); TREE_TYPE (stmt) = void_type_node; OMP_TASKGROUP_BODY (stmt) = body; - OMP_TASKGROUP_CLAUSES (stmt) = NULL_TREE; - return stmt; + OMP_TASKGROUP_CLAUSES (stmt) = gfc_trans_omp_clauses (&block, + code->ext.omp_clauses, + code->loc); + gfc_add_expr_to_block (&block, stmt); + return gfc_finish_block (&block); } static tree @@ -6995,7 +7000,11 @@ gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses) res = gfc_trans_omp_directive (code); ompws_flags = saved_ompws_flags; break; - + + case EXEC_BLOCK: + res = gfc_trans_block_construct (code); + break; + default: gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code"); } diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c index 50fceeb..4277806 100644 --- a/gcc/fortran/trans-types.c +++ b/gcc/fortran/trans-types.c @@ -3014,7 +3014,11 @@ create_fn_spec (gfc_symbol *sym, tree fntype) } if (sym->ts.type == BT_CHARACTER) { - spec[spec_len++] = 'R'; + if (!sym->ts.u.cl->length + && (sym->attr.allocatable || sym->attr.pointer)) + spec[spec_len++] = 'w'; + else + spec[spec_len++] = 'R'; spec[spec_len++] = ' '; } } diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 85ef974..93d6da6 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -180,9 +180,9 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name) int_range_max edge_range; gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name))); - // Do not process values along abnormal or EH edges. - if (e->flags & (EDGE_ABNORMAL|EDGE_EH)) - return false; + // Do not process values along abnormal edges. + if (e->flags & EDGE_ABNORMAL) + return get_tree_range (r, name, NULL); unsigned idx; if ((idx = tracer.header ("range_on_edge ("))) @@ -203,7 +203,7 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name) bool res = true; if (!gimple_range_ssa_p (name)) - res = range_of_expr (r, name); + return get_tree_range (r, name, NULL); else { range_on_exit (r, e->src, name); @@ -258,7 +258,7 @@ gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name) if (!name) res = fold_range_internal (r, s, NULL_TREE); else if (!gimple_range_ssa_p (name)) - res = false; + res = get_tree_range (r, name, NULL); // Check if the stmt has already been processed, and is not stale. else if (m_cache.get_non_stale_global_range (r, name)) { diff --git a/gcc/match.pd b/gcc/match.pd index 3ff15bc..5bed2e1 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3606,6 +3606,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) >= inside_prec - !inside_unsignedp) (convert @0))))))) +/* (float_type)(integer_type) x -> trunc (x) if the type of x matches + float_type. Only do the transformation if we do not need to preserve + trapping behaviour, so require !flag_trapping_math. */ +#if GIMPLE +(simplify + (float (fix_trunc @0)) + (if (!flag_trapping_math + && types_match (type, TREE_TYPE (@0)) + && direct_internal_fn_supported_p (IFN_TRUNC, type, + OPTIMIZE_FOR_BOTH)) + (IFN_TRUNC @0))) +#endif + /* If we have a narrowing conversion to an integral type that is fed by a BIT_AND_EXPR, we might be able to remove the BIT_AND_EXPR if it merely masks off bits outside the final type (and nothing else). */ diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 057b7ae..15e4424 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -591,7 +591,15 @@ omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx) tree copy = copy_var_decl (var, name, type); DECL_CONTEXT (copy) = current_function_decl; - DECL_CHAIN (copy) = ctx->block_vars; + + if (ctx) + { + DECL_CHAIN (copy) = ctx->block_vars; + ctx->block_vars = copy; + } + else + record_vars (copy); + /* If VAR is listed in task_shared_vars, it means it wasn't originally addressable and is just because task needs to take it's address. But we don't need to take address of privatizations @@ -602,7 +610,6 @@ omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx) || (global_nonaddressable_vars && bitmap_bit_p (global_nonaddressable_vars, DECL_UID (var))))) TREE_ADDRESSABLE (copy) = 0; - ctx->block_vars = copy; return copy; } @@ -1281,7 +1288,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) tree at = t; if (ctx->outer) scan_omp_op (&at, ctx->outer); - tree nt = omp_copy_decl_1 (at, ctx); + tree nt = omp_copy_decl_1 (at, ctx->outer); splay_tree_insert (ctx->field_map, (splay_tree_key) &DECL_CONTEXT (t), (splay_tree_value) nt); @@ -1322,7 +1329,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) tree at = decl; if (ctx->outer) scan_omp_op (&at, ctx->outer); - tree nt = omp_copy_decl_1 (at, ctx); + tree nt = omp_copy_decl_1 (at, ctx->outer); splay_tree_insert (ctx->field_map, (splay_tree_key) &DECL_CONTEXT (decl), (splay_tree_value) nt); diff --git a/gcc/params.opt b/gcc/params.opt index 06a6fdc..83b3db6 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -533,6 +533,10 @@ The maximum number of nested indirect inlining performed by early inliner. Common Joined UInteger Var(param_max_fields_for_field_sensitive) Param Maximum number of fields in a structure before pointer analysis treats the structure as a single variable. +-param=max-fsm-thread-length= +Common Joined UInteger Var(param_max_fsm_thread_length) Init(10) IntegerRange(1, 999999) Param Optimization +Maximum number of basic blocks on a jump thread path. + -param=max-fsm-thread-path-insns= Common Joined UInteger Var(param_max_fsm_thread_path_insns) Init(100) IntegerRange(1, 999999) Param Optimization Maximum number of instructions to copy when duplicating blocks on a finite state automaton jump thread path. diff --git a/gcc/passes.def b/gcc/passes.def index c11c237..4c54176 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -339,9 +339,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_thread_jumps); NEXT_PASS (pass_vrp, false /* warn_array_bounds_p */); NEXT_PASS (pass_vrp_threader); - /* Threading can leave many const/copy propagations in the IL. - Clean them up. Instead of just copy_prop, we use ccp to - compute alignment and nonzero bits. */ + /* Run CCP to compute alignment and nonzero bits. */ NEXT_PASS (pass_ccp, true /* nonzero_p */); NEXT_PASS (pass_warn_restrict); NEXT_PASS (pass_dse); diff --git a/gcc/target.def b/gcc/target.def index b9bc7fd..927ebfc 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -4717,45 +4717,6 @@ not generate any instructions in this case.", default_setup_incoming_varargs) DEFHOOK -(load_bounds_for_arg, - "This hook is used by expand pass to emit insn to load bounds of\n\ -@var{arg} passed in @var{slot}. Expand pass uses this hook in case\n\ -bounds of @var{arg} are not passed in register. If @var{slot} is a\n\ -memory, then bounds are loaded as for regular pointer loaded from\n\ -memory. If @var{slot} is not a memory then @var{slot_no} is an integer\n\ -constant holding number of the target dependent special slot which\n\ -should be used to obtain bounds. Hook returns RTX holding loaded bounds.", - rtx, (rtx slot, rtx arg, rtx slot_no), - default_load_bounds_for_arg) - -DEFHOOK -(store_bounds_for_arg, - "This hook is used by expand pass to emit insns to store @var{bounds} of\n\ -@var{arg} passed in @var{slot}. Expand pass uses this hook in case\n\ -@var{bounds} of @var{arg} are not passed in register. If @var{slot} is a\n\ -memory, then @var{bounds} are stored as for regular pointer stored in\n\ -memory. If @var{slot} is not a memory then @var{slot_no} is an integer\n\ -constant holding number of the target dependent special slot which\n\ -should be used to store @var{bounds}.", - void, (rtx arg, rtx slot, rtx bounds, rtx slot_no), - default_store_bounds_for_arg) - -DEFHOOK -(load_returned_bounds, - "This hook is used by expand pass to emit insn to load bounds\n\ -returned by function call in @var{slot}. Hook returns RTX holding\n\ -loaded bounds.", - rtx, (rtx slot), - default_load_returned_bounds) - -DEFHOOK -(store_returned_bounds, - "This hook is used by expand pass to emit insn to store @var{bounds}\n\ -returned by function call into @var{slot}.", - void, (rtx slot, rtx bounds), - default_store_returned_bounds) - -DEFHOOK (call_args, "While generating RTL for a function call, this target hook is invoked once\n\ for each argument passed to the function, either a register returned by\n\ @@ -4958,12 +4919,6 @@ The return value is usually either a @code{reg} RTX for the hard\n\ register in which to pass the argument, or zero to pass the argument\n\ on the stack.\n\ \n\ -The return value can be a @code{const_int} which means argument is\n\ -passed in a target specific slot with specified number. Target hooks\n\ -should be used to store or load argument in such case. See\n\ -@code{TARGET_STORE_BOUNDS_FOR_ARG} and @code{TARGET_LOAD_BOUNDS_FOR_ARG}\n\ -for more information.\n\ -\n\ The value of the expression can also be a @code{parallel} RTX@. This is\n\ used when an argument is passed in multiple locations. The mode of the\n\ @code{parallel} should be the mode of the entire argument. The\n\ diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 812bbe3..0b525bb 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -2253,36 +2253,6 @@ default_member_type_forces_blk (const_tree, machine_mode) return false; } -rtx -default_load_bounds_for_arg (rtx addr ATTRIBUTE_UNUSED, - rtx ptr ATTRIBUTE_UNUSED, - rtx bnd ATTRIBUTE_UNUSED) -{ - gcc_unreachable (); -} - -void -default_store_bounds_for_arg (rtx val ATTRIBUTE_UNUSED, - rtx addr ATTRIBUTE_UNUSED, - rtx bounds ATTRIBUTE_UNUSED, - rtx to ATTRIBUTE_UNUSED) -{ - gcc_unreachable (); -} - -rtx -default_load_returned_bounds (rtx slot ATTRIBUTE_UNUSED) -{ - gcc_unreachable (); -} - -void -default_store_returned_bounds (rtx slot ATTRIBUTE_UNUSED, - rtx bounds ATTRIBUTE_UNUSED) -{ - gcc_unreachable (); -} - /* Default version of canonicalize_comparison. */ void diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 92d5199..7f7f25a 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -272,10 +272,6 @@ extern bool can_use_doloop_if_innermost (const widest_int &, const widest_int &, unsigned int, bool); -extern rtx default_load_bounds_for_arg (rtx, rtx, rtx); -extern void default_store_bounds_for_arg (rtx, rtx, rtx, rtx); -extern rtx default_load_returned_bounds (rtx); -extern void default_store_returned_bounds (rtx,rtx); extern bool default_optab_supported_p (int, machine_mode, machine_mode, optimization_type); extern unsigned int default_max_noce_ifcvt_seq_cost (edge); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2876c7a..602b727 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,341 @@ +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/mvn-cmeq0-1.c: New test. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/narrow_high_combine.c: Update case. + * gcc.target/aarch64/xtn-combine-1.c: New test. + * gcc.target/aarch64/xtn-combine-2.c: New test. + * gcc.target/aarch64/xtn-combine-3.c: New test. + * gcc.target/aarch64/xtn-combine-4.c: New test. + * gcc.target/aarch64/xtn-combine-5.c: New test. + * gcc.target/aarch64/xtn-combine-6.c: New test. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/shl-combine-2.c: New test. + * gcc.target/aarch64/shl-combine-3.c: New test. + * gcc.target/aarch64/shl-combine-4.c: New test. + * gcc.target/aarch64/shl-combine-5.c: New test. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/shrn-combine-10.c: New test. + * gcc.target/aarch64/shrn-combine-5.c: New test. + * gcc.target/aarch64/shrn-combine-6.c: New test. + * gcc.target/aarch64/shrn-combine-7.c: New test. + * gcc.target/aarch64/shrn-combine-8.c: New test. + * gcc.target/aarch64/shrn-combine-9.c: New test. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/shrn-combine-1.c: New test. + * gcc.target/aarch64/shrn-combine-2.c: New test. + * gcc.target/aarch64/shrn-combine-3.c: New test. + * gcc.target/aarch64/shrn-combine-4.c: New test. + +2021-10-20 Chung-Lin Tang <cltang@codesourcery.com> + + * gfortran.dg/gomp/reduction4.f90: Adjust omp target in_reduction' scan + pattern. + +2021-10-20 Martin Liska <mliska@suse.cz> + + Revert: + 2021-10-20 Martin Liska <mliska@suse.cz> + + PR target/102374 + * gcc.target/i386/pr102374.c: New test. + +2021-10-20 Martin Liska <mliska@suse.cz> + + Revert: + 2021-10-20 Martin Liska <mliska@suse.cz> + + PR target/102375 + * gcc.target/aarch64/pr102375.c: New test. + +2021-10-20 Wilco Dijkstra <wdijkstr@arm.com> + + PR target/100966 + * gcc.target/aarch64/frint.x: Add roundeven tests. + * gcc.target/aarch64/frint_double.c: Likewise. + * gcc.target/aarch64/frint_float.c: Likewise. + +2021-10-20 Andre Simoes Dias Vieira <andre.simoesdiasvieira@arm.com> + + * gcc.target/aarch64/fmla_intrinsic_1.c: prevent over optimization. + * gcc.target/aarch64/fmls_intrinsic_1.c: Likewise. + * gcc.target/aarch64/fmul_intrinsic_1.c: Likewise. + * gcc.target/aarch64/mla_intrinsic_1.c: Likewise. + * gcc.target/aarch64/mls_intrinsic_1.c: Likewise. + * gcc.target/aarch64/mul_intrinsic_1.c: Likewise. + * gcc.target/aarch64/simd/vmul_elem_1.c: Likewise. + * gcc.target/aarch64/vclz.c: Likewise. + * gcc.target/aarch64/vneg_s.c: Likewise. + +2021-10-20 Andre Simoes Dias Vieira <andre.simoesdiasvieira@arm.com> + + * gcc.target/aarch64/merge_trunc1.c: New test. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.dg/pr102764.c: New test. + +2021-10-20 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/102815 + * gfortran.dg/bind-c-contiguous-5.c (do_call, reset_var): Handle + big andian. + +2021-10-20 Jakub Jelinek <jakub@redhat.com> + + PR c++/102642 + * g++.dg/tls/pr102642.C: New test. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + Richard Biener <rguenther@suse.de> + + * gcc.dg/Warray-bounds-87.c: Remove xfail. + * gcc.dg/analyzer/pr94851-2.c: Remove xfail. + * gcc.dg/graphite/pr69728.c: Remove xfail. + * gcc.dg/graphite/scop-dsyr2k.c: Remove xfail. + * gcc.dg/graphite/scop-dsyrk.c: Remove xfail. + * gcc.dg/shrink-wrap-loop.c: Remove xfail. + * gcc.dg/loop-8.c: Adjust for new threading restrictions. + * gcc.dg/tree-ssa/ifc-20040816-1.c: Same. + * gcc.dg/tree-ssa/pr21559.c: Same. + * gcc.dg/tree-ssa/pr59597.c: Same. + * gcc.dg/tree-ssa/pr71437.c: Same. + * gcc.dg/tree-ssa/pr77445-2.c: Same. + * gcc.dg/tree-ssa/ssa-dom-thread-4.c: Same. + * gcc.dg/tree-ssa/ssa-dom-thread-7.c: Same. + * gcc.dg/vect/bb-slp-16.c: Same. + * gcc.dg/tree-ssa/ssa-dom-thread-6.c: Remove. + * gcc.dg/tree-ssa/ssa-dom-thread-18.c: Remove. + * gcc.dg/tree-ssa/ssa-dom-thread-2a.c: Remove. + * gcc.dg/tree-ssa/ssa-thread-invalid.c: New test. + +2021-10-20 Jeff Law <jeffreyalaw@gmail.com> + + * gcc.dg/plugin/gil-1.c: Add dg-require-effective-target marker. + +2021-10-20 Hongtao Liu <hongtao.liu@intel.com> + Kewen Lin <linkw@linux.ibm.com> + + PR middle-end/102722 + PR middle-end/102697 + PR middle-end/102462 + PR middle-end/102706 + PR middle-end/102744 + * c-c++-common/Wstringop-overflow-2.c: Adjust testcase with new + xfail/target selector. + * gcc.dg/Warray-bounds-51.c: Ditto. + * gcc.dg/Warray-parameter-3.c: Ditto. + * gcc.dg/Wstringop-overflow-14.c: Ditto. + * gcc.dg/Wstringop-overflow-21.c: Ditto. + * gcc.dg/Wstringop-overflow-68.c: Ditto. + * gcc.dg/Wstringop-overflow-76.c: Ditto. + * gcc.dg/Warray-bounds-48.c: Ditto. + * gcc.dg/Wzero-length-array-bounds-2.c: Ditto. + * lib/target-supports.exp (check_vect_slp_aligned_store_usage): + New function. + (check_effective_target_vect_slp_v2qi_store): Ditto. + (check_effective_target_vect_slp_v4qi_store): Ditto. + (check_effective_target_vect_slp_v8qi_store): Ditto. + (check_effective_target_vect_slp_v16qi_store): Ditto. + (check_effective_target_vect_slp_v2hi_store): Ditto. + (check_effective_target_vect_slp_v4hi_store): Ditto. + (check_effective_target_vect_slp_v2si_store): Ditto. + (check_effective_target_vect_slp_v4si_store): Ditto. + * c-c++-common/Wstringop-overflow-2-novec.c: New test. + * gcc.dg/Warray-bounds-51-novec.c: New test. + * gcc.dg/Warray-bounds-48-novec.c: New test. + * gcc.dg/Warray-parameter-3-novec.c: New test. + * gcc.dg/Wstringop-overflow-14-novec.c: New test. + * gcc.dg/Wstringop-overflow-21-novec.c: New test. + * gcc.dg/Wstringop-overflow-76-novec.c: New test. + * gcc.dg/Wzero-length-array-bounds-2-novec.c: New test. + +2021-10-19 Paul A. Clarke <pc@us.ibm.com> + + * gcc.target/powerpc/sse4_2-pcmpgtq.c: Tighten dg constraints + to minimally Power8. + +2021-10-19 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/92482 + * gfortran.dg/bind-c-char-descr.f90: Remove xfail; extend a bit. + +2021-10-19 Martin Liska <mliska@suse.cz> + + PR target/102375 + * gcc.target/aarch64/pr102375.c: New test. + +2021-10-19 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102827 + * gcc.dg/pr102827.c: New testcase. + +2021-10-19 Xionghu Luo <luoxhu@linux.ibm.com> + + * gcc.target/powerpc/builtins-1.c: Update instruction counts. + +2021-10-19 Haochen Gui <guihaoc@gcc.gnu.org> + + * gcc.target/powerpc/p10_vec_xl_sext.c: New test. + +2021-10-19 prathamesh.kulkarni <prathamesh.kulkarni@linaro.org> + + PR target/93183 + * gcc.target/aarch64/sve/pr93183.c: Remove -mcpu=generic+sve from dg-options. + +2021-10-19 Jakub Jelinek <jakub@redhat.com> + + PR c++/102786 + * g++.dg/cpp2a/constexpr-virtual19.C: New test. + +2021-10-19 Martin Liska <mliska@suse.cz> + + PR target/102374 + * gcc.target/i386/pr102374.c: New test. + +2021-10-19 dianhong xu <dianhong.xu@intel.com> + + * gcc.target/i386/avx512fp16-set1-pch-1a.c: New test. + * gcc.target/i386/avx512fp16-set1-pch-1b.c: New test. + * gcc.target/i386/avx512fp16vl-set1-pch-1a.c: New test. + * gcc.target/i386/avx512fp16vl-set1-pch-1b.c: New test. + +2021-10-18 Andrew MacLeod <amacleod@redhat.com> + + PR tree-optimization/102796 + * g++.dg/pr102796.C: New. + +2021-10-18 Kwok Cheung Yeung <kcy@codesourcery.com> + + * gfortran.dg/gomp/declare-variant-15.f90 (variant2, base2, test2): + Add tests. + * gfortran.dg/gomp/declare-variant-16.f90 (base2, variant2, test2): + Add tests. + +2021-10-18 UroÅ¡ Bizjak <ubizjak@gmail.com> + + PR target/102761 + * gcc.target/i386/pr102761.c: New test. + +2021-10-18 Jason Merrill <jason@redhat.com> + + * g++.dg/template/crash90.C: Check location of pedwarn. + +2021-10-18 H.J. Lu <hjl.tools@gmail.com> + + * gcc.target/i386/387-12.c (dg-do compile): Require ia32. + (dg-options): Remove -m32. + +2021-10-18 Roger Sayle <roger@nextmovesoftware.com> + + * gcc.target/i386/387-12.c: Add explicit -m32 option. + +2021-10-18 Roger Sayle <roger@nextmovesoftware.com> + + * gcc.target/bfin/ones.c: New test case. + * gcc.target/bfin/parity.c: New test case. + * gcc.target/bfin/popcount.c: New test case. + +2021-10-18 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102788 + * g++.dg/vect/pr102788.cc: New testcase. + +2021-10-18 Roger Sayle <roger@nextmovesoftware.com> + + * gcc.target/bfin/ssabs.c: New test case. + * gcc.target/bfin/ssneg.c: New test case. + +2021-10-18 prathamesh.kulkarni <prathamesh.kulkarni@linaro.org> + + PR target/93183 + * gcc.target/aarch64/sve/cond_unary_4.c: Adjust. + * gcc.target/aarch64/sve/pr93183.c: New test. + +2021-10-18 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/102086 + PR fortran/92189 + PR fortran/92621 + PR fortran/101308 + PR fortran/101309 + PR fortran/101635 + PR fortran/92482 + * gfortran.dg/ISO_Fortran_binding_4.f90: Extend testcase. + * gfortran.dg/PR100914.f90: Remove xfail. + * gfortran.dg/PR100915.c: Expect CFI_type_cfunptr. + * gfortran.dg/PR100915.f90: Handle CFI_type_cfunptr != CFI_type_cptr. + * gfortran.dg/PR93963.f90: Extend select-rank tests. + * gfortran.dg/bind-c-intent-out.f90: Change to dg-do run, + update scan-dump. + * gfortran.dg/bind_c_array_params_2.f90: Update/extend scan-dump. + * gfortran.dg/bind_c_char_10.f90: Update scan-dump. + * gfortran.dg/bind_c_char_8.f90: Remove dg-error "sorry". + * gfortran.dg/c-interop/allocatable-dummy.f90: Remove xfail. + * gfortran.dg/c-interop/c1255-1.f90: Likewise. + * gfortran.dg/c-interop/c407c-1.f90: Update dg-error. + * gfortran.dg/c-interop/cf-descriptor-5.f90: Remove xfail. + * gfortran.dg/c-interop/cf-out-descriptor-3.f90: Likewise. + * gfortran.dg/c-interop/cf-out-descriptor-4.f90: Likewise. + * gfortran.dg/c-interop/cf-out-descriptor-5.f90: Likewise. + * gfortran.dg/c-interop/contiguous-2.f90: Likewise. + * gfortran.dg/c-interop/contiguous-3.f90: Likewise. + * gfortran.dg/c-interop/deferred-character-1.f90: Likewise. + * gfortran.dg/c-interop/deferred-character-2.f90: Likewise. + * gfortran.dg/c-interop/fc-descriptor-3.f90: Likewise. + * gfortran.dg/c-interop/fc-descriptor-5.f90: Likewise. + * gfortran.dg/c-interop/fc-descriptor-6.f90: Likewise. + * gfortran.dg/c-interop/fc-out-descriptor-3.f90: Likewise. + * gfortran.dg/c-interop/fc-out-descriptor-4.f90: Likewise. + * gfortran.dg/c-interop/fc-out-descriptor-5.f90: Likewise. + * gfortran.dg/c-interop/fc-out-descriptor-6.f90: Likewise. + * gfortran.dg/c-interop/ff-descriptor-5.f90: Likewise. + * gfortran.dg/c-interop/ff-descriptor-6.f90: Likewise. + * gfortran.dg/c-interop/fc-descriptor-7.f90: Remove xfail + extend. + * gfortran.dg/c-interop/fc-descriptor-7-c.c: Update for changes. + * gfortran.dg/c-interop/shape.f90: Add implicit none. + * gfortran.dg/c-interop/typecodes-array-char-c.c: Add kind=4 char. + * gfortran.dg/c-interop/typecodes-array-char.f90: Likewise. + * gfortran.dg/c-interop/typecodes-array-float128.f90: Remove xfail. + * gfortran.dg/c-interop/typecodes-scalar-basic.f90: Likewise. + * gfortran.dg/c-interop/typecodes-scalar-float128.f90: Likewise. + * gfortran.dg/c-interop/typecodes-scalar-int128.f90: Likewise. + * gfortran.dg/c-interop/typecodes-scalar-longdouble.f90: Likewise. + * gfortran.dg/iso_c_binding_char_1.f90: Remove dg-error "sorry". + * gfortran.dg/pr93792.f90: Turn XFAIL into PASS. + * gfortran.dg/ISO_Fortran_binding_19.f90: New test. + * gfortran.dg/assumed_type_12.f90: New test. + * gfortran.dg/assumed_type_13.c: New test. + * gfortran.dg/assumed_type_13.f90: New test. + * gfortran.dg/bind-c-char-descr.f90: New test. + * gfortran.dg/bind-c-contiguous-1.c: New test. + * gfortran.dg/bind-c-contiguous-1.f90: New test. + * gfortran.dg/bind-c-contiguous-2.f90: New test. + * gfortran.dg/bind-c-contiguous-3.c: New test. + * gfortran.dg/bind-c-contiguous-3.f90: New test. + * gfortran.dg/bind-c-contiguous-4.c: New test. + * gfortran.dg/bind-c-contiguous-4.f90: New test. + * gfortran.dg/bind-c-contiguous-5.c: New test. + * gfortran.dg/bind-c-contiguous-5.f90: New test. + +2021-10-18 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102798 + * gcc.dg/pr102798.c: New testcase. + +2021-10-18 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/102745 + * gfortran.dg/class_72.f90: New. + 2021-10-15 Jason Merrill <jason@redhat.com> PR c++/51851 diff --git a/gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c b/gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c new file mode 100644 index 0000000..3c34ad3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c @@ -0,0 +1,126 @@ +/* PR middle-end/91458 - inconsistent warning for writing past the end + of an array member + { dg-do compile } + { dg-options "-O2 -fno-tree-vectorize -Wall -Wno-array-bounds -fno-ipa-icf" } */ + +void sink (void*); + +// Exercise trailing one-element array members. + +struct A1 +{ + char n; + char a[1]; // { dg-message "destination object" "note" } +}; + +// Verify warning for access to a definition with an initializer that doesn't +// initialize the one-element array member. +struct A1 a1__ = { 0 }; + +void ga1__ (void) +{ + a1__.a[0] = 0; + a1__.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a1__.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + + struct A1 a = { 1 }; + a.a[0] = 0; + a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + sink (&a); +} + +// Verify warning for access to a definition with an initializer that +// initializes the one-element array member to empty. +struct A1 a1_0 = { 0, { } }; + +void ga1_0_ (void) +{ + a1_0.a[0] = 0; + a1_0.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a1_0.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + + struct A1 a = { 1, { } }; + a.a[0] = 0; + a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + sink (&a); +} + +// Verify warning for access to a definition with an initializer that +// initializes the one-element array member. +struct A1 a1_1 = { 0, { 1 } }; + +void ga1_1 (void) +{ + a1_1.a[0] = 0; + a1_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a1_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + + struct A1 a = { 0, { 1 } }; + a.a[0] = 0; + a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + sink (&a); +} + +// Exercise interior one-element array members (verify they're not +// treated as trailing. + +struct A1i +{ + char n; + char a[1]; // { dg-message "destination object" } + char x; +}; + +// Verify warning for access to a definition with an initializer that doesn't +// initialize the one-element array member. +struct A1i a1i__ = { 0 }; + +void ga1i__ (void) +{ + a1i__.a[0] = 0; + a1i__.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a1i__.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + + struct A1i a = { 0 }; + a.a[0] = 0; + a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + sink (&a); +} + +// Verify warning for access to a definition with an initializer that +// initializes the one-element array member to empty. +struct A1 a1i_0 = { 0, { } }; + +void ga1i_0_ (void) +{ + a1i_0.a[0] = 0; + a1i_0.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a1i_0.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + + struct A1 a = { 0, { } }; + a.a[0] = 0; + a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + sink (&a); +} + +// Verify warning for access to a definition with an initializer that +// initializes the one-element array member. +struct A1 a1i_1 = { 0, { 1 } }; + +void ga1i_1 (void) +{ + a1i_1.a[0] = 0; + a1i_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a1i_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + + struct A1 a = { 0, { 1 } }; + a.a[0] = 1; + a.a[1] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + a.a[2] = 3; // { dg-warning "\\\[-Wstringop-overflow" } + sink (&a); +} diff --git a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c index 7d29b5f..ca38bda 100644 --- a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c +++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c @@ -190,7 +190,7 @@ void ga1__ (void) struct A1 a = { 1 }; a.a[0] = 0; a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } - a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v2qi_store } } } sink (&a); } @@ -207,7 +207,7 @@ void ga1_0_ (void) struct A1 a = { 1, { } }; a.a[0] = 0; a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } - a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v2qi_store } } } sink (&a); } @@ -221,10 +221,10 @@ void ga1_1 (void) a1_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } a1_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } - struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } + struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v4qi_store } } } a.a[0] = 0; - a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } - a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } } sink (&a); } @@ -289,7 +289,7 @@ void ga1i__ (void) struct A1i a = { 0 }; a.a[0] = 0; a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } - a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v2qi_store } } } sink (&a); } @@ -306,7 +306,7 @@ void ga1i_0_ (void) struct A1 a = { 0, { } }; a.a[0] = 0; a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } - a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v2qi_store } } } sink (&a); } @@ -320,10 +320,10 @@ void ga1i_1 (void) a1i_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } a1i_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } - struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } + struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { target { vect_slp_v4qi_store } } } a.a[0] = 1; - a.a[1] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } - a.a[2] = 3; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + a.a[1] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v4qi_store } } } + a.a[2] = 3; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v4qi_store } } } sink (&a); } diff --git a/gcc/testsuite/c-c++-common/ubsan/pr64888.c b/gcc/testsuite/c-c++-common/ubsan/pr64888.c new file mode 100644 index 0000000..6319c2f --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/pr64888.c @@ -0,0 +1,27 @@ +/* PR middle-end/64888 */ +/* { dg-do compile { target fopenmp } } */ +/* { dg-options "-fopenmp -fsanitize=undefined" } */ + +int a, b; + +void +foo () +{ + int c; +#pragma omp parallel default (none) shared (a, b) private (c) + { + c = a / b; /* { dg-bogus "not specified in enclosing" } */ + (void) c; + } +#pragma omp task default (none) shared (a, b) private (c) + { + c = a << b; /* { dg-bogus "not specified in enclosing" } */ + (void) c; + } +#pragma omp teams default (none) shared (a, b) + { + int d[a]; /* { dg-bogus "not specified in enclosing" } */ + d[0] = 0; + (void) d[0]; + } +} diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual19.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual19.C new file mode 100644 index 0000000..cb0d1be --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual19.C @@ -0,0 +1,11 @@ +// PR c++/102786 +// { dg-do compile { target c++20 } } + +struct S { + virtual constexpr int foo () const { return 42; } +}; + +constexpr S s; +constexpr auto a = &S::foo; +constexpr auto b = (s.*a) (); +constexpr auto c = (s.*&S::foo) (); diff --git a/gcc/testsuite/g++.dg/pr102796.C b/gcc/testsuite/g++.dg/pr102796.C new file mode 100644 index 0000000..6ad1008 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr102796.C @@ -0,0 +1,18 @@ +// { dg-do compile } +// { dg-options "-O3 -fno-tree-ccp -fno-tree-fre -fno-tree-forwprop -std=c++17" } + +namespace std { +template <class _E> +struct initializer_list { + const int* __begin_; + decltype(sizeof(int)) __size_; +}; +} // namespace std +struct destroyme1 {}; +struct witharg1 { + witharg1(const destroyme1&); + ~witharg1(); +}; +std::initializer_list globalInitList2 = {witharg1(destroyme1()), + witharg1(destroyme1())}; + diff --git a/gcc/testsuite/g++.dg/template/crash90.C b/gcc/testsuite/g++.dg/template/crash90.C index 125ab0a..fee7dc5 100644 --- a/gcc/testsuite/g++.dg/template/crash90.C +++ b/gcc/testsuite/g++.dg/template/crash90.C @@ -4,5 +4,6 @@ template < unsigned > struct A ; template < typename > struct B ; -template < typename T , A < B < T > {} // { dg-error "parse error|non-type|initializer" } +template < typename T , A < B < T > {} // { dg-error "parse error|non-type" } // { dg-error "39:expected" "" { target *-*-* } .-1 } +// { dg-error "37:initializer list" "" { target c++98_only } .-2 } diff --git a/gcc/testsuite/g++.dg/tls/pr102642.C b/gcc/testsuite/g++.dg/tls/pr102642.C new file mode 100644 index 0000000..e3236d3 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/pr102642.C @@ -0,0 +1,10 @@ +// PR c++/102642 +// { dg-do compile { target c++11 } } + +thread_local int *z; // { dg-message "previous declaration" } + +void +foo () +{ + extern thread_local int z; // { dg-error "conflicting declaration" } +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c b/gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c new file mode 100644 index 0000000..da179a2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c @@ -0,0 +1,364 @@ +/* PR middle-end/91647 - missing -Warray-bounds accessing a zero-length array + of a declared object + { dg-do "compile" } + { dg-options "-O2 -Wall -fno-tree-vectorize" } + { dg-require-effective-target alloca } */ + +typedef __INT16_TYPE__ int16_t; +typedef __INT32_TYPE__ int32_t; + +void sink (void*); + +/* Exercise a true flexible member. */ + +struct AX +{ + int32_t n; + int16_t ax[]; // { dg-message "while referencing 'ax'" "member" } +}; + +static void warn_ax_local (struct AX *p) +{ + p->ax[0] = 0; // { dg-warning "\\\[-Warray-bounds" } + p->ax[1] = 1; // { dg-warning "\\\[-Warray-bounds" } +} + +static void nowarn_ax_extern (struct AX *p) +{ + p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999; +} + +static void warn_ax_local_buf (struct AX *p) +{ + p->ax[0] = 4; p->ax[1] = 5; + + p->ax[2] = 6; // { dg-warning "\\\[-Warray-bounds" } + p->ax[3] = 7; // { dg-warning "\\\[-Warray-bounds" } + p->ax[4] = 8; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_ax_extern_buf (struct AX *p) +{ + p->ax[0] = 9; p->ax[1] = 10; p->ax[2] = 11; + + p->ax[3] = 12; // { dg-warning "\\\[-Warray-bounds" } + p->ax[4] = 13; // { dg-warning "\\\[-Warray-bounds" } + p->ax[5] = 14; // { dg-warning "\\\[-Warray-bounds" } +} + +static void nowarn_ax_extern_bufx (struct AX *p) +{ + p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999; +} + +static void nowarn_ax_ref (struct AX *p) +{ + p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999; +} + +void test_ax (struct AX *p, unsigned n) +{ + { + struct AX sax; // { dg-message "defined here" "struct definition" } + warn_ax_local (&sax); + sink (&sax); + } + + { + extern + struct AX xsax; + nowarn_ax_extern (&xsax); + sink (&xsax); + } + + { + /* Verify out-of-bounds access to the local BUF is diagnosed. */ + char ax_buf_p2[sizeof (struct AX) + 2 * sizeof (int16_t)]; + warn_ax_local_buf ((struct AX*) ax_buf_p2); + sink (ax_buf_p2); + } + + { + /* Verify out-of-bounds access to the extern BUF with a known + bound is diagnosed. */ + extern char ax_buf_p3[sizeof (struct AX) + 3 * sizeof (int16_t)]; + warn_ax_extern_buf ((struct AX*) ax_buf_p3); + sink (ax_buf_p3); + } + + { + /* Verify that accesses to BUFX with an unknown bound are not + diagnosed. */ + extern char bufx[]; + nowarn_ax_extern_bufx ((struct AX*) bufx); + sink (bufx); + } + + { + /* Verify that accesses to BUFN with a runtime bound are not + diagnosed. */ + char bufn[n]; + nowarn_ax_extern_bufx ((struct AX*) bufn); + sink (bufn); + } + + nowarn_ax_ref (p); +} + + +/* Exercise a zero-length trailing member array. It's the same as above + except that extern declarations with no definitions are considered to + have zero elements (they can't be initialized to have any). */ + +struct A0 +{ + int32_t n; + int16_t a0[0]; // { dg-message "while referencing 'a0'" "member" } +}; + +static void warn_a0_local (struct A0 *p) +{ + p->a0[0] = 0; // { dg-warning "\\\[-Warray-bounds" } + p->a0[1] = 1; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a0_extern (struct A0 *p) +{ + p->a0[0] = 2; // { dg-warning "\\\[-Warray-bounds" } + p->a0[1] = 3; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a0_local_buf (struct A0 *p) +{ + p->a0[0] = 4; p->a0[1] = 5; + + p->a0[2] = 6; // { dg-warning "\\\[-Warray-bounds" } + p->a0[3] = 7; // { dg-warning "\\\[-Warray-bounds" } + p->a0[4] = 8; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a0_extern_buf (struct A0 *p) +{ + p->a0[0] = 9; p->a0[1] = 10; p->a0[2] = 11; + + p->a0[3] = 12; // { dg-warning "\\\[-Warray-bounds" } + p->a0[4] = 13; // { dg-warning "\\\[-Warray-bounds" } + p->a0[5] = 14; // { dg-warning "\\\[-Warray-bounds" } +} + +static void nowarn_a0_extern_bufx (struct A0 *p) +{ + p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999; +} + +static void nowarn_a0_ref (struct A0 *p) +{ + p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999; +} + +void test_a0 (struct A0 *p, unsigned n) +{ + { + struct A0 sa0; // { dg-message "defined here" "struct definition" } + warn_a0_local (&sa0); + sink (&sa0); + } + + { + extern + struct A0 xsa0; // { dg-message "defined here" "struct definition" } + warn_a0_extern (&xsa0); + sink (&xsa0); + } + + { + /* Verify out-of-bounds access to the local BUF is diagnosed. */ + char a0_buf_p2[sizeof (struct A0) + 2 * sizeof (int16_t)]; + warn_a0_local_buf ((struct A0*) a0_buf_p2); + sink (a0_buf_p2); + } + + { + /* Verify out-of-bounds access to the extern BUF with a known + bound is diagnosed. */ + extern char a0_buf_p3[sizeof (struct A0) + 3 * sizeof (int16_t)]; + warn_a0_extern_buf ((struct A0*) a0_buf_p3); + sink (a0_buf_p3); + } + + { + /* Verify that accesses to BUFX with an unknown bound are not + diagnosed. */ + extern char bufx[]; + nowarn_a0_extern_bufx ((struct A0*) bufx); + sink (bufx); + } + + { + /* Verify that accesses to BUFN with a runtime bound are not + diagnosed. */ + char bufn[n]; + nowarn_a0_extern_bufx ((struct A0*) bufn); + sink (bufn); + } + + nowarn_a0_ref (p); +} + + +/* Exercise a one-element trailing member array. It's the same as above + except that it has exactly one element. */ + +struct A1 +{ + int32_t n; + int16_t a1[1]; // { dg-message "while referencing 'a1'" } +}; + +static void warn_a1_local_noinit (struct A1 *p) +{ + p->a1[0] = 0; + p->a1[1] = 1; // { dg-warning "\\\[-Warray-bounds" } + p->a1[2] = 2; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a1_extern (struct A1 *p) +{ + p->a1[0] = 0; + p->a1[1] = 1; // { dg-warning "\\\[-Warray-bounds" } + p->a1[2] = 2; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a1_init (struct A1 *p) +{ + p->a1[0] = 0; + p->a1[1] = 1; // { dg-warning "\\\[-Warray-bounds" } + p->a1[2] = 2; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a1_local_buf (struct A1 *p) +{ + p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3; + + p->a1[4] = 4; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a1_extern_buf (struct A1 *p) +{ + p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3; p->a1[4] = 4; + + p->a1[5] = 5; // { dg-warning "\\\[-Warray-bounds" } +} + +static void nowarn_a1_extern_bufx (struct A1 *p) +{ + p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999; +} + +static void nowarn_a1_ref (struct A1 *p) +{ + p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999; +} + +void test_a1 (struct A1 *p, unsigned n) +{ + { + struct A1 a1; + warn_a1_local_noinit (&a1); + sink (&a1); + } + + { + extern struct A1 a1x; + warn_a1_extern (&a1x); + sink (&a1x); +} + { + struct A1 a1 = { 0, { 1 } }; + warn_a1_init (&a1); + sink (&a1); + } + + { + /* Verify out-of-bounds access to the local BUF is diagnosed. */ + char buf_p2[sizeof (struct A1) + 2 * sizeof (int16_t)]; + warn_a1_local_buf ((struct A1*) buf_p2); + sink (buf_p2); + } + + { + /* Verify out-of-bounds access to the extern BUF with a known + bound is diagnosed. */ + extern char a1_buf_p3[sizeof (struct A1) + 3 * sizeof (int16_t)]; + warn_a1_extern_buf ((struct A1*) a1_buf_p3); + sink (a1_buf_p3); + } + + { + /* Verify that accesses to BUFX with an unknown bound are not + diagnosed. */ + extern char bufx[]; + nowarn_a1_extern_bufx ((struct A1*) bufx); + sink (bufx); + } + + { + /* Verify that accesses to BUFN with a runtime bound are not + diagnosed. */ + char bufn[n]; + nowarn_a1_extern_bufx ((struct A1*) bufn); + sink (bufn); + } + + nowarn_a1_ref (p); +} + + +/* Exercise a two-element trailing member array. It's treated + the same as an interior array member. */ + +struct A2 +{ + int32_t n; + int16_t a2[2]; // { dg-message "while referencing 'a2'" } +}; + +static void warn_a2_noinit (struct A2 *p) +{ + p->a2[0] = 0; p->a2[1] = 1; + + p->a2[2] = 2; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a2_init (struct A2 *p) +{ + p->a2[0] = 0; p->a2[1] = 1; + + p->a2[2] = 2; // { dg-warning "\\\[-Warray-bounds" } + p->a2[9] = 9; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a2_ref (struct A2 *p) +{ + p->a2[0] = 0; p->a2[1] = 1; + + p->a2[2] = 2; // { dg-warning "\\\[-Warray-bounds" } + p->a2[9] = 9; // { dg-warning "\\\[-Warray-bounds" } +} + +void test_a2 (struct A2 *p) +{ + { + struct A2 a2; + warn_a2_noinit (&a2); + sink (&a2); + } + + { + struct A2 a2 = { 0, { 1, 2 } }; + warn_a2_init (&a2); + sink (&a2); + } + + warn_a2_ref (p); +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-48.c b/gcc/testsuite/gcc.dg/Warray-bounds-48.c index 13373d1..19b7634c 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-48.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-48.c @@ -30,7 +30,7 @@ static void nowarn_ax_extern (struct AX *p) static void warn_ax_local_buf (struct AX *p) { - p->ax[0] = 4; p->ax[1] = 5; + p->ax[0] = 4; p->ax[1] = 5; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v2hi_store && { ! vect_slp_v4hi_store } } } } p->ax[2] = 6; // { dg-warning "\\\[-Warray-bounds" } p->ax[3] = 7; // { dg-warning "\\\[-Warray-bounds" } @@ -130,7 +130,7 @@ static void warn_a0_extern (struct A0 *p) static void warn_a0_local_buf (struct A0 *p) { - p->a0[0] = 4; p->a0[1] = 5; + p->a0[0] = 4; p->a0[1] = 5; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v2hi_store && { ! vect_slp_v4hi_store } } } } p->a0[2] = 6; // { dg-warning "\\\[-Warray-bounds" } p->a0[3] = 7; // { dg-warning "\\\[-Warray-bounds" } diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c b/gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c new file mode 100644 index 0000000..ef8056d --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c @@ -0,0 +1,21 @@ +/* PR middle-end/92333 - missing variable name referencing VLA in warnings + PR middle-end/82608 - missing -Warray-bounds on an out-of-bounds VLA index + { dg-do compile } + { dg-options "-O2 -Wall -fno-tree-vectorize" } */ + +void sink (void*); + +void test_struct_char_vla_location (void) +{ + unsigned nelts = 7; + + struct { + char cvla[nelts]; // { dg-message "declared here|while referencing" } + } s; + + s.cvla[0] = __LINE__; + s.cvla[nelts - 1] = 0; + s.cvla[nelts] = 0; // { dg-warning "\\\[-Warray-bounds" } + + sink (&s); +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-51.c b/gcc/testsuite/gcc.dg/Warray-bounds-51.c index de60d87..8b589f3 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-51.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-51.c @@ -39,7 +39,7 @@ void test_struct_char_vla_location (void) } s; s.cvla[0] = __LINE__; - s.cvla[nelts - 1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } + s.cvla[nelts - 1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v2qi_store } } } s.cvla[nelts] = 0; // { dg-warning "\\\[-Warray-bounds" } sink (&s); diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-87.c b/gcc/testsuite/gcc.dg/Warray-bounds-87.c index a49874d..a545780 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-87.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-87.c @@ -33,7 +33,7 @@ static unsigned int h (int i, int j) case 9: return j; case 10: - return a[i]; // { dg-bogus "-Warray-bounds" "pr101671" { xfail *-*-* } } + return a[i]; // { dg-bogus "-Warray-bounds" "pr101671" } } return 0; } diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c b/gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c new file mode 100644 index 0000000..5089d55 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c @@ -0,0 +1,16 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + { dg-do compile } + { dg-options "-Wall -Warray-parameter=1" } */ + +/* Also verify that -Warray-bounds doesn't trigger for ordinary array + parameters... */ +#pragma GCC optimize ("2,no-tree-vectorize") + +/* ...but does for static arrays. */ +__attribute__ ((noipa)) void +gcas3 (char a[static 3]) +{ + a[0] = 0; a[1] = 1; a[2] = 2; + a[3] = 3; // { dg-warning "\\\[-Warray-bounds" } +} diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-3.c b/gcc/testsuite/gcc.dg/Warray-parameter-3.c index e8a269c..b6ed8da 100644 --- a/gcc/testsuite/gcc.dg/Warray-parameter-3.c +++ b/gcc/testsuite/gcc.dg/Warray-parameter-3.c @@ -77,7 +77,7 @@ gia3 (int a[3]) __attribute__ ((noipa)) void gcas3 (char a[static 3]) { - a[0] = 0; a[1] = 1; a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } + a[0] = 0; a[1] = 1; a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v4qi_store } } } a[3] = 3; // { dg-warning "\\\[-Warray-bounds" } } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c new file mode 100644 index 0000000..de39eaa --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c @@ -0,0 +1,16 @@ +/* Test to verify that past-the-end multibyte writes via lvalues of wider + types than char are diagnosed. + { dg-do compile } + { dg-require-effective-target int32plus } + { dg-options "-O2 -fno-tree-vectorize -Wall -Wno-array-bounds" } */ + +typedef __INT16_TYPE__ int16_t; + +char a4[4], a8[8], a16[16]; + +void test_int16 (void) +{ + char *p = a4 + 1; + *(int16_t*)p = 0; + *(int16_t*)(p + 2) = 0; // { dg-warning "writing 2 bytes into a region of size 1" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c index 7683084..c4a3f05 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c @@ -36,8 +36,8 @@ void test_memcpy_cond (int i) void test_int16 (void) { char *p = a4 + 1; - *(int16_t*)p = 0; // { dg-warning "writing 4 bytes into a region of size 3" "" { target { i?86-*-* x86_64-*-* } } } - *(int16_t*)(p + 2) = 0; // { dg-warning "writing 2 bytes into a region of size 1" "" { xfail { i?86-*-* x86_64-*-* } } } + *(int16_t*)p = 0; // { dg-warning "writing 4 bytes into a region of size 3" "pr102706" { target { vect_slp_v2hi_store } } } + *(int16_t*)(p + 2) = 0; // { dg-warning "writing 2 bytes into a region of size 1" "pr102706" { xfail { vect_slp_v2hi_store } } } } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c new file mode 100644 index 0000000..6f83548 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c @@ -0,0 +1,34 @@ +/* PR middle-end/92312 - bogus -Wstringop-overflow storing into a trailing + array backed by larger buffer + { dg-do compile } + { dg-options "-O2 -fno-tree-vectorize -Wall -Wno-array-bounds" } */ + +struct S0 { char a, b[0]; }; + +void sink (void*); + +void test_store_zero_length (int i) +{ + char a[3]; + struct S0 *p = (struct S0*)a; + p->a = 0; + p->b[0] = 0; + p->b[1] = 1; // { dg-bogus "\\\[-Wstringop-overflow" } + p->b[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + p->b[i] = 2; + sink (p); +} + +struct Sx { char a, b[]; }; + +void test_store_flexarray (int i) +{ + char a[3]; + struct Sx *p = (struct Sx*)a; + p->a = 0; + p->b[0] = 0; + p->b[1] = 1; // { dg-bogus "\\\[-Wstringop-overflow" } + p->b[2] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + p->b[i] = 2; + sink (p); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c index d88bde9..3fccfc9 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c @@ -23,10 +23,10 @@ void test_store_zero_length (int i) { char a[3]; struct S0 *p = (struct S0*)a; - p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } + p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v4qi_store } } } p->b[0] = 0; p->b[1] = 1; // { dg-bogus "\\\[-Wstringop-overflow" } - p->b[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + p->b[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { xfail { vect_slp_v4qi_store } } } p->b[i] = 2; sink (p); } @@ -50,10 +50,10 @@ void test_store_flexarray (int i) { char a[3]; struct Sx *p = (struct Sx*)a; - p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } + p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v4qi_store } } } p->b[0] = 0; p->b[1] = 1; // { dg-bogus "\\\[-Wstringop-overflow" } - p->b[2] = 1; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + p->b[2] = 1; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { xfail { vect_slp_v4qi_store } } } p->b[i] = 2; sink (p); } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c index 09df000..04e91af 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c @@ -58,11 +58,18 @@ void warn_comp_lit_zero (void) void warn_comp_lit (void) { *(AC2*)a1 = Ac2; // { dg-warning "writing 2 bytes into a region of size 1" "pr101475" { xfail *-*-* } } - *(AC4*)a2 = Ac4; // { dg-warning "writing 4 bytes into a region of size 2" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } } - *(AC4*)a3 = Ac4; // { dg-warning "writing 4 bytes into a region of size 3" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } } - *(AC8*)a4 = Ac8; // { dg-warning "writing 8 bytes into a region of size 4" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } } - *(AC8*)a7 = Ac8; // { dg-warning "writing 8 bytes into a region of size 7" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } } - *(AC16*)a15 = Ac16; // { dg-warning "writing 16 bytes into a region of size 15" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } } + // After vectorization, below codes are optimized to + // MEM <vector(4) char> [(char *)&a2] = { 0, 1, 2, 3 }; + // MEM <vector(4) char> [(char *)&a3] = { 0, 1, 2, 3 }; + // MEM <vector(8) char> [(char *)&a4] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + // MEM <vector(8) char> [(char *)&a7] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + // MEM <vector(16) char> [(char *)&a15] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + // and warning should be expected, refer to PR102722. + *(AC4*)a2 = Ac4; // { dg-warning "writing 4 bytes into a region of size 2" "pr101475" { xfail { ! { vect_slp_v4qi_store } } } } + *(AC4*)a3 = Ac4; // { dg-warning "writing 4 bytes into a region of size 3" "pr101475" { xfail { ! { vect_slp_v4qi_store } } } } + *(AC8*)a4 = Ac8; // { dg-warning "writing 8 bytes into a region of size 4" "pr101475" { xfail { ! { vect_slp_v8qi_store } } } } + *(AC8*)a7 = Ac8; // { dg-warning "writing 8 bytes into a region of size 7" "pr101475" { xfail { ! { vect_slp_v8qi_store } } } } + *(AC16*)a15 = Ac16; // { dg-warning "writing 16 bytes into a region of size 15" "pr101475" { xfail { ! { vect_slp_v16qi_store } } } } } void warn_aggr_decl (void) diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c new file mode 100644 index 0000000..71c643b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c @@ -0,0 +1,88 @@ +/* Verify warnings and notes for MAX_EXPRs involving either pointers + to distinct objects or one to a known object and the other to + an unknown one. Unlike for the same object, for unrelated objects + the expected warnings and notes are the same as for MIN_EXPR: when + the order of the objects in the address space cannot be determined + the larger of them is assumed to be used. (This is different for + distinct struct members where the order is given.) + The relational expressions are strictly invalid but that should be + diagnosed by a separate warning. + { dg-do compile } + { dg-options "-O2 -Wno-array-bounds -fno-tree-vectorize" } */ + +#define MAX(p, q) ((p) > (q) ? (p) : (q)) + +/* Verify that even for MAX_EXPR and like for MIN_EXPR, the note points + to the larger of the two objects and mentions the offset into it + (although the offset might be better included in the warning). */ +extern char a3[3]; +extern char a5[5]; // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" } + +void max_a3_a5 (int i) +{ + char *p = a3 + i; + char *q = a5 + i; + + /* The relational expression below is invalid and should be diagnosed + by its own warning independently of -Wstringop-overflow. */ + char *d = MAX (p, q); + + d[2] = 0; + d[3] = 0; + d[4] = 0; + d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" } +} + + +// Same as above but with the larger array as the first MAX_EXPR operand. +extern char b4[4]; +extern char b6[6]; // { dg-message "at offset 6 into destination object 'b6' of size 6" "note" } + +void max_b6_b4 (int i) +{ + char *p = b6 + i; + char *q = b4 + i; + char *d = MAX (p, q); + + d[3] = 0; + d[4] = 0; + d[5] = 0; + d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" } +} + +struct A3_5 +{ + char a3[3]; // { dg-message "at offset 3 into destination object 'a3' of size 3" "pr??????" { xfail *-*-* } } + char a5[5]; // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" } +}; + +void max_A3_A5 (int i, struct A3_5 *pa3_5) +{ + char *p = pa3_5->a3 + i; + char *q = pa3_5->a5 + i; + + char *d = MAX (p, q); + d[2] = 0; + d[3] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr??????" { xfail *-*-* } } + d[4] = 0; + d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" } +} + + +struct B4_B6 +{ + char b4[4]; + char b6[6]; // { dg-message "at offset 6 into destination object 'b6' of size 6" "note" } +}; + +void max_B6_B4 (int i, struct B4_B6 *pb4_b6) +{ + char *p = pb4_b6->b6 + i; + char *q = pb4_b6->b4 + i; + char *d = MAX (p, q); + + d[3] = 0; + d[4] = 0; + d[5] = 0; + d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c index 0c7b53c..5246726 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c @@ -27,10 +27,10 @@ void max_a3_a5 (int i) by its own warning independently of -Wstringop-overflow. */ char *d = MAX (p, q); - d[2] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "" { target { i?86-*-* x86_64-*-* } } } + d[2] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "pr102706" { target { vect_slp_v4qi_store } } } d[3] = 0; d[4] = 0; - d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } } + d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr102706" { xfail { vect_slp_v4qi_store } } } } @@ -44,10 +44,10 @@ void max_b6_b4 (int i) char *q = b4 + i; char *d = MAX (p, q); - d[3] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "" { target { i?86-*-* x86_64-*-* } } } + d[3] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "pr102706" { target { vect_slp_v4qi_store } } } d[4] = 0; d[5] = 0; - d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } } + d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr102706" { xfail { vect_slp_v4qi_store } } } } @@ -82,7 +82,8 @@ void max_d8_p (char *q, int i) struct A3_5 { char a3[3]; // { dg-message "at offset 3 into destination object 'a3' of size 3" "pr??????" { xfail *-*-* } } - char a5[5]; // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" { xfail { i?86-*-* x86_64-*-* } } } + // refer to pr102697 for xfail + char a5[5]; // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" { xfail { vect_slp_v4qi_store } } } }; void max_A3_A5 (int i, struct A3_5 *pa3_5) @@ -95,14 +96,15 @@ void max_A3_A5 (int i, struct A3_5 *pa3_5) d[2] = 0; d[3] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr??????" { xfail *-*-* } } d[4] = 0; - d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } } + d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr102697" { xfail { vect_slp_v4qi_store } } } } struct B4_B6 { char b4[4]; - char b6[6]; // { dg-message "at offset \[^a-zA-Z\n\r\]*6\[^a-zA-Z0-9\]* into destination object 'b6' of size 6" "note" { xfail { i?86-*-* x86_64-*-* } } } + // refer to pr102697 for xfail + char b6[6]; // { dg-message "at offset \[^a-zA-Z\n\r\]*6\[^a-zA-Z0-9\]* into destination object 'b6' of size 6" "note" { xfail { vect_slp_v4qi_store } } } }; void max_B6_B4 (int i, struct B4_B6 *pb4_b6) @@ -114,7 +116,7 @@ void max_B6_B4 (int i, struct B4_B6 *pb4_b6) d[3] = 0; d[4] = 0; d[5] = 0; - d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } } + d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr102697" { xfail { vect_slp_v4qi_store } } } } diff --git a/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2-novec.c b/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2-novec.c new file mode 100644 index 0000000..8e023b7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2-novec.c @@ -0,0 +1,45 @@ +/* Test to verify that -Wzero-length-bounds and not -Warray-bounds is + issued for accesses to interior zero-length array members that are + within the bounds of the enclosing struct. + { dg-do compile } + { dg-options "-O2 -Wall -fno-tree-vectorize" } */ + +void sink (void*); + +struct A { int i; }; +struct B { int j; struct A a[0]; }; + +struct C +{ + struct B b1; + struct B b2; +}; + +char cbuf1[1 * sizeof (struct C)]; +char cbuf2[2 * sizeof (struct C)] = { }; + +void test_C_global_buf (void) +{ + struct C *p = (struct C*)&cbuf1; + + p->b1.a[-1].i = 0; // { dg-warning "\\\[-Warray-bounds" } + p->b1.a[ 0].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" } + p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Warray-bounds" } + sink (p); + + p->b2.a[ 0].i = 0; // { dg-warning "\\\[-Warray-bounds" } + p->b2.a[ 1].i = 0; // { dg-warning "\\\[-Warray-bounds" } + sink (p); + + p = (struct C*)&cbuf2; + p->b1.a[-1].i = 0; // { dg-warning "\\\[-Warray-bounds" } + p->b1.a[ 0].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" } + p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" } + sink (p); + + p->b2.a[ 0].i = 0; + p->b2.a[ 1].i = 0; + p->b2.a[ 2].i = 0; // { dg-warning "\\\[-Warray-bounds" } + p->b2.a[ 3].i = 0; // { dg-warning "\\\[-Warray-bounds" } + sink (p); +} diff --git a/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2.c b/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2.c index 841b2bf..b232149 100644 --- a/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2.c +++ b/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2.c @@ -87,7 +87,7 @@ void test_C_global_buf (void) p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" } sink (p); - p->b2.a[ 0].i = 0; + p->b2.a[ 0].i = 0; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v2si_store && { ! vect_slp_v4si_store } } } } p->b2.a[ 1].i = 0; p->b2.a[ 2].i = 0; // { dg-warning "\\\[-Warray-bounds" } p->b2.a[ 3].i = 0; // { dg-warning "\\\[-Warray-bounds" } diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94851-2.c b/gcc/testsuite/gcc.dg/analyzer/pr94851-2.c index 0acf488..62176bd 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr94851-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr94851-2.c @@ -45,7 +45,7 @@ int pamark(void) { if (curbp->b_amark == (AMARK *)NULL) curbp->b_amark = p; else - last->m_next = p; /* { dg-warning "dereference of NULL 'last'" "deref" { xfail *-*-* } } */ + last->m_next = p; /* { dg-warning "dereference of NULL 'last'" "deref" } */ } p->m_name = (char)c; /* { dg-bogus "leak of 'p'" "bogus leak" } */ diff --git a/gcc/testsuite/gcc.dg/graphite/pr69728.c b/gcc/testsuite/gcc.dg/graphite/pr69728.c index 69e2831..a6f3857 100644 --- a/gcc/testsuite/gcc.dg/graphite/pr69728.c +++ b/gcc/testsuite/gcc.dg/graphite/pr69728.c @@ -24,6 +24,4 @@ fn1 () run into scheduling issues before here, not being able to handle empty domains. */ -/* XFAILed by fix for PR86865. */ - -/* { dg-final { scan-tree-dump "loop nest optimized" "graphite" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump "loop nest optimized" "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/scop-dsyr2k.c b/gcc/testsuite/gcc.dg/graphite/scop-dsyr2k.c index 925ae30..41c91b9 100644 --- a/gcc/testsuite/gcc.dg/graphite/scop-dsyr2k.c +++ b/gcc/testsuite/gcc.dg/graphite/scop-dsyr2k.c @@ -17,4 +17,4 @@ void dsyr2k(int N) { #pragma endscop } -/* { dg-final { scan-tree-dump-times "number of SCoPs: 1" 1 "graphite" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "number of SCoPs: 1" 1 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/scop-dsyrk.c b/gcc/testsuite/gcc.dg/graphite/scop-dsyrk.c index b748946..e01a517 100644 --- a/gcc/testsuite/gcc.dg/graphite/scop-dsyrk.c +++ b/gcc/testsuite/gcc.dg/graphite/scop-dsyrk.c @@ -19,4 +19,4 @@ void dsyrk(int N) #pragma endscop } -/* { dg-final { scan-tree-dump-times "number of SCoPs: 1" 1 "graphite" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "number of SCoPs: 1" 1 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/loop-8.c b/gcc/testsuite/gcc.dg/loop-8.c index 90ea1c4..a685fc2 100644 --- a/gcc/testsuite/gcc.dg/loop-8.c +++ b/gcc/testsuite/gcc.dg/loop-8.c @@ -11,18 +11,23 @@ f (int *a, int *b) { int i; - for (i = 0; i < 100; i++) + i = 100; + if (i > 0) { - int d = 42; + do + { + int d = 42; - a[i] = d; - if (i % 2) - d = i; - b[i] = d; + a[i] = d; + if (i % 2) + d = i; + b[i] = d; + ++i; + } + while (i < 100); } } /* Load of 42 is moved out of the loop, introducing a new pseudo register. */ -/* { dg-final { scan-rtl-dump-times "Decided" 1 "loop2_invariant" } } */ /* { dg-final { scan-rtl-dump-not "without introducing a new temporary register" "loop2_invariant" } } */ diff --git a/gcc/testsuite/gcc.dg/plugin/gil-1.c b/gcc/testsuite/gcc.dg/plugin/gil-1.c index 66872f0..6cbc197 100644 --- a/gcc/testsuite/gcc.dg/plugin/gil-1.c +++ b/gcc/testsuite/gcc.dg/plugin/gil-1.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-fanalyzer" } */ +/* { dg-require-effective-target analyzer } */ #include "gil.h" diff --git a/gcc/testsuite/gcc.dg/pr102764.c b/gcc/testsuite/gcc.dg/pr102764.c new file mode 100644 index 0000000..ea1c634 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr102764.c @@ -0,0 +1,14 @@ +/* PR middle-end/102764 */ +/* Reported by Chengnian Sun <cnsun@uwaterloo.ca> */ + +/* { dg-do compile } */ +/* { dg-options "-O3 -fcompare-debug" } */ + +volatile int a; + +void main (void) +{ + for (int i = 0; i < 1000; i++) + if (i % 17) + a++; +} diff --git a/gcc/testsuite/gcc.dg/pr102827.c b/gcc/testsuite/gcc.dg/pr102827.c new file mode 100644 index 0000000..eed3eba --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr102827.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O -ftree-vectorize --param ssa-name-def-chain-limit=0" } */ +/* { dg-additional-options "-mavx" { target { x86_64-*-* i?86-*-* } } } */ + +void +test_double_double_nugt_var (double *dest, double *src, int b, int i) +{ + while (i < 1) + { + dest[i] = b ? src[i] : 0.0; + ++i; + } +} diff --git a/gcc/testsuite/gcc.dg/pr36902.c b/gcc/testsuite/gcc.dg/pr36902.c index 7dafc9a..365a26e 100644 --- a/gcc/testsuite/gcc.dg/pr36902.c +++ b/gcc/testsuite/gcc.dg/pr36902.c @@ -24,10 +24,9 @@ struct { unsigned char pcr_select[4]; } sel; +unsigned char buf[64]; int bar(void) { - static unsigned char buf[64]; - sel.size_of_select = 3; foo(buf, sel.pcr_select, sel.size_of_select); @@ -52,8 +51,6 @@ foo2(unsigned char * to, const unsigned char * from, int n) int baz(void) { - static unsigned char buf[64]; - sel.size_of_select = 5; foo2(buf, sel.pcr_select, sel.size_of_select); diff --git a/gcc/testsuite/gcc.dg/shrink-wrap-loop.c b/gcc/testsuite/gcc.dg/shrink-wrap-loop.c index 6e1be893..ddc99e6 100644 --- a/gcc/testsuite/gcc.dg/shrink-wrap-loop.c +++ b/gcc/testsuite/gcc.dg/shrink-wrap-loop.c @@ -1,58 +1,6 @@ /* { dg-do compile { target { { { i?86-*-* x86_64-*-* } && lp64 } || { arm_thumb2 } } } } */ /* { dg-options "-O2 -fdump-rtl-pro_and_epilogue" } */ -/* -Our new threader is threading things a bit too early, and causing the -testcase in gcc.dg/shrink-wrap-loop.c to fail. - - The gist is this BB inside a loop: - - <bb 6> : - # p_2 = PHI <p2_6(D)(2), p_12(5)> - if (p_2 != 0B) - goto <bb 3>; [INV] - else - goto <bb 7>; [INV] - -Our threader can move this check outside of the loop (good). This is -done before branch probabilities are calculated and causes the probs -to be calculated as: - -<bb 2> [local count: 216361238]: - if (p2_6(D) != 0B) - goto <bb 7>; [54.59%] - else - goto <bb 6>; [45.41%] - -Logically this seems correct to me. A simple check outside of a loop -should slightly but not overwhelmingly favor a non-zero value. - -Interestingly however, the old threader couldn't get this, but the IL -ended up identical, albeit with different probabilities. What happens -is that, because the old code could not thread this, the p2 != 0 check -would remain inside the loop and probs would be calculated thusly: - - <bb 6> [local count: 1073741824]: - # p_2 = PHI <p2_6(D)(2), p_12(5)> - if (p_2 != 0B) - goto <bb 3>; [94.50%] - else - goto <bb 7>; [5.50%] - -Then when the loop header copying pass ("ch") shuffled things around, -the IL would end up identical to my early threader code, but with the -probabilities would remain as 94.5/5.5. - -The above discrepancy causes the RTL ifcvt pass to generate different -code, and by the time we get to the shrink wrapping pass, things look -sufficiently different such that the legacy code can actually shrink -wrap, whereas our new code does not. - -IMO, if the loop-ch pass moves conditionals outside of a loop, the -probabilities should be adjusted, but that does mean the shrink wrap -won't happen for this contrived testcase. - */ - int foo (int *p1, int *p2); int @@ -68,4 +16,4 @@ test (int *p1, int *p2) return 1; } -/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" { xfail *-*-* } } } */ +/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c index b55a533..f8a6495 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c @@ -39,4 +39,4 @@ int main1 () which is folded by vectorizer. Both outgoing edges must have probability 100% so the resulting profile match after folding. */ /* { dg-final { scan-tree-dump-times "Invalid sum of outgoing probabilities 200.0" 1 "ifcvt" } } */ -/* { dg-final { scan-tree-dump-times "Invalid sum of incoming counts" 1 "ifcvt" } } */ +/* { dg-final { scan-tree-dump-times "Invalid sum of incoming counts" 2 "ifcvt" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c index 51b3b7a..43f046e 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c @@ -35,10 +35,7 @@ void foo (void) /* First, we should simplify the bits < 0 test within the loop. */ /* { dg-final { scan-tree-dump-times "Simplified relational" 1 "evrp" } } */ -/* Second, we should thread the edge out of the loop via the break - statement. We also realize that the final bytes == 0 test is useless, - and thread over it. We also know that toread != 0 is useless when - entering while loop and thread over it. */ -/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp-thread1" } } */ +/* We used to check for 3 threaded jumps here, but they all would + rotate the loop. */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c b/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c index 2caa1f5..764b3fe 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c @@ -56,11 +56,7 @@ main (int argc, char argv[]) return crc; } -/* Previously we had 3 jump threads, but one of them crossed loops. - The reason the old threader was allowing it, was because there was - an ASSERT_EXPR getting in the way. Without the ASSERT_EXPR, we - have an empty pre-header block as the final block in the thread, - which the threader will simply join with the next block which *is* - in a different loop. */ -/* { dg-final { scan-tree-dump-times "Registering jump thread" 2 "vrp-thread1" } } */ +/* None of the threads we can get in vrp-thread1 are valid. They all + cross or rotate loops. */ +/* { dg-final { scan-tree-dump-not "Registering jump thread" "vrp-thread1" } } */ /* { dg-final { scan-tree-dump-not "joiner" "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c index a2386ba..eab3a25 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-ffast-math -O3 -fdump-tree-vrp-thread1-details" } */ +/* { dg-options "-ffast-math -O3 -fdump-tree-dom3-details" } */ int I = 50, J = 50; int S, L; @@ -39,4 +39,8 @@ void foo (int K) bar (LD, SD); } } -/* { dg-final { scan-tree-dump-times "Threaded jump " 2 "vrp-thread1" } } */ + +/* We used to get 1 vrp-thread1 candidates here, but they now get + deferred until after loop opts are done, because they were rotating + loops. */ +/* { dg-final { scan-tree-dump-times "Threaded jump " 2 "dom3" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c index 18f7aab..f2a5e78 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c @@ -123,8 +123,7 @@ enum STATES FMS( u8 **in , u32 *transitions) { aarch64 has the highest CASE_VALUES_THRESHOLD in GCC. It's high enough to change decisions in switch expansion which in turn can expose new jump threading opportunities. Skip the later tests on aarch64. */ -/* { dg-final { scan-tree-dump "Jumps threaded: \[7-9\]" "thread1" } } */ -/* { dg-final { scan-tree-dump-times "Invalid sum" 1 "thread1" } } */ +/* { dg-final { scan-tree-dump "Jumps threaded: \[7-9\]" "thread2" } } */ /* { dg-final { scan-tree-dump-not "optimizing for size" "thread1" } } */ /* { dg-final { scan-tree-dump-not "optimizing for size" "thread2" } } */ /* { dg-final { scan-tree-dump-not "optimizing for size" "thread3" { target { ! aarch64*-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c deleted file mode 100644 index 0246ebf..0000000 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c +++ /dev/null @@ -1,27 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -std=gnu89 --param logical-op-non-short-circuit=0" } */ - -#include "ssa-dom-thread-4.c" - -/* On targets that define LOGICAL_OP_NON_SHORT_CIRCUIT to 0, we split both - "a_elt || b_elt" and "b_elt && kill_elt" into two conditions each, - rather than using "(var1 != 0) op (var2 != 0)". Also, as on other targets, - we duplicate the header of the inner "while" loop. There are then - 4 threading opportunities: - - 1x "!a_elt && b_elt" in the outer "while" loop - -> the start of the inner "while" loop, - skipping the known-true "b_elt" in the first condition. - 1x "!b_elt" in the first condition - -> the outer "while" loop's continuation point, - skipping the known-false "b_elt" in the second condition. - 2x "kill_elt->indx >= b_elt->indx" in the first "while" loop - -> "kill_elt->indx == b_elt->indx" in the second condition, - skipping the known-true "b_elt && kill_elt" in the second - condition. - - All the cases are picked up by VRP1 as jump threads. */ - -/* There used to be 6 jump threads found by thread1, but they all - depended on threading through distinct loops in ethread. */ -/* { dg-final { scan-tree-dump-times "Threaded" 2 "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c deleted file mode 100644 index 8f0a12c..0000000 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c +++ /dev/null @@ -1,21 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp-thread1-stats -fdump-tree-dom2-stats" } */ - -void bla(); - -/* In the following case, we should be able to thread edge through - the loop header. */ - -void thread_entry_through_header (void) -{ - int i; - - for (i = 0; i < 170; i++) - bla (); -} - -/* There's a single jump thread that should be handled by the VRP - jump threading pass. */ -/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "vrp-thread1"} } */ -/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 0 "vrp-thread1"} } */ -/* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c index 46e464f..9cd4635 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -fdump-tree-dom2-details -std=gnu89 --param logical-op-non-short-circuit=1" } */ +/* { dg-options "-O2 -fdump-tree-vrp-thread2-details -fdump-tree-dom2-details -std=gnu89 --param logical-op-non-short-circuit=1" } */ struct bitmap_head_def; typedef struct bitmap_head_def *bitmap; typedef const struct bitmap_head_def *const_bitmap; @@ -53,10 +53,8 @@ bitmap_ior_and_compl (bitmap dst, const_bitmap a, const_bitmap b, return changed; } -/* The block starting the second conditional has 3 incoming edges, - we should thread all three, but due to a bug in the threading - code we missed the edge when the first conditional is false - (b_elt is zero, which means the second conditional is always - zero. VRP1 catches all three. */ -/* { dg-final { scan-tree-dump-times "Registering jump thread" 2 "vrp-thread1" } } */ -/* { dg-final { scan-tree-dump-times "Path crosses loops" 1 "vrp-thread1" } } */ +/* We used to catch 3 jump threads in vrp-thread1, but they all + rotated the loop, so they were disallowed. This in turn created + other opportunities for the other threaders which result in the the + post-loop threader (vrp-thread2) catching more. */ +/* { dg-final { scan-tree-dump-times "Registering jump thread" 5 "vrp-thread2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c deleted file mode 100644 index b0a7d42..0000000 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c +++ /dev/null @@ -1,44 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-thread1-details -fdump-tree-thread3-details" } */ - -/* { dg-final { scan-tree-dump-times "Registering jump" 6 "thread1" } } */ -/* { dg-final { scan-tree-dump-times "Registering jump" 1 "thread3" } } */ - -int sum0, sum1, sum2, sum3; -int foo (char *s, char **ret) -{ - int state=0; - char c; - - for (; *s && state != 4; s++) - { - c = *s; - if (c == '*') - { - s++; - break; - } - switch (state) - { - case 0: - if (c == '+') - state = 1; - else if (c != '-') - sum0+=c; - break; - case 1: - if (c == '+') - state = 2; - else if (c == '-') - state = 0; - else - sum1+=c; - break; - default: - break; - } - - } - *ret = s; - return state; -} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c index 16abcde..1da00a6 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c @@ -1,15 +1,14 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-thread2-stats -fdump-tree-dom2-stats -fdump-tree-thread3-stats -fdump-tree-dom3-stats -fdump-tree-vrp2-stats -fno-guess-branch-probability" } */ -/* { dg-final { scan-tree-dump "Jumps threaded: 12" "thread1" } } */ -/* { dg-final { scan-tree-dump "Jumps threaded: 5" "thread3" { target { ! aarch64*-*-* } } } } */ +/* { dg-final { scan-tree-dump "Jumps threaded: 12" "thread3" } } */ /* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2" } } */ /* aarch64 has the highest CASE_VALUES_THRESHOLD in GCC. It's high enough to change decisions in switch expansion which in turn can expose new jump threading opportunities. Skip the later tests on aarch64. */ /* { dg-final { scan-tree-dump-not "Jumps threaded" "dom3" { target { ! aarch64*-*-* } } } } */ -/* { dg-final { scan-tree-dump-not "Jumps threaded" "vrp2" { target { ! aarch64*-*-* } } } } */ +/* { dg-final { scan-tree-dump-not "Jumps threaded" "vrp-thread2" { target { ! aarch64*-*-* } } } } */ enum STATE { S0=0, diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-invalid.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-invalid.c new file mode 100644 index 0000000..bd56a62 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-invalid.c @@ -0,0 +1,102 @@ +// { dg-do compile } +// { dg-options "-O2 -fgimple -fdump-statistics" } +// +// This is a collection of seemingly threadble paths that should not be allowed. + +void foobar (int); + +// Possible thread from 2->4->3, but it would rotate the loop. +void __GIMPLE (ssa) +f1 () +{ + int i; + + // Pre-header. + __BB(2): + goto __BB4; + + // Latch. + __BB(3): + foobar (i_1); + i_5 = i_1 + 1; + goto __BB4; + + __BB(4,loop_header(1)): + i_1 = __PHI (__BB2: 0, __BB3: i_5); + if (i_1 != 101) + goto __BB3; + else + goto __BB5; + + __BB(5): + return; + +} + +// Possible thread from 2->3->5 but threading through the empty latch +// would create a non-empty latch. +void __GIMPLE (ssa) +f2 () +{ + int i; + + // Pre-header. + __BB(2): + goto __BB3; + + __BB(3,loop_header(1)): + i_8 = __PHI (__BB5: i_5, __BB2: 0); + foobar (i_8); + i_5 = i_8 + 1; + if (i_5 != 256) + goto __BB5; + else + goto __BB4; + + // Latch. + __BB(5): + goto __BB3; + + __BB(4): + return; + +} + +// Possible thread from 3->5->6->3 but this would thread through the +// header but not exit the loop. +int __GIMPLE (ssa) +f3 (int a) +{ + int i; + + __BB(2): + goto __BB6; + + __BB(3): + if (i_1 != 0) + goto __BB4; + else + goto __BB5; + + __BB(4): + foobar (5); + goto __BB5; + + // Latch. + __BB(5): + i_7 = i_1 + 1; + goto __BB6; + + __BB(6,loop_header(1)): + i_1 = __PHI (__BB2: 1, __BB5: i_7); + if (i_1 <= 99) + goto __BB3; + else + goto __BB7; + + __BB(7): + return; + +} + +// { dg-final { scan-tree-dump-not "Jumps threaded" "statistics" } } diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-16.c b/gcc/testsuite/gcc.dg/vect/bb-slp-16.c index e68a9b6..82fae06 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-16.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-16.c @@ -1,4 +1,6 @@ /* { dg-require-effective-target vect_int } */ +/* The SLP vectorization happens as part of the if-converted loop body. */ +/* { dg-additional-options "-fdump-tree-vect-details" } */ #include <stdarg.h> #include "tree-vect.h" @@ -65,5 +67,4 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp1" } } */ - +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fmla_intrinsic_1.c b/gcc/testsuite/gcc.target/aarch64/fmla_intrinsic_1.c index 59ad41e..adb787a 100644 --- a/gcc/testsuite/gcc.target/aarch64/fmla_intrinsic_1.c +++ b/gcc/testsuite/gcc.target/aarch64/fmla_intrinsic_1.c @@ -11,6 +11,7 @@ extern void abort (void); #define TEST_VMLA(q1, q2, size, in1_lanes, in2_lanes) \ static void \ +__attribute__((noipa,noinline)) \ test_vfma##q1##_lane##q2##_f##size (float##size##_t * res, \ const float##size##_t *in1, \ const float##size##_t *in2) \ @@ -104,12 +105,12 @@ main (int argc, char **argv) vfmaq_laneq_f32. */ /* { dg-final { scan-assembler-times "fmla\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, v\[0-9\]+\.s\\\[\[0-9\]+\\\]" 2 } } */ -/* vfma_lane_f64. */ -/* { dg-final { scan-assembler-times "fmadd\\td\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+" 1 } } */ +/* vfma_lane_f64. + vfma_laneq_f64. */ +/* { dg-final { scan-assembler-times "fmadd\\td\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+" 2 } } */ /* vfmaq_lane_f64. - vfma_laneq_f64. vfmaq_laneq_f64. */ -/* { dg-final { scan-assembler-times "fmla\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 3 } } */ +/* { dg-final { scan-assembler-times "fmla\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fmls_intrinsic_1.c b/gcc/testsuite/gcc.target/aarch64/fmls_intrinsic_1.c index 2d5a3d3..865def2 100644 --- a/gcc/testsuite/gcc.target/aarch64/fmls_intrinsic_1.c +++ b/gcc/testsuite/gcc.target/aarch64/fmls_intrinsic_1.c @@ -11,6 +11,7 @@ extern void abort (void); #define TEST_VMLS(q1, q2, size, in1_lanes, in2_lanes) \ static void \ +__attribute__((noipa,noinline)) \ test_vfms##q1##_lane##q2##_f##size (float##size##_t * res, \ const float##size##_t *in1, \ const float##size##_t *in2) \ @@ -105,12 +106,12 @@ main (int argc, char **argv) vfmsq_laneq_f32. */ /* { dg-final { scan-assembler-times "fmls\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, v\[0-9\]+\.s\\\[\[0-9\]+\\\]" 2 } } */ -/* vfms_lane_f64. */ -/* { dg-final { scan-assembler-times "fmsub\\td\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+" 1 } } */ +/* vfms_lane_f64. + vfms_laneq_f64. */ +/* { dg-final { scan-assembler-times "fmsub\\td\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+" 2 } } */ /* vfmsq_lane_f64. - vfms_laneq_f64. vfmsq_laneq_f64. */ -/* { dg-final { scan-assembler-times "fmls\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 3 } } */ +/* { dg-final { scan-assembler-times "fmls\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fmul_intrinsic_1.c b/gcc/testsuite/gcc.target/aarch64/fmul_intrinsic_1.c index 8b0880d..d01095e 100644 --- a/gcc/testsuite/gcc.target/aarch64/fmul_intrinsic_1.c +++ b/gcc/testsuite/gcc.target/aarch64/fmul_intrinsic_1.c @@ -9,6 +9,7 @@ extern double fabs (double); #define TEST_VMUL(q1, q2, size, in1_lanes, in2_lanes) \ static void \ +__attribute__((noipa,noinline)) \ test_vmul##q1##_lane##q2##_f##size (float##size##_t * res, \ const float##size##_t *in1, \ const float##size##_t *in2) \ @@ -104,12 +105,12 @@ main (int argc, char **argv) vmulq_laneq_f32. */ /* { dg-final { scan-assembler-times "fmul\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, v\[0-9\]+\.s\\\[\[0-9\]+\\\]" 2 } } */ -/* vmul_lane_f64. */ -/* { dg-final { scan-assembler-times "fmul\\td\[0-9\]+, d\[0-9\]+, d\[0-9\]+" 1 } } */ +/* vmul_lane_f64. + Vmul_laneq_f64. */ +/* { dg-final { scan-assembler-times "fmul\\td\[0-9\]+, d\[0-9\]+, d\[0-9\]+" 2 } } */ -/* vmul_laneq_f64. - vmulq_lane_f64. +/* vmulq_lane_f64. vmulq_laneq_f64. */ -/* { dg-final { scan-assembler-times "fmul\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 3 } } */ +/* { dg-final { scan-assembler-times "fmul\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/frint.x b/gcc/testsuite/gcc.target/aarch64/frint.x index 1403740..d598a25 100644 --- a/gcc/testsuite/gcc.target/aarch64/frint.x +++ b/gcc/testsuite/gcc.target/aarch64/frint.x @@ -4,6 +4,7 @@ extern GPF SUFFIX(floor) (GPF); extern GPF SUFFIX(nearbyint) (GPF); extern GPF SUFFIX(rint) (GPF); extern GPF SUFFIX(round) (GPF); +extern GPF SUFFIX(roundeven) (GPF); GPF test1a (GPF x) { @@ -64,3 +65,14 @@ GPF test6b (GPF x) { return SUFFIX(round)(x); } + +GPF test7a (GPF x) +{ + return SUFFIX(__builtin_roundeven)(x); +} + +GPF test7b (GPF x) +{ + return SUFFIX(roundeven)(x); +} + diff --git a/gcc/testsuite/gcc.target/aarch64/frint_double.c b/gcc/testsuite/gcc.target/aarch64/frint_double.c index 9613949..1d28eb0 100644 --- a/gcc/testsuite/gcc.target/aarch64/frint_double.c +++ b/gcc/testsuite/gcc.target/aarch64/frint_double.c @@ -12,3 +12,4 @@ /* { dg-final { scan-assembler-times "frinti\td\[0-9\]" 2 } } */ /* { dg-final { scan-assembler-times "frintx\td\[0-9\]" 2 } } */ /* { dg-final { scan-assembler-times "frinta\td\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "frintn\td\[0-9\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/frint_float.c b/gcc/testsuite/gcc.target/aarch64/frint_float.c index 493ec37..530cf97 100644 --- a/gcc/testsuite/gcc.target/aarch64/frint_float.c +++ b/gcc/testsuite/gcc.target/aarch64/frint_float.c @@ -12,3 +12,4 @@ /* { dg-final { scan-assembler-times "frinti\ts\[0-9\]" 2 } } */ /* { dg-final { scan-assembler-times "frintx\ts\[0-9\]" 2 } } */ /* { dg-final { scan-assembler-times "frinta\ts\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "frintn\ts\[0-9\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/merge_trunc1.c b/gcc/testsuite/gcc.target/aarch64/merge_trunc1.c new file mode 100644 index 0000000..0721706 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/merge_trunc1.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ffast-math" } */ + +float +f1 (float x) +{ + int y = x; + + return (float) y; +} + +double +f2 (double x) +{ + long y = x; + + return (double) y; +} + +float +f3 (double x) +{ + int y = x; + + return (float) y; +} + +double +f4 (float x) +{ + int y = x; + + return (double) y; +} + +/* { dg-final { scan-assembler "frintz\\ts\[0-9\]+, s\[0-9\]+" } } */ +/* { dg-final { scan-assembler "frintz\\td\[0-9\]+, d\[0-9\]+" } } */ +/* { dg-final { scan-assembler "fcvtzs\\tw\[0-9\]+, d\[0-9\]+" } } */ +/* { dg-final { scan-assembler "scvtf\\ts\[0-9\]+, w\[0-9\]+" } } */ +/* { dg-final { scan-assembler "fcvtzs\\tw\[0-9\]+, s\[0-9\]+" } } */ +/* { dg-final { scan-assembler "scvtf\\td\[0-9\]+, w\[0-9\]+" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/mla_intrinsic_1.c b/gcc/testsuite/gcc.target/aarch64/mla_intrinsic_1.c index 46b3c78..885bfb3 100644 --- a/gcc/testsuite/gcc.target/aarch64/mla_intrinsic_1.c +++ b/gcc/testsuite/gcc.target/aarch64/mla_intrinsic_1.c @@ -11,6 +11,7 @@ extern void abort (void); #define TEST_VMLA(q, su, size, in1_lanes, in2_lanes) \ static void \ +__attribute__((noipa,noinline)) \ test_vmlaq_lane##q##_##su##size (MAP##su (size, ) * res, \ const MAP##su(size, ) *in1, \ const MAP##su(size, ) *in2) \ diff --git a/gcc/testsuite/gcc.target/aarch64/mls_intrinsic_1.c b/gcc/testsuite/gcc.target/aarch64/mls_intrinsic_1.c index e01a4f6..df046ce 100644 --- a/gcc/testsuite/gcc.target/aarch64/mls_intrinsic_1.c +++ b/gcc/testsuite/gcc.target/aarch64/mls_intrinsic_1.c @@ -11,6 +11,7 @@ extern void abort (void); #define TEST_VMLS(q, su, size, in1_lanes, in2_lanes) \ static void \ +__attribute__((noipa,noinline)) \ test_vmlsq_lane##q##_##su##size (MAP##su (size, ) * res, \ const MAP##su(size, ) *in1, \ const MAP##su(size, ) *in2) \ diff --git a/gcc/testsuite/gcc.target/aarch64/mul_intrinsic_1.c b/gcc/testsuite/gcc.target/aarch64/mul_intrinsic_1.c index 00ef4f2..517b937 100644 --- a/gcc/testsuite/gcc.target/aarch64/mul_intrinsic_1.c +++ b/gcc/testsuite/gcc.target/aarch64/mul_intrinsic_1.c @@ -11,6 +11,7 @@ extern void abort (void); #define TEST_VMUL(q, su, size, in1_lanes, in2_lanes) \ static void \ +__attribute__((noipa,noinline)) \ test_vmulq_lane##q##_##su##size (MAP##su (size, ) * res, \ const MAP##su(size, ) *in1, \ const MAP##su(size, ) *in2) \ diff --git a/gcc/testsuite/gcc.target/aarch64/mvn-cmeq0-1.c b/gcc/testsuite/gcc.target/aarch64/mvn-cmeq0-1.c new file mode 100644 index 0000000..27b3909 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/mvn-cmeq0-1.c @@ -0,0 +1,17 @@ +/* { dg-do assemble } */ +/* { dg-options "-O --save-temps" } */ + +#include <arm_neon.h> + +uint8x8_t bar(int16x8_t abs_row0, int16x8_t row0) { + uint16x8_t row0_diff = + vreinterpretq_u16_s16(veorq_s16(abs_row0, vshrq_n_s16(row0, 15))); + uint8x8_t abs_row0_gt0 = + vmovn_u16(vcgtq_u16(vreinterpretq_u16_s16(abs_row0), vdupq_n_u16(0))); + return abs_row0_gt0; +} + + +/* { dg-final { scan-assembler-times {\tcmtst\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tcmeq\t} } } */ +/* { dg-final { scan-assembler-not {\tnot\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/narrow_high_combine.c b/gcc/testsuite/gcc.target/aarch64/narrow_high_combine.c index 50ecab0..fa61196 100644 --- a/gcc/testsuite/gcc.target/aarch64/narrow_high_combine.c +++ b/gcc/testsuite/gcc.target/aarch64/narrow_high_combine.c @@ -225,7 +225,8 @@ TEST_2_UNARY (vqmovun, uint32x4_t, int64x2_t, s64, u32) /* { dg-final { scan-assembler-times "\\tuqshrn2\\tv" 6} } */ /* { dg-final { scan-assembler-times "\\tsqrshrn2\\tv" 6} } */ /* { dg-final { scan-assembler-times "\\tuqrshrn2\\tv" 6} } */ -/* { dg-final { scan-assembler-times "\\txtn2\\tv" 12} } */ +/* { dg-final { scan-assembler-times "\\txtn2\\tv" 6} } */ +/* { dg-final { scan-assembler-times "\\tuzp1\\tv" 6} } */ /* { dg-final { scan-assembler-times "\\tuqxtn2\\tv" 6} } */ /* { dg-final { scan-assembler-times "\\tsqxtn2\\tv" 6} } */ /* { dg-final { scan-assembler-times "\\tsqxtun2\\tv" 6} } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shl-combine-2.c b/gcc/testsuite/gcc.target/aarch64/shl-combine-2.c new file mode 100644 index 0000000..6a0331f --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shl-combine-2.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE char + +void e (signed TYPE * restrict a, signed TYPE *b, int n) +{ + for (int i = 0; i < n; i++) + b[i] = a[i] >> (sizeof(TYPE)*8)-1; +} + +/* { dg-final { scan-assembler-times {\tcmlt\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tsshr\t} } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/shl-combine-3.c b/gcc/testsuite/gcc.target/aarch64/shl-combine-3.c new file mode 100644 index 0000000..2086b24a --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shl-combine-3.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE short + +void e (signed TYPE * restrict a, signed TYPE *b, int n) +{ + for (int i = 0; i < n; i++) + b[i] = a[i] >> (sizeof(TYPE)*8)-1; +} + +/* { dg-final { scan-assembler-times {\tcmlt\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tsshr\t} } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/shl-combine-4.c b/gcc/testsuite/gcc.target/aarch64/shl-combine-4.c new file mode 100644 index 0000000..0831810 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shl-combine-4.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE int + +void e (signed TYPE * restrict a, signed TYPE *b, int n) +{ + for (int i = 0; i < n; i++) + b[i] = a[i] >> (sizeof(TYPE)*8)-1; +} + +/* { dg-final { scan-assembler-times {\tcmlt\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tsshr\t} } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/shl-combine-5.c b/gcc/testsuite/gcc.target/aarch64/shl-combine-5.c new file mode 100644 index 0000000..6b2a6bd --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shl-combine-5.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE long + +void e (signed TYPE * restrict a, signed TYPE *b, int n) +{ + for (int i = 0; i < n; i++) + b[i] = a[i] >> (sizeof(TYPE)*8)-1; +} + +/* { dg-final { scan-assembler-times {\tcmlt\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tsshr\t} } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-1.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-1.c new file mode 100644 index 0000000..a285246 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-1.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE char + +void foo (unsigned TYPE * restrict a, TYPE * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = (a[i] * a[i]) >> 2; +} + +/* { dg-final { scan-assembler-times {\tshrn\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tshrn2\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-10.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-10.c new file mode 100644 index 0000000..3a1cfce --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-10.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + + +#include <arm_neon.h> + +uint32x4_t foo (uint64x2_t a, uint64x2_t b) +{ + return vrshrn_high_n_u64 (vrshrn_n_u64 (a, 32), b, 32); +} + +/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-2.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-2.c new file mode 100644 index 0000000..012135b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-2.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE short + +void foo (unsigned TYPE * restrict a, TYPE * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = (a[i] * a[i]) >> 2; +} + +/* { dg-final { scan-assembler-times {\tshrn\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tshrn2\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-3.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-3.c new file mode 100644 index 0000000..8b5b360 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-3.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE int + +void foo (unsigned long long * restrict a, TYPE * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = a[i] >> 3; +} + +/* { dg-final { scan-assembler-times {\tshrn\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tshrn2\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-4.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-4.c new file mode 100644 index 0000000..fedca76 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-4.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE long long + +void foo (unsigned TYPE * restrict a, TYPE * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = (a[i] * a[i]) >> 2; +} + +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-5.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-5.c new file mode 100644 index 0000000..408e8553 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-5.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE1 char +#define TYPE2 short +#define SHIFT 8 + +void foo (TYPE2 * restrict a, TYPE1 * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = a[i] >> SHIFT; +} + +/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-6.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-6.c new file mode 100644 index 0000000..6211ba3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-6.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE1 short +#define TYPE2 int +#define SHIFT 16 + +void foo (TYPE2 * restrict a, TYPE1 * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = a[i] >> SHIFT; +} + +/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-7.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-7.c new file mode 100644 index 0000000..56cbeac --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-7.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE1 int +#define TYPE2 long long +#define SHIFT 32 + +void foo (TYPE2 * restrict a, TYPE1 * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = a[i] >> SHIFT; +} + +/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-8.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-8.c new file mode 100644 index 0000000..6a47f3c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-8.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + + +#include <arm_neon.h> + +uint8x16_t foo (uint16x8_t a, uint16x8_t b) +{ + return vrshrn_high_n_u16 (vrshrn_n_u16 (a, 8), b, 8); +} + +/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-9.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-9.c new file mode 100644 index 0000000..929a55c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-9.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + + +#include <arm_neon.h> + +uint16x8_t foo (uint32x4_t a, uint32x4_t b) +{ + return vrshrn_high_n_u32 (vrshrn_n_u32 (a, 16), b, 16); +} + +/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vmul_elem_1.c b/gcc/testsuite/gcc.target/aarch64/simd/vmul_elem_1.c index a1faefd..ffa391a 100644 --- a/gcc/testsuite/gcc.target/aarch64/simd/vmul_elem_1.c +++ b/gcc/testsuite/gcc.target/aarch64/simd/vmul_elem_1.c @@ -146,12 +146,14 @@ check_v2sf (float32_t elemA, float32_t elemB) vst1_f32 (vec32x2_res, vmul_n_f32 (vec32x2_src, elemA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (* (uint32_t *) &vec32x2_res[indx] != * (uint32_t *) &expected2_1[indx]) abort (); vst1_f32 (vec32x2_res, vmul_n_f32 (vec32x2_src, elemB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (* (uint32_t *) &vec32x2_res[indx] != * (uint32_t *) &expected2_2[indx]) abort (); @@ -169,24 +171,28 @@ check_v4sf (float32_t elemA, float32_t elemB, float32_t elemC, float32_t elemD) vst1q_f32 (vec32x4_res, vmulq_n_f32 (vec32x4_src, elemA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (* (uint32_t *) &vec32x4_res[indx] != * (uint32_t *) &expected4_1[indx]) abort (); vst1q_f32 (vec32x4_res, vmulq_n_f32 (vec32x4_src, elemB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (* (uint32_t *) &vec32x4_res[indx] != * (uint32_t *) &expected4_2[indx]) abort (); vst1q_f32 (vec32x4_res, vmulq_n_f32 (vec32x4_src, elemC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (* (uint32_t *) &vec32x4_res[indx] != * (uint32_t *) &expected4_3[indx]) abort (); vst1q_f32 (vec32x4_res, vmulq_n_f32 (vec32x4_src, elemD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (* (uint32_t *) &vec32x4_res[indx] != * (uint32_t *) &expected4_4[indx]) abort (); @@ -204,12 +210,14 @@ check_v2df (float64_t elemdC, float64_t elemdD) vst1q_f64 (vec64x2_res, vmulq_n_f64 (vec64x2_src, elemdC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (* (uint64_t *) &vec64x2_res[indx] != * (uint64_t *) &expectedd2_1[indx]) abort (); vst1q_f64 (vec64x2_res, vmulq_n_f64 (vec64x2_src, elemdD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (* (uint64_t *) &vec64x2_res[indx] != * (uint64_t *) &expectedd2_2[indx]) abort (); @@ -227,12 +235,14 @@ check_v2si (int32_t elemsA, int32_t elemsB) vst1_s32 (vecs32x2_res, vmul_n_s32 (vecs32x2_src, elemsA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (vecs32x2_res[indx] != expecteds2_1[indx]) abort (); vst1_s32 (vecs32x2_res, vmul_n_s32 (vecs32x2_src, elemsB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (vecs32x2_res[indx] != expecteds2_2[indx]) abort (); @@ -248,12 +258,14 @@ check_v2si_unsigned (uint32_t elemusA, uint32_t elemusB) vst1_u32 (vecus32x2_res, vmul_n_u32 (vecus32x2_src, elemusA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (vecus32x2_res[indx] != expectedus2_1[indx]) abort (); vst1_u32 (vecus32x2_res, vmul_n_u32 (vecus32x2_src, elemusB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (vecus32x2_res[indx] != expectedus2_2[indx]) abort (); @@ -271,24 +283,28 @@ check_v4si (int32_t elemsA, int32_t elemsB, int32_t elemsC, int32_t elemsD) vst1q_s32 (vecs32x4_res, vmulq_n_s32 (vecs32x4_src, elemsA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecs32x4_res[indx] != expecteds4_1[indx]) abort (); vst1q_s32 (vecs32x4_res, vmulq_n_s32 (vecs32x4_src, elemsB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecs32x4_res[indx] != expecteds4_2[indx]) abort (); vst1q_s32 (vecs32x4_res, vmulq_n_s32 (vecs32x4_src, elemsC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecs32x4_res[indx] != expecteds4_3[indx]) abort (); vst1q_s32 (vecs32x4_res, vmulq_n_s32 (vecs32x4_src, elemsD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecs32x4_res[indx] != expecteds4_4[indx]) abort (); @@ -305,24 +321,28 @@ check_v4si_unsigned (uint32_t elemusA, uint32_t elemusB, uint32_t elemusC, vst1q_u32 (vecus32x4_res, vmulq_n_u32 (vecus32x4_src, elemusA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecus32x4_res[indx] != expectedus4_1[indx]) abort (); vst1q_u32 (vecus32x4_res, vmulq_n_u32 (vecus32x4_src, elemusB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecus32x4_res[indx] != expectedus4_2[indx]) abort (); vst1q_u32 (vecus32x4_res, vmulq_n_u32 (vecus32x4_src, elemusC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecus32x4_res[indx] != expectedus4_3[indx]) abort (); vst1q_u32 (vecus32x4_res, vmulq_n_u32 (vecus32x4_src, elemusD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecus32x4_res[indx] != expectedus4_4[indx]) abort (); @@ -341,24 +361,28 @@ check_v4hi (int16_t elemhA, int16_t elemhB, int16_t elemhC, int16_t elemhD) vst1_s16 (vech16x4_res, vmul_n_s16 (vech16x4_src, elemhA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vech16x4_res[indx] != expectedh4_1[indx]) abort (); vst1_s16 (vech16x4_res, vmul_n_s16 (vech16x4_src, elemhB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vech16x4_res[indx] != expectedh4_2[indx]) abort (); vst1_s16 (vech16x4_res, vmul_n_s16 (vech16x4_src, elemhC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vech16x4_res[indx] != expectedh4_3[indx]) abort (); vst1_s16 (vech16x4_res, vmul_n_s16 (vech16x4_src, elemhD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vech16x4_res[indx] != expectedh4_4[indx]) abort (); @@ -375,24 +399,28 @@ check_v4hi_unsigned (uint16_t elemuhA, uint16_t elemuhB, uint16_t elemuhC, vst1_u16 (vecuh16x4_res, vmul_n_u16 (vecuh16x4_src, elemuhA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecuh16x4_res[indx] != expecteduh4_1[indx]) abort (); vst1_u16 (vecuh16x4_res, vmul_n_u16 (vecuh16x4_src, elemuhB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecuh16x4_res[indx] != expecteduh4_2[indx]) abort (); vst1_u16 (vecuh16x4_res, vmul_n_u16 (vecuh16x4_src, elemuhC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecuh16x4_res[indx] != expecteduh4_3[indx]) abort (); vst1_u16 (vecuh16x4_res, vmul_n_u16 (vecuh16x4_src, elemuhD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecuh16x4_res[indx] != expecteduh4_4[indx]) abort (); @@ -411,48 +439,56 @@ check_v8hi (int16_t elemhA, int16_t elemhB, int16_t elemhC, int16_t elemhD, vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_1[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_2[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_3[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_4[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhE)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_5[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhF)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_6[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhG)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_7[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhH)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_8[indx]) abort (); @@ -470,48 +506,56 @@ check_v8hi_unsigned (uint16_t elemuhA, uint16_t elemuhB, uint16_t elemuhC, vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_1[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_2[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_3[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_4[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhE)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_5[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhF)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_6[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhG)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_7[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhH)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_8[indx]) abort (); diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr93183.c b/gcc/testsuite/gcc.target/aarch64/sve/pr93183.c index 2f92224..8d1ee41 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pr93183.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr93183.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -mcpu=generic+sve" } */ +/* { dg-options "-O3" } */ typedef unsigned char uint8_t; diff --git a/gcc/testsuite/gcc.target/aarch64/vclz.c b/gcc/testsuite/gcc.target/aarch64/vclz.c index a36ee44..ca4d174 100644 --- a/gcc/testsuite/gcc.target/aarch64/vclz.c +++ b/gcc/testsuite/gcc.target/aarch64/vclz.c @@ -66,22 +66,62 @@ extern void abort (void); #define CLZ_INST(reg_len, data_len, is_signed) \ CONCAT1 (vclz, POSTFIX (reg_len, data_len, is_signed)) -#define RUN_TEST(test_set, answ_set, reg_len, data_len, is_signed, n) \ - INHIB_OPTIMIZATION; \ - a = LOAD_INST (reg_len, data_len, is_signed) (test_set); \ - b = LOAD_INST (reg_len, data_len, is_signed) (answ_set); \ - a = CLZ_INST (reg_len, data_len, is_signed) (a); \ - for (i = 0; i < n; i++) \ - if (a [i] != b [i]) \ - return 1; +#define BUILD_TEST(type, size, lanes) \ +int __attribute__((noipa,noinline)) \ +run_test##type##size##x##lanes (int##size##_t* test_set, \ + int##size##_t* answ_set, \ + int reg_len, int data_len, \ + int n) \ +{ \ + int i; \ + INHIB_OPTIMIZATION; \ + int##size##x##lanes##_t a = vld1##type##size (test_set); \ + int##size##x##lanes##_t b = vld1##type##size (answ_set); \ + a = vclz##type##size (a); \ + for (i = 0; i < n; i++){ \ + if (a [i] != b [i]) \ + return 1; \ + } \ + return 0; \ +} + +/* unsigned inputs */ +#define U_BUILD_TEST(type, size, lanes) \ +int __attribute__((noipa,noinline)) \ +run_test##type##size##x##lanes (uint##size##_t* test_set, \ + uint##size##_t* answ_set, \ + int reg_len, int data_len, \ + int n) \ +{ \ + int i; \ + INHIB_OPTIMIZATION; \ + uint##size##x##lanes##_t a = vld1##type##size (test_set); \ + uint##size##x##lanes##_t b = vld1##type##size (answ_set); \ + a = vclz##type##size (a); \ + for (i = 0; i < n; i++){ \ + if (a [i] != b [i]) \ + return 1; \ + } \ + return 0; \ +} + +BUILD_TEST (_s, 8, 8) +BUILD_TEST (_s, 16, 4) +BUILD_TEST (_s, 32, 2) +BUILD_TEST (q_s, 8, 16) +BUILD_TEST (q_s, 16, 8) +BUILD_TEST (q_s, 32, 4) + +U_BUILD_TEST (_u, 8, 8) +U_BUILD_TEST (_u, 16, 4) +U_BUILD_TEST (_u, 32, 2) +U_BUILD_TEST (q_u, 8, 16) +U_BUILD_TEST (q_u, 16, 8) +U_BUILD_TEST (q_u, 32, 4) int __attribute__ ((noinline)) test_vclz_s8 () { - int i; - int8x8_t a; - int8x8_t b; - int8_t test_set0[8] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7 @@ -98,22 +138,18 @@ test_vclz_s8 () 0, 0, 0, 0, 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 64, 8, 1, 8); - RUN_TEST (test_set1, answ_set1, 64, 8, 1, 1); + int o1 = run_test_s8x8 (test_set0, answ_set0, 64, 8, 8); + int o2 = run_test_s8x8 (test_set1, answ_set1, 64, 8, 1); - return 0; + return o1||o2; } /* Double scan-assembler-times to take account of unsigned functions. */ -/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.8b, v\[0-9\]+\.8b" 4 } } */ +/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.8b, v\[0-9\]+\.8b" 2 } } */ int __attribute__ ((noinline)) test_vclz_s16 () { - int i; - int16x4_t a; - int16x4_t b; - int16_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 }; int16_t test_set1[4] = { TEST4, TEST5, TEST6, TEST7 }; int16_t test_set2[4] = { TEST8, TEST9, TEST10, TEST11 }; @@ -126,25 +162,21 @@ test_vclz_s16 () int16_t answ_set3[4] = { 4, 3, 2, 1 }; int16_t answ_set4[4] = { 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 64, 16, 1, 4); - RUN_TEST (test_set1, answ_set1, 64, 16, 1, 4); - RUN_TEST (test_set2, answ_set2, 64, 16, 1, 4); - RUN_TEST (test_set3, answ_set3, 64, 16, 1, 4); - RUN_TEST (test_set4, answ_set4, 64, 16, 1, 1); + int o1 = run_test_s16x4 (test_set0, answ_set0, 64, 16, 4); + int o2 = run_test_s16x4 (test_set1, answ_set1, 64, 16, 4); + int o3 = run_test_s16x4 (test_set2, answ_set2, 64, 16, 4); + int o4 = run_test_s16x4 (test_set3, answ_set3, 64, 16, 4); + int o5 = run_test_s16x4 (test_set4, answ_set4, 64, 16, 1); - return 0; + return o1||o2||o3||o4||o5; } /* Double scan-assembler-times to take account of unsigned functions. */ -/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.4h, v\[0-9\]+\.4h" 10} } */ +/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.4h, v\[0-9\]+\.4h" 2} } */ int __attribute__ ((noinline)) test_vclz_s32 () { - int i; - int32x2_t a; - int32x2_t b; - int32_t test_set0[2] = { TEST0, TEST1 }; int32_t test_set1[2] = { TEST2, TEST3 }; int32_t test_set2[2] = { TEST4, TEST5 }; @@ -181,37 +213,34 @@ test_vclz_s32 () int32_t answ_set15[2] = { 2, 1 }; int32_t answ_set16[2] = { 0, 0 }; - RUN_TEST (test_set0, answ_set0, 64, 32, 1, 2); - RUN_TEST (test_set1, answ_set1, 64, 32, 1, 2); - RUN_TEST (test_set2, answ_set2, 64, 32, 1, 2); - RUN_TEST (test_set3, answ_set3, 64, 32, 1, 2); - RUN_TEST (test_set4, answ_set4, 64, 32, 1, 2); - RUN_TEST (test_set5, answ_set5, 64, 32, 1, 2); - RUN_TEST (test_set6, answ_set6, 64, 32, 1, 2); - RUN_TEST (test_set7, answ_set7, 64, 32, 1, 2); - RUN_TEST (test_set8, answ_set8, 64, 32, 1, 2); - RUN_TEST (test_set9, answ_set9, 64, 32, 1, 2); - RUN_TEST (test_set10, answ_set10, 64, 32, 1, 2); - RUN_TEST (test_set11, answ_set11, 64, 32, 1, 2); - RUN_TEST (test_set12, answ_set12, 64, 32, 1, 2); - RUN_TEST (test_set13, answ_set13, 64, 32, 1, 2); - RUN_TEST (test_set14, answ_set14, 64, 32, 1, 2); - RUN_TEST (test_set15, answ_set15, 64, 32, 1, 2); - RUN_TEST (test_set16, answ_set16, 64, 32, 1, 1); - - return 0; + int o1 = run_test_s32x2 (test_set0, answ_set0, 64, 32, 2); + int o2 = run_test_s32x2 (test_set1, answ_set1, 64, 32, 2); + int o3 = run_test_s32x2 (test_set2, answ_set2, 64, 32, 2); + int o4 = run_test_s32x2 (test_set3, answ_set3, 64, 32, 2); + int o5 = run_test_s32x2 (test_set4, answ_set4, 64, 32, 2); + int o6 = run_test_s32x2 (test_set5, answ_set5, 64, 32, 2); + int o7 = run_test_s32x2 (test_set6, answ_set6, 64, 32, 2); + int o8 = run_test_s32x2 (test_set7, answ_set7, 64, 32, 2); + int o9 = run_test_s32x2 (test_set8, answ_set8, 64, 32, 2); + int o10 = run_test_s32x2 (test_set9, answ_set9, 64, 32, 2); + int o11 = run_test_s32x2 (test_set10, answ_set10, 64, 32, 2); + int o12 = run_test_s32x2 (test_set11, answ_set11, 64, 32, 2); + int o13 = run_test_s32x2 (test_set12, answ_set12, 64, 32, 2); + int o14 = run_test_s32x2 (test_set13, answ_set13, 64, 32, 2); + int o15 = run_test_s32x2 (test_set14, answ_set14, 64, 32, 2); + int o16 = run_test_s32x2 (test_set15, answ_set15, 64, 32, 2); + int o17 = run_test_s32x2 (test_set16, answ_set16, 64, 32, 1); + + return o1||o2||o3||o4||o5||o6||o7||o8||o9||o10||o11||o12||o13||o14 + ||o15||o16||o17; } /* Double scan-assembler-times to take account of unsigned functions. */ -/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s" 34 } } */ +/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s" 2 } } */ int __attribute__ ((noinline)) test_vclzq_s8 () { - int i; - int8x16_t a; - int8x16_t b; - int8_t test_set0[16] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7, TEST8, TEST8, TEST8, TEST8, TEST8, TEST8, TEST8, TEST8 @@ -219,8 +248,8 @@ test_vclzq_s8 () int8_t answ_set0[16] = { 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 128, 8, 1, 9); - return 0; + int o1 = run_testq_s8x16 (test_set0, answ_set0, 128, 8, 9); + return o1; } /* Double scan-assembler-times to take account of unsigned functions. */ @@ -229,10 +258,6 @@ test_vclzq_s8 () int __attribute__ ((noinline)) test_vclzq_s16 () { - int i; - int16x8_t a; - int16x8_t b; - int16_t test_set0[8] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7 }; @@ -252,23 +277,19 @@ test_vclzq_s16 () int16_t answ_set2[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 128, 16, 1, 8); - RUN_TEST (test_set1, answ_set1, 128, 16, 1, 8); - RUN_TEST (test_set2, answ_set2, 128, 16, 1, 1); + int o1 = run_testq_s16x8 (test_set0, answ_set0, 128, 16, 8); + int o2 = run_testq_s16x8 (test_set1, answ_set1, 128, 16, 8); + int o3 = run_testq_s16x8 (test_set2, answ_set2, 128, 16, 1); - return 0; + return o1||o2||o3; } /* Double scan-assembler-times to take account of unsigned functions. */ -/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h" 6 } } */ +/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h" 2 } } */ int __attribute__ ((noinline)) test_vclzq_s32 () { - int i; - int32x4_t a; - int32x4_t b; - int32_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 }; int32_t test_set1[4] = { TEST4, TEST5, TEST6, TEST7 }; int32_t test_set2[4] = { TEST8, TEST9, TEST10, TEST11 }; @@ -289,27 +310,23 @@ test_vclzq_s32 () int32_t answ_set7[4] = { 4, 3, 2, 1 }; int32_t answ_set8[4] = { 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 128, 32, 1, 4); - RUN_TEST (test_set1, answ_set1, 128, 32, 1, 4); - RUN_TEST (test_set2, answ_set2, 128, 32, 1, 4); - RUN_TEST (test_set3, answ_set3, 128, 32, 1, 4); - RUN_TEST (test_set4, answ_set4, 128, 32, 1, 1); + int o1 = run_testq_s32x4 (test_set0, answ_set0, 128, 32, 4); + int o2 = run_testq_s32x4 (test_set1, answ_set1, 128, 32, 4); + int o3 = run_testq_s32x4 (test_set2, answ_set2, 128, 32, 4); + int o4 = run_testq_s32x4 (test_set3, answ_set3, 128, 32, 4); + int o5 = run_testq_s32x4 (test_set4, answ_set4, 128, 32, 1); - return 0; + return o1||o2||o3||o4||o5; } /* Double scan-assembler-times to take account of unsigned functions. */ -/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s" 10 } } */ +/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s" 2 } } */ /* Unsigned versions. */ int __attribute__ ((noinline)) test_vclz_u8 () { - int i; - uint8x8_t a; - uint8x8_t b; - uint8_t test_set0[8] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7 }; @@ -323,10 +340,10 @@ test_vclz_u8 () 0, 0, 0, 0, 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 64, 8, 0, 8); - RUN_TEST (test_set1, answ_set1, 64, 8, 0, 1); + int o1 = run_test_u8x8 (test_set0, answ_set0, 64, 8, 8); + int o2 = run_test_u8x8 (test_set1, answ_set1, 64, 8, 1); - return 0; + return o1||o2; } /* ASM scan near test for signed version. */ @@ -334,10 +351,6 @@ test_vclz_u8 () int __attribute__ ((noinline)) test_vclz_u16 () { - int i; - uint16x4_t a; - uint16x4_t b; - uint16_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 }; uint16_t test_set1[4] = { TEST4, TEST5, TEST6, TEST7 }; uint16_t test_set2[4] = { TEST8, TEST9, TEST10, TEST11 }; @@ -350,13 +363,13 @@ test_vclz_u16 () uint16_t answ_set3[4] = { 4, 3, 2, 1 }; uint16_t answ_set4[4] = { 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 64, 16, 0, 4); - RUN_TEST (test_set1, answ_set1, 64, 16, 0, 4); - RUN_TEST (test_set2, answ_set2, 64, 16, 0, 4); - RUN_TEST (test_set3, answ_set3, 64, 16, 0, 4); - RUN_TEST (test_set4, answ_set4, 64, 16, 0, 1); + int o1 = run_test_u16x4 (test_set0, answ_set0, 64, 16, 4); + int o2 = run_test_u16x4 (test_set1, answ_set1, 64, 16, 4); + int o3 = run_test_u16x4 (test_set2, answ_set2, 64, 16, 4); + int o4 = run_test_u16x4 (test_set3, answ_set3, 64, 16, 4); + int o5 = run_test_u16x4 (test_set4, answ_set4, 64, 16, 1); - return 0; + return o1||o2||o3||o4||o5; } /* ASM scan near test for signed version. */ @@ -364,10 +377,6 @@ test_vclz_u16 () int __attribute__ ((noinline)) test_vclz_u32 () { - int i; - uint32x2_t a; - uint32x2_t b; - uint32_t test_set0[2] = { TEST0, TEST1 }; uint32_t test_set1[2] = { TEST2, TEST3 }; uint32_t test_set2[2] = { TEST4, TEST5 }; @@ -404,25 +413,26 @@ test_vclz_u32 () uint32_t answ_set15[2] = { 2, 1 }; uint32_t answ_set16[2] = { 0, 0 }; - RUN_TEST (test_set0, answ_set0, 64, 32, 0, 2); - RUN_TEST (test_set1, answ_set1, 64, 32, 0, 2); - RUN_TEST (test_set2, answ_set2, 64, 32, 0, 2); - RUN_TEST (test_set3, answ_set3, 64, 32, 0, 2); - RUN_TEST (test_set4, answ_set4, 64, 32, 0, 2); - RUN_TEST (test_set5, answ_set5, 64, 32, 0, 2); - RUN_TEST (test_set6, answ_set6, 64, 32, 0, 2); - RUN_TEST (test_set7, answ_set7, 64, 32, 0, 2); - RUN_TEST (test_set8, answ_set8, 64, 32, 0, 2); - RUN_TEST (test_set9, answ_set9, 64, 32, 0, 2); - RUN_TEST (test_set10, answ_set10, 64, 32, 0, 2); - RUN_TEST (test_set11, answ_set11, 64, 32, 0, 2); - RUN_TEST (test_set12, answ_set12, 64, 32, 0, 2); - RUN_TEST (test_set13, answ_set13, 64, 32, 0, 2); - RUN_TEST (test_set14, answ_set14, 64, 32, 0, 2); - RUN_TEST (test_set15, answ_set15, 64, 32, 0, 2); - RUN_TEST (test_set16, answ_set16, 64, 32, 0, 1); - - return 0; + int o1 = run_test_u32x2 (test_set0, answ_set0, 64, 32, 2); + int o2 = run_test_u32x2 (test_set1, answ_set1, 64, 32, 2); + int o3 = run_test_u32x2 (test_set2, answ_set2, 64, 32, 2); + int o4 = run_test_u32x2 (test_set3, answ_set3, 64, 32, 2); + int o5 = run_test_u32x2 (test_set4, answ_set4, 64, 32, 2); + int o6 = run_test_u32x2 (test_set5, answ_set5, 64, 32, 2); + int o7 = run_test_u32x2 (test_set6, answ_set6, 64, 32, 2); + int o8 = run_test_u32x2 (test_set7, answ_set7, 64, 32, 2); + int o9 = run_test_u32x2 (test_set8, answ_set8, 64, 32, 2); + int o10 = run_test_u32x2 (test_set9, answ_set9, 64, 32, 2); + int o11 = run_test_u32x2 (test_set10, answ_set10, 64, 32, 2); + int o12 = run_test_u32x2 (test_set11, answ_set11, 64, 32, 2); + int o13 = run_test_u32x2 (test_set12, answ_set12, 64, 32, 2); + int o14 = run_test_u32x2 (test_set13, answ_set13, 64, 32, 2); + int o15 = run_test_u32x2 (test_set14, answ_set14, 64, 32, 2); + int o16 = run_test_u32x2 (test_set15, answ_set15, 64, 32, 2); + int o17 = run_test_u32x2 (test_set16, answ_set16, 64, 32, 1); + + return o1||o2||o3||o4||o5||o6||o7||o8||o9||o10||o11||o12||o13||o14 + ||o15||o16||o17; } /* ASM scan near test for signed version. */ @@ -441,9 +451,9 @@ test_vclzq_u8 () uint8_t answ_set0[16] = { 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 128, 8, 0, 9); + int o1 = run_testq_u8x16 (test_set0, answ_set0, 128, 8, 9); - return 0; + return o1; } /* ASM scan near test for signed version. */ @@ -476,11 +486,11 @@ test_vclzq_u16 () 0, 0, 0, 0, 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 128, 16, 0, 8); - RUN_TEST (test_set1, answ_set1, 128, 16, 0, 8); - RUN_TEST (test_set2, answ_set2, 128, 16, 0, 1); + int o1 = run_testq_u16x8 (test_set0, answ_set0, 128, 16, 8); + int o2 = run_testq_u16x8 (test_set1, answ_set1, 128, 16, 8); + int o3 = run_testq_u16x8 (test_set2, answ_set2, 128, 16, 1); - return 0; + return o1||o2||o3; } /* ASM scan near test for signed version. */ @@ -488,10 +498,6 @@ test_vclzq_u16 () int __attribute__ ((noinline)) test_vclzq_u32 () { - int i; - uint32x4_t a; - uint32x4_t b; - uint32_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 }; uint32_t test_set1[4] = { TEST4, TEST5, TEST6, TEST7 }; uint32_t test_set2[4] = { TEST8, TEST9, TEST10, TEST11 }; @@ -512,13 +518,13 @@ test_vclzq_u32 () uint32_t answ_set7[4] = { 4, 3, 2, 1 }; uint32_t answ_set8[4] = { 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 128, 32, 0, 4); - RUN_TEST (test_set1, answ_set1, 128, 32, 0, 4); - RUN_TEST (test_set2, answ_set2, 128, 32, 0, 4); - RUN_TEST (test_set3, answ_set3, 128, 32, 0, 4); - RUN_TEST (test_set4, answ_set4, 128, 32, 0, 1); + int o1 = run_testq_u32x4 (test_set0, answ_set0, 128, 32, 4); + int o2 = run_testq_u32x4 (test_set1, answ_set1, 128, 32, 4); + int o3 = run_testq_u32x4 (test_set2, answ_set2, 128, 32, 4); + int o4 = run_testq_u32x4 (test_set3, answ_set3, 128, 32, 4); + int o5 = run_testq_u32x4 (test_set4, answ_set4, 128, 32, 1); - return 0; + return o1||o2||o3||o4||o5; } /* ASM scan near test for signed version. */ diff --git a/gcc/testsuite/gcc.target/aarch64/vneg_s.c b/gcc/testsuite/gcc.target/aarch64/vneg_s.c index 6947526..8ddc4d2 100644 --- a/gcc/testsuite/gcc.target/aarch64/vneg_s.c +++ b/gcc/testsuite/gcc.target/aarch64/vneg_s.c @@ -31,49 +31,24 @@ extern void abort (void); -#define CONCAT(a, b) a##b -#define CONCAT1(a, b) CONCAT (a, b) -#define REG_INFEX64 _ -#define REG_INFEX128 q_ -#define REG_INFEX(reg_len) REG_INFEX##reg_len -#define POSTFIX(reg_len, data_len) \ - CONCAT1 (REG_INFEX (reg_len), s##data_len) -#define DATA_TYPE_32 float -#define DATA_TYPE_64 double -#define DATA_TYPE(data_len) DATA_TYPE_##data_len - -#define FORCE_SIMD_INST64_8(data) -#define FORCE_SIMD_INST64_16(data) -#define FORCE_SIMD_INST64_32(data) -#define FORCE_SIMD_INST64_64(data) force_simd (data) -#define FORCE_SIMD_INST128_8(data) -#define FORCE_SIMD_INST128_16(data) -#define FORCE_SIMD_INST128_32(data) -#define FORCE_SIMD_INST128_64(data) - -#define FORCE_SIMD_INST(reg_len, data_len, data) \ - CONCAT1 (FORCE_SIMD_INST, reg_len##_##data_len) (data) -#define LOAD_INST(reg_len, data_len) \ - CONCAT1 (vld1, POSTFIX (reg_len, data_len)) -#define NEG_INST(reg_len, data_len) \ - CONCAT1 (vneg, POSTFIX (reg_len, data_len)) - -#define RUN_TEST(test_set, answ_set, reg_len, data_len, n, a, b) \ - { \ - int i; \ - INHIB_OPTIMIZATION; \ - (a) = LOAD_INST (reg_len, data_len) (test_set); \ - (b) = LOAD_INST (reg_len, data_len) (answ_set); \ - FORCE_SIMD_INST (reg_len, data_len, a) \ - a = NEG_INST (reg_len, data_len) (a); \ - FORCE_SIMD_INST (reg_len, data_len, a) \ - for (i = 0; i < n; i++) \ - { \ - INHIB_OPTIMIZATION; \ - if (a[i] != b[i]) \ - return 1; \ - } \ - } +#define BUILD_TEST(type, size, lanes) \ +int __attribute__((noipa,noinline)) \ +run_test##type##size##x##lanes (int##size##_t* test_set, \ + int##size##_t* answ_set, \ + int reg_len, int data_len, int n) \ +{ \ + int i; \ + int##size##x##lanes##_t a = vld1##type##size (test_set); \ + int##size##x##lanes##_t b = vld1##type##size (answ_set); \ + a = vneg##type##size (a); \ + for (i = 0; i < n; i++) \ + { \ + INHIB_OPTIMIZATION; \ + if (a[i] != b[i]) \ + return 1; \ + } \ + return 0; \ +} \ #define RUN_TEST_SCALAR(test_val, answ_val, a, b) \ { \ @@ -87,12 +62,19 @@ extern void abort (void); force_simd (res); \ } +BUILD_TEST (_s, 8, 8) +BUILD_TEST (_s, 16, 4) +BUILD_TEST (_s, 32, 2) +BUILD_TEST (_s, 64, 1) + +BUILD_TEST (q_s, 8, 16) +BUILD_TEST (q_s, 16, 8) +BUILD_TEST (q_s, 32, 4) +BUILD_TEST (q_s, 64, 2) + int __attribute__ ((noinline)) test_vneg_s8 () { - int8x8_t a; - int8x8_t b; - int8_t test_set0[8] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, SCHAR_MAX, SCHAR_MIN }; @@ -100,9 +82,9 @@ test_vneg_s8 () ANSW0, ANSW1, ANSW2, ANSW3, ANSW4, ANSW5, SCHAR_MIN + 1, SCHAR_MIN }; - RUN_TEST (test_set0, answ_set0, 64, 8, 8, a, b); + int o1 = run_test_s8x8 (test_set0, answ_set0, 64, 8, 8); - return 0; + return o1; } /* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.8b, v\[0-9\]+\.8b" 1 } } */ @@ -110,29 +92,23 @@ test_vneg_s8 () int __attribute__ ((noinline)) test_vneg_s16 () { - int16x4_t a; - int16x4_t b; - int16_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 }; int16_t test_set1[4] = { TEST4, TEST5, SHRT_MAX, SHRT_MIN }; int16_t answ_set0[4] = { ANSW0, ANSW1, ANSW2, ANSW3 }; int16_t answ_set1[4] = { ANSW4, ANSW5, SHRT_MIN + 1, SHRT_MIN }; - RUN_TEST (test_set0, answ_set0, 64, 16, 4, a, b); - RUN_TEST (test_set1, answ_set1, 64, 16, 4, a, b); + int o1 = run_test_s16x4 (test_set0, answ_set0, 64, 16, 4); + int o2 = run_test_s16x4 (test_set1, answ_set1, 64, 16, 4); - return 0; + return o1||o2; } -/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.4h, v\[0-9\]+\.4h" 2 } } */ +/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.4h, v\[0-9\]+\.4h" 1 } } */ int __attribute__ ((noinline)) test_vneg_s32 () { - int32x2_t a; - int32x2_t b; - int32_t test_set0[2] = { TEST0, TEST1 }; int32_t test_set1[2] = { TEST2, TEST3 }; int32_t test_set2[2] = { TEST4, TEST5 }; @@ -143,22 +119,19 @@ test_vneg_s32 () int32_t answ_set2[2] = { ANSW4, ANSW5 }; int32_t answ_set3[2] = { INT_MIN + 1, INT_MIN }; - RUN_TEST (test_set0, answ_set0, 64, 32, 2, a, b); - RUN_TEST (test_set1, answ_set1, 64, 32, 2, a, b); - RUN_TEST (test_set2, answ_set2, 64, 32, 2, a, b); - RUN_TEST (test_set3, answ_set3, 64, 32, 2, a, b); + int o1 = run_test_s32x2 (test_set0, answ_set0, 64, 32, 2); + int o2 = run_test_s32x2 (test_set1, answ_set1, 64, 32, 2); + int o3 = run_test_s32x2 (test_set2, answ_set2, 64, 32, 2); + int o4 = run_test_s32x2 (test_set3, answ_set3, 64, 32, 2); - return 0; + return o1||o2||o3||o4; } -/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s" 4 } } */ +/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s" 1 } } */ int __attribute__ ((noinline)) test_vneg_s64 () { - int64x1_t a; - int64x1_t b; - int64_t test_set0[1] = { TEST0 }; int64_t test_set1[1] = { TEST1 }; int64_t test_set2[1] = { TEST2 }; @@ -177,16 +150,16 @@ test_vneg_s64 () int64_t answ_set6[1] = { LLONG_MIN + 1 }; int64_t answ_set7[1] = { LLONG_MIN }; - RUN_TEST (test_set0, answ_set0, 64, 64, 1, a, b); - RUN_TEST (test_set1, answ_set1, 64, 64, 1, a, b); - RUN_TEST (test_set2, answ_set2, 64, 64, 1, a, b); - RUN_TEST (test_set3, answ_set3, 64, 64, 1, a, b); - RUN_TEST (test_set4, answ_set4, 64, 64, 1, a, b); - RUN_TEST (test_set5, answ_set5, 64, 64, 1, a, b); - RUN_TEST (test_set6, answ_set6, 64, 64, 1, a, b); - RUN_TEST (test_set7, answ_set7, 64, 64, 1, a, b); + int o1 = run_test_s64x1 (test_set0, answ_set0, 64, 64, 1); + int o2 = run_test_s64x1 (test_set1, answ_set1, 64, 64, 1); + int o3 = run_test_s64x1 (test_set2, answ_set2, 64, 64, 1); + int o4 = run_test_s64x1 (test_set3, answ_set3, 64, 64, 1); + int o5 = run_test_s64x1 (test_set4, answ_set4, 64, 64, 1); + int o6 = run_test_s64x1 (test_set5, answ_set5, 64, 64, 1); + int o7 = run_test_s64x1 (test_set6, answ_set6, 64, 64, 1); + int o8 = run_test_s64x1 (test_set7, answ_set7, 64, 64, 1); - return 0; + return o1||o2||o3||o4||o5||o6||o7||o8; } int __attribute__ ((noinline)) @@ -206,14 +179,11 @@ test_vnegd_s64 () return 0; } -/* { dg-final { scan-assembler-times "neg\\td\[0-9\]+, d\[0-9\]+" 16 } } */ +/* { dg-final { scan-assembler-times "neg\\td\[0-9\]+, d\[0-9\]+" 8 } } */ int __attribute__ ((noinline)) test_vnegq_s8 () { - int8x16_t a; - int8x16_t b; - int8_t test_set0[16] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, SCHAR_MAX, SCHAR_MIN, 4, 8, 15, 16, 23, 42, -1, -2 @@ -224,9 +194,9 @@ test_vnegq_s8 () -4, -8, -15, -16, -23, -42, 1, 2 }; - RUN_TEST (test_set0, answ_set0, 128, 8, 8, a, b); + int o1 = run_testq_s8x16 (test_set0, answ_set0, 128, 8, 8); - return 0; + return o1; } /* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.16b, v\[0-9\]+\.16b" 1 } } */ @@ -234,9 +204,6 @@ test_vnegq_s8 () int __attribute__ ((noinline)) test_vnegq_s16 () { - int16x8_t a; - int16x8_t b; - int16_t test_set0[8] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, SHRT_MAX, SHRT_MIN }; @@ -244,9 +211,9 @@ test_vnegq_s16 () ANSW0, ANSW1, ANSW2, ANSW3, ANSW4, ANSW5, SHRT_MIN + 1, SHRT_MIN }; - RUN_TEST (test_set0, answ_set0, 128, 16, 8, a, b); + int o1 = run_testq_s16x8 (test_set0, answ_set0, 128, 16, 8); - return 0; + return o1; } /* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h" 1 } } */ @@ -254,29 +221,23 @@ test_vnegq_s16 () int __attribute__ ((noinline)) test_vnegq_s32 () { - int32x4_t a; - int32x4_t b; - int32_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 }; int32_t test_set1[4] = { TEST4, TEST5, INT_MAX, INT_MIN }; int32_t answ_set0[4] = { ANSW0, ANSW1, ANSW2, ANSW3 }; int32_t answ_set1[4] = { ANSW4, ANSW5, INT_MIN + 1, INT_MIN }; - RUN_TEST (test_set0, answ_set0, 128, 32, 4, a, b); - RUN_TEST (test_set1, answ_set1, 128, 32, 4, a, b); + int o1 = run_testq_s32x4 (test_set0, answ_set0, 128, 32, 4); + int o2 = run_testq_s32x4 (test_set1, answ_set1, 128, 32, 4); - return 0; + return o1||o2; } -/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s" 2 } } */ +/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s" 1 } } */ int __attribute__ ((noinline)) test_vnegq_s64 () { - int64x2_t a; - int64x2_t b; - int64_t test_set0[2] = { TEST0, TEST1 }; int64_t test_set1[2] = { TEST2, TEST3 }; int64_t test_set2[2] = { TEST4, TEST5 }; @@ -287,15 +248,15 @@ test_vnegq_s64 () int64_t answ_set2[2] = { ANSW4, ANSW5 }; int64_t answ_set3[2] = { LLONG_MIN + 1, LLONG_MIN }; - RUN_TEST (test_set0, answ_set0, 128, 64, 2, a, b); - RUN_TEST (test_set1, answ_set1, 128, 64, 2, a, b); - RUN_TEST (test_set2, answ_set2, 128, 64, 2, a, b); - RUN_TEST (test_set3, answ_set3, 128, 64, 2, a, b); + int o1 = run_testq_s64x2 (test_set0, answ_set0, 128, 64, 2); + int o2 = run_testq_s64x2 (test_set1, answ_set1, 128, 64, 2); + int o3 = run_testq_s64x2 (test_set2, answ_set2, 128, 64, 2); + int o4 = run_testq_s64x2 (test_set3, answ_set3, 128, 64, 2); - return 0; + return o1||o2||o2||o4; } -/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d" 4 } } */ +/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d" 1 } } */ int main (int argc, char **argv) diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-1.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-1.c new file mode 100644 index 0000000..14e0414 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-1.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define SIGN signed +#define TYPE1 char +#define TYPE2 short + +void d2 (SIGN TYPE1 * restrict a, SIGN TYPE2 *b, int n) +{ + for (int i = 0; i < n; i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tuzp1\t} 1 } } */ +/* { dg-final { scan-assembler-not {\txtn\t} } } */ +/* { dg-final { scan-assembler-not {\txtn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-2.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-2.c new file mode 100644 index 0000000..c259010 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-2.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define SIGN signed +#define TYPE1 short +#define TYPE2 int + +void d2 (SIGN TYPE1 * restrict a, SIGN TYPE2 *b, int n) +{ + for (int i = 0; i < n; i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tuzp1\t} 1 } } */ +/* { dg-final { scan-assembler-not {\txtn\t} } } */ +/* { dg-final { scan-assembler-not {\txtn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-3.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-3.c new file mode 100644 index 0000000..9a2065f --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-3.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define SIGN signed +#define TYPE1 int +#define TYPE2 long long + +void d2 (SIGN TYPE1 * restrict a, SIGN TYPE2 *b, int n) +{ + for (int i = 0; i < n; i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tuzp1\t} 1 } } */ +/* { dg-final { scan-assembler-not {\txtn\t} } } */ +/* { dg-final { scan-assembler-not {\txtn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-4.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-4.c new file mode 100644 index 0000000..77c3dce --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-4.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define SIGN unsigned +#define TYPE1 char +#define TYPE2 short + +void d2 (SIGN TYPE1 * restrict a, SIGN TYPE2 *b, int n) +{ + for (int i = 0; i < n; i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tuzp1\t} 1 } } */ +/* { dg-final { scan-assembler-not {\txtn\t} } } */ +/* { dg-final { scan-assembler-not {\txtn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-5.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-5.c new file mode 100644 index 0000000..ae30e86 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-5.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define SIGN unsigned +#define TYPE1 short +#define TYPE2 int + +void d2 (SIGN TYPE1 * restrict a, SIGN TYPE2 *b, int n) +{ + for (int i = 0; i < n; i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tuzp1\t} 1 } } */ +/* { dg-final { scan-assembler-not {\txtn\t} } } */ +/* { dg-final { scan-assembler-not {\txtn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-6.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-6.c new file mode 100644 index 0000000..882f3d3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-6.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define SIGN unsigned +#define TYPE1 int +#define TYPE2 long long + +void d2 (SIGN TYPE1 * restrict a, SIGN TYPE2 *b, int n) +{ + for (int i = 0; i < n; i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tuzp1\t} 1 } } */ +/* { dg-final { scan-assembler-not {\txtn\t} } } */ +/* { dg-final { scan-assembler-not {\txtn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/i386/387-12.c b/gcc/testsuite/gcc.target/i386/387-12.c index 7fe50a2..ba86536 100644 --- a/gcc/testsuite/gcc.target/i386/387-12.c +++ b/gcc/testsuite/gcc.target/i386/387-12.c @@ -1,6 +1,6 @@ /* PR target/26915 */ -/* { dg-do compile } */ -/* { dg-options "-O -m32 -mfpmath=387 -mfancy-math-387" } */ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O -mfpmath=387 -mfancy-math-387" } */ double testm0(void) { diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-set1-pch-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-set1-pch-1a.c new file mode 100644 index 0000000..0055193 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512fp16-set1-pch-1a.c @@ -0,0 +1,13 @@ +/* { dg-do compile} */ +/* { dg-options "-O2 -mavx512fp16" } */ + +#include <immintrin.h> + +__m512h +__attribute__ ((noinline, noclone)) +test_mm512_set1_pch (_Float16 _Complex A) +{ + return _mm512_set1_pch(A); +} + +/* { dg-final { scan-assembler "vbroadcastss\[ \\t\]+\[^\n\r\]*%zmm\[01\]" } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-set1-pch-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-set1-pch-1b.c new file mode 100644 index 0000000..450d7e3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512fp16-set1-pch-1b.c @@ -0,0 +1,42 @@ +/* { dg-do run { target avx512fp16 } } */ +/* { dg-options "-O2 -mavx512fp16" } */ + +#include<stdio.h> +#include <math.h> +#include <complex.h> + +static void do_test (void); + +#define DO_TEST do_test +#define AVX512FP16 + +#include <immintrin.h> +#include "avx512-check.h" + +static void +do_test (void) +{ + _Float16 _Complex fc = 1.0 + 1.0*I; + union + { + _Float16 _Complex a; + float b; + } u = { .a = fc }; + float ff= u.b; + + typedef union + { + float fp[16]; + __m512h m512h; + } u1; + + __m512h test512 = _mm512_set1_pch(fc); + + u1 test; + test.m512h = test512; + for (int i = 0; i<16; i++) + { + if (test.fp[i] != ff) abort(); + } + +} diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-set1-pch-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-set1-pch-1a.c new file mode 100644 index 0000000..4c5624f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-set1-pch-1a.c @@ -0,0 +1,20 @@ +/* { dg-do compile} */ +/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */ + +#include <immintrin.h> + +__m256h +__attribute__ ((noinline, noclone)) +test_mm256_set1_pch (_Float16 _Complex A) +{ + return _mm256_set1_pch(A); +} + +__m128h +__attribute__ ((noinline, noclone)) +test_mm_set1_pch (_Float16 _Complex A) +{ + return _mm_set1_pch(A); +} + +/* { dg-final { scan-assembler-times "vbroadcastss" 2 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-set1-pch-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-set1-pch-1b.c new file mode 100644 index 0000000..aebff14 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-set1-pch-1b.c @@ -0,0 +1,57 @@ +/* { dg-do run { target avx512fp16 } } */ +/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */ + +#include<stdio.h> +#include <math.h> +#include <complex.h> + +static void do_test (void); + +#define DO_TEST do_test +#define AVX512FP16 + +#include <immintrin.h> +#include "avx512-check.h" + +static void +do_test (void) +{ + _Float16 _Complex fc = 1.0 + 1.0*I; + union + { + _Float16 _Complex a; + float b; + } u = { .a = fc }; + float ff= u.b; + + typedef union + { + float fp[8]; + __m256h m256h; + } u1; + + __m256h test256 = _mm256_set1_pch(fc); + + u1 test1; + test1.m256h = test256; + for (int i = 0; i<8; i++) + { + if (test1.fp[i] != ff) abort(); + } + + typedef union + { + float fp[4]; + __m128h m128h; + } u2; + + __m128h test128 = _mm_set1_pch(fc); + + u2 test2; + test2.m128h = test128; + for (int i = 0; i<4; i++) + { + if (test2.fp[i] != ff) abort(); + } + +} diff --git a/gcc/testsuite/gcc.target/i386/pr102761.c b/gcc/testsuite/gcc.target/i386/pr102761.c new file mode 100644 index 0000000..58ff27e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr102761.c @@ -0,0 +1,11 @@ +/* PR target/102761 */ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +int foo (void); + +void +bar (void) +{ + asm volatile ("%a0" : : "X"(foo () ? 2 : 1)); /* { dg-error "invalid constraints for operand" } */ +} diff --git a/gcc/testsuite/gcc.target/i386/pr102812.c b/gcc/testsuite/gcc.target/i386/pr102812.c new file mode 100644 index 0000000..bad4fa9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr102812.c @@ -0,0 +1,12 @@ +/* PR target/102812 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse4 -mno-avx" } */ +/* { dg-final { scan-assembler-not "vmovdqa64\t" } } */ +/* { dg-final { scan-assembler "movdqa\t" } } */ + +typedef _Float16 v8hf __attribute__((__vector_size__ (16))); + +v8hf t (_Float16 a) +{ + return (v8hf) {a, 0, 0, 0, 0, 0, 0, 0}; +} diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-1.c b/gcc/testsuite/gcc.target/powerpc/builtins-1.c index 83aed5a..2dafa90 100644 --- a/gcc/testsuite/gcc.target/powerpc/builtins-1.c +++ b/gcc/testsuite/gcc.target/powerpc/builtins-1.c @@ -317,10 +317,10 @@ int main () /* { dg-final { scan-assembler-times "vctuxs" 2 } } */ /* { dg-final { scan-assembler-times "vmrghb" 4 { target be } } } */ -/* { dg-final { scan-assembler-times "vmrghb" 5 { target le } } } */ +/* { dg-final { scan-assembler-times "vmrghb" 6 { target le } } } */ /* { dg-final { scan-assembler-times "vmrghh" 8 } } */ -/* { dg-final { scan-assembler-times "xxmrghw" 8 } } */ -/* { dg-final { scan-assembler-times "xxmrglw" 8 } } */ +/* { dg-final { scan-assembler-times "xxmrghw" 4 } } */ +/* { dg-final { scan-assembler-times "xxmrglw" 4 } } */ /* { dg-final { scan-assembler-times "vmrglh" 8 } } */ /* { dg-final { scan-assembler-times "xxlnor" 6 } } */ /* { dg-final { scan-assembler-times {\mvpkudus\M} 1 } } */ @@ -347,7 +347,7 @@ int main () /* { dg-final { scan-assembler-times "vspltb" 6 } } */ /* { dg-final { scan-assembler-times "vspltw" 0 } } */ /* { dg-final { scan-assembler-times "vmrgow" 8 } } */ -/* { dg-final { scan-assembler-times "vmrglb" 5 { target le } } } */ +/* { dg-final { scan-assembler-times "vmrglb" 4 { target le } } } */ /* { dg-final { scan-assembler-times "vmrglb" 6 { target be } } } */ /* { dg-final { scan-assembler-times "vmrgew" 8 } } */ /* { dg-final { scan-assembler-times "vsplth" 8 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/p10_vec_xl_sext.c b/gcc/testsuite/gcc.target/powerpc/p10_vec_xl_sext.c new file mode 100644 index 0000000..78e72ac --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/p10_vec_xl_sext.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target int128 } */ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2" } */ + +#include <altivec.h> + +vector signed __int128 +foo1 (signed long a, signed char *b) +{ + return vec_xl_sext (a, b); +} + +vector signed __int128 +foo2 (signed long a, signed short *b) +{ + return vec_xl_sext (a, b); +} + +vector signed __int128 +foo3 (signed long a, signed int *b) +{ + return vec_xl_sext (a, b); +} + +vector signed __int128 +foo4 (signed long a, signed long *b) +{ + return vec_xl_sext (a, b); +} + +/* { dg-final { scan-assembler-times {\mvextsd2q\M} 4 } } */ +/* { dg-final { scan-assembler-times {\mvextsb2d\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvextsh2d\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvextsw2d\M} 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_2-pcmpgtq.c b/gcc/testsuite/gcc.target/powerpc/sse4_2-pcmpgtq.c index e8ecd9c..36b9bd7 100644 --- a/gcc/testsuite/gcc.target/powerpc/sse4_2-pcmpgtq.c +++ b/gcc/testsuite/gcc.target/powerpc/sse4_2-pcmpgtq.c @@ -1,6 +1,6 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mvsx" } */ -/* { dg-require-effective-target vsx_hw } */ +/* { dg-options "-O2 -mpower8-vector" } */ +/* { dg-require-effective-target p8vector_hw } */ #ifndef CHECK_H #define CHECK_H "sse4_2-check.h" diff --git a/gcc/testsuite/gfortran.dg/bind-c-char-descr.f90 b/gcc/testsuite/gfortran.dg/bind-c-char-descr.f90 index 3b01ad3..8829fd1 100644 --- a/gcc/testsuite/gfortran.dg/bind-c-char-descr.f90 +++ b/gcc/testsuite/gfortran.dg/bind-c-char-descr.f90 @@ -2,7 +2,6 @@ ! ! Contributed by José Rui Faustino de Sousa ! -! Note the xfail issue below for 'strg_print_2("abc") program strp_p @@ -24,13 +23,18 @@ program strp_p if (len(str) /= 3 .or. str /= "abc") stop 1 if (len(strp_1) /= 3 .or. strp_1 /= "abc") stop 2 if (len(strp_2) /= 3 .or. strp_2 /= "abc") stop 3 - call strg_print_0("abc") ! Error (10.0.0) or segmentation fault (9.1.0) - call strg_print_0(str) ! Error (10.0.0) or segmentation fault (9.1.0) - call strg_print_0(strp_1) ! Error (10.0.0) or segmentation fault (9.1.0) - call strg_print_0(strp_2) ! Error (10.0.0) or segmentation fault (9.1.0) - call strg_print_1(strp_1) ! Not yet supported + call strg_print_0("abc") + call strg_print_0(str) + call strg_print_0(strp_1) + call strg_print_0(strp_2) + call strg_print_0_c("abc") + call strg_print_0_c(str) + call strg_print_0_c(strp_1) + call strg_print_0_c(strp_2) + call strg_print_1(strp_1) + call strg_print_1_c(strp_1) - call strg_print_2("abc", xfail=.true.) + call strg_print_2("abc") call strg_print_2(str) call strg_print_2(strp_1) call strg_print_2(strp_2) @@ -42,14 +46,21 @@ program strp_p contains - subroutine strg_print_0(this) bind(c) ! Error (10.0.0 20191106) or warning (9.1.0) issued with bind(c) + subroutine strg_print_0 (this) character(len=*, kind=c_char), target, intent(in) :: this if (len (this) /= 3) stop 10 if (this /= "abc") stop 11 end subroutine strg_print_0 + + subroutine strg_print_0_c (this) bind(c) + character(len=*, kind=c_char), target, intent(in) :: this + + if (len (this) /= 3) stop 10 + if (this /= "abc") stop 11 + end subroutine strg_print_0_c - subroutine strg_print_1(this) bind(c) ! Not yet supported with bind(c) + subroutine strg_print_1 (this) bind(c) character(len=:, kind=c_char), pointer, intent(in) :: this character(len=:), pointer :: strn @@ -63,26 +74,34 @@ contains if (this /= "abc") stop 25 end if end subroutine strg_print_1 + + subroutine strg_print_1_c (this) bind(c) + character(len=:, kind=c_char), pointer, intent(in) :: this + character(len=:), pointer :: strn + + if (.not. associated (this)) stop 20 + if (len (this) /= 3) stop 21 + if (this /= "abc") stop 22 + strn => this + if (.not. associated (strn)) stop 23 + if(associated(strn))then + if (len (this) /= 3) stop 24 + if (this /= "abc") stop 25 + end if + end subroutine strg_print_1_c - subroutine strg_print_2(this, xfail) + subroutine strg_print_2(this) use, intrinsic :: iso_c_binding, only: & c_loc, c_f_pointer type(*), target, intent(in) :: this(..) - logical, optional, value :: xfail character(len=l), pointer :: strn call c_f_pointer(c_loc(this), strn) if (.not. associated (strn)) stop 30 - if(associated(strn))then + if (associated(strn)) then if (len (strn) /= 3) stop 31 - if (strn /= "abc") then - if (present (xfail)) then - print *, 'INVALID STRING - EXPECTED "abc" / PR47225' - else - stop 32 - end if - end if + if (strn /= "abc") stop 32 end if end subroutine strg_print_2 diff --git a/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c b/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c index 48c03d4..0b7bae8 100644 --- a/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c +++ b/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c @@ -88,6 +88,7 @@ do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, basic_check (z, is_cont || num == 2); if (!is_cont && num == 1) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ check_str (x, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero); check_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one); check_str (x, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two); @@ -97,24 +98,55 @@ do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, check_str (z, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero); check_str (z, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one); check_str (z, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two); +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + check_str (x, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + check_str (x, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + check_str (x, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); + check_str (y, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + check_str (y, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + check_str (y, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); + check_str (z, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + check_str (z, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + check_str (z, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); +#else +#error "Unsupported __BYTE_ORDER__" +#endif } else if (num == 1) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ if (memcmp ((const char*) x->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) y->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) z->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0) __builtin_abort (); +#else + if (memcmp ((const char*) x->base_addr, "\0\0\0a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) y->base_addr, "\0\0\0a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) z->base_addr, "\0\0\0a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p", 9*4) != 0) + __builtin_abort (); +#endif } else if (num == 2) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ if (memcmp ((const char*) x->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) y->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) z->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9*4) != 0) __builtin_abort (); +#else + if (memcmp ((const char*) x->base_addr, "\0\0\0d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) y->base_addr, "\0\0\0d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) z->base_addr, "\0\0\0d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m", 9*4) != 0) + __builtin_abort (); +#endif } else __builtin_abort (); @@ -144,6 +176,7 @@ do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, // intent_in if (intent_in && !is_cont && num == 1) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ check_str (x, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero); check_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one); check_str (x, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two); @@ -153,24 +186,53 @@ do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, check_str (z, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero); check_str (z, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one); check_str (z, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two); +#else + check_str (x, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + check_str (x, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + check_str (x, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); + check_str (y, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + check_str (y, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + check_str (y, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); + check_str (z, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + check_str (z, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + check_str (z, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); +#endif } else if (intent_in && num == 1) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ if (memcmp ((const char*) x->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) y->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) z->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0) __builtin_abort (); +#else + if (memcmp ((const char*) x->base_addr, "\0\0\0a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) y->base_addr, "\0\0\0a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) z->base_addr, "\0\0\0a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p", 9*4) != 0) + __builtin_abort (); +#endif } else if (intent_in && num == 2) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ if (memcmp ((const char*) x->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9) != 0) __builtin_abort (); if (memcmp ((const char*) y->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9) != 0) __builtin_abort (); if (memcmp ((const char*) z->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9) != 0) __builtin_abort (); +#else + if (memcmp ((const char*) x->base_addr, "\0\0\0d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m", 9) != 0) + __builtin_abort (); + if (memcmp ((const char*) y->base_addr, "\0\0\0d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m", 9) != 0) + __builtin_abort (); + if (memcmp ((const char*) z->base_addr, "\0\0\0d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m", 9) != 0) + __builtin_abort (); +#endif } else if (intent_in) __builtin_abort (); @@ -179,15 +241,22 @@ do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, if (is_cont && num == 1) { /* Copy in - set the value to check that no copy out is done. */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ memcpy ((char*) x->base_addr, "1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9\0\0\0", 9*4); memcpy ((char*) y->base_addr, "1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9\0\0\0", 9*4); memcpy ((char*) z->base_addr, "1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9\0\0\0", 9*4); +#else + memcpy ((char*) x->base_addr, "\0\0\0""1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9", 9*4); + memcpy ((char*) y->base_addr, "\0\0\0""1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9", 9*4); + memcpy ((char*) z->base_addr, "\0\0\0""1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9", 9*4); +#endif } return addr1; } // !intent_in if (!is_cont && num == 1) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ check_str (x, "A\0\0\0B\0\0\0C\0\0\0", 3*4, zero); check_str (x, "D\0\0\0E\0\0\0F\0\0\0", 3*4, one); check_str (x, "G\0\0\0H\0\0\0I\0\0\0", 3*4, two); @@ -197,15 +266,35 @@ do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, check_str (z, "A\0\0\0B\0\0\0C\0\0\0", 3*4, zero); check_str (z, "D\0\0\0E\0\0\0F\0\0\0", 3*4, one); check_str (z, "G\0\0\0H\0\0\0I\0\0\0", 3*4, two); +#else + check_str (x, "\0\0\0A\0\0\0B\0\0\0C", 3*4, zero); + check_str (x, "\0\0\0D\0\0\0E\0\0\0F", 3*4, one); + check_str (x, "\0\0\0G\0\0\0H\0\0\0I", 3*4, two); + check_str (y, "\0\0\0A\0\0\0B\0\0\0C", 3*4, zero); + check_str (y, "\0\0\0D\0\0\0E\0\0\0F", 3*4, one); + check_str (y, "\0\0\0G\0\0\0H\0\0\0I", 3*4, two); + check_str (z, "\0\0\0A\0\0\0B\0\0\0C", 3*4, zero); + check_str (z, "\0\0\0D\0\0\0E\0\0\0F", 3*4, one); + check_str (z, "\0\0\0G\0\0\0H\0\0\0I", 3*4, two); +#endif } else { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ if (memcmp ((const char*) x->base_addr, "A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) y->base_addr, "A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) z->base_addr, "A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I\0\0\0", 9*4) != 0) __builtin_abort (); +#else + if (memcmp ((const char*) x->base_addr, "\0\0\0A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) y->base_addr, "\0\0\0A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) z->base_addr, "\0\0\0A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I", 9*4) != 0) + __builtin_abort (); +#endif } return addr1; } @@ -275,15 +364,27 @@ reset_var (CFI_cdesc_t *x, int num) if (num == 1) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ set_str (x, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero); set_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one); set_str (x, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two); +#else + set_str (x, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + set_str (x, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + set_str (x, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); +#endif } else if (num == 2) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ set_str (x, "d\0\0\0e\0\0\0f\0\0\0", 3*4, zero); set_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one); set_str (x, "j\0\0\0l\0\0\0m\0\0\0", 3*4, two); +#else + set_str (x, "\0\0\0d\0\0\0e\0\0\0f", 3*4, zero); + set_str (x, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + set_str (x, "\0\0\0j\0\0\0l\0\0\0m", 3*4, two); +#endif } else __builtin_abort (); diff --git a/gcc/testsuite/gfortran.dg/c-interop/shape-bindc.f90 b/gcc/testsuite/gfortran.dg/c-interop/shape-bindc.f90 new file mode 100644 index 0000000..d9e193a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c-interop/shape-bindc.f90 @@ -0,0 +1,77 @@ +! { dg-do run } +! +! TS 29113 +! 6.4.1 SHAPE +! +! The description of the intrinsic function SHAPE in ISO/IEC 1539-1:2010 +! is changed for an assumed-rank array that is associated with an +! assumed-size array; an assumed-size array has no shape, but in this +! case the result has a value equal to +! [ (SIZE (ARRAY, I, KIND), I=1,RANK (ARRAY)) ] +! with KIND omitted from SIZE if it was omitted from SHAPE. +! +! The idea here is that the main program passes some arrays to a test +! subroutine with an assumed-size dummy, which in turn passes that to a +! subroutine with an assumed-rank dummy. + +program test + + ! Define some arrays for testing. + integer, target :: x1(5) + integer :: y1(0:9) + integer, pointer :: p1(:) + integer, allocatable :: a1(:) + integer, target :: x3(2,3,4) + integer :: y3(0:1,-3:-1,4) + integer, pointer :: p3(:,:,:) + integer, allocatable :: a3(:,:,:) + + ! Test the 1-dimensional arrays. + call test1 (x1) + call test1 (y1) + p1 => x1 + call test1 (p1) + allocate (a1(5)) + call test1 (a1) + + ! Test the multi-dimensional arrays. + call test3 (x3, 1, 2, 1, 3) + call test3 (y3, 0, 1, -3, -1) + p3 => x3 + call test3 (p3, 1, 2, 1, 3) + allocate (a3(2,3,4)) + call test3 (a3, 1, 2, 1, 3) + +contains + + subroutine testit (a) bind(c) + integer :: a(..) + + integer :: r + r = rank(a) + + block + integer :: s(r) + s = shape(a) + do i = 1, r + if (s(i) .ne. size(a,i)) stop 101 + end do + end block + + end subroutine + + subroutine test1 (a) bind(c) + integer :: a(*) + + call testit (a) + end subroutine + + subroutine test3 (a, l1, u1, l2, u2) bind(c) + implicit none + integer :: l1, u1, l2, u2 + integer :: a(l1:u1, l2:u2, *) + + call testit (a) + end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/c-interop/shape-poly.f90 b/gcc/testsuite/gfortran.dg/c-interop/shape-poly.f90 new file mode 100644 index 0000000..e17ca88 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c-interop/shape-poly.f90 @@ -0,0 +1,89 @@ +! { dg-do run } +! +! TS 29113 +! 6.4.1 SHAPE +! +! The description of the intrinsic function SHAPE in ISO/IEC 1539-1:2010 +! is changed for an assumed-rank array that is associated with an +! assumed-size array; an assumed-size array has no shape, but in this +! case the result has a value equal to +! [ (SIZE (ARRAY, I, KIND), I=1,RANK (ARRAY)) ] +! with KIND omitted from SIZE if it was omitted from SHAPE. +! +! The idea here is that the main program passes some arrays to a test +! subroutine with an assumed-size dummy, which in turn passes that to a +! subroutine with an assumed-rank dummy. +! +! This is the polymorphic version of shape.f90. + +module m + type :: t + integer :: id + real :: xyz(3) + end type +end module + +program test + use m + + ! Define some arrays for testing. + type(t), target :: x1(5) + type(t) :: y1(0:9) + class(t), pointer :: p1(:) + class(t), allocatable :: a1(:) + type(t), target :: x3(2,3,4) + type(t) :: y3(0:1,-3:-1,4) + class(t), pointer :: p3(:,:,:) + type(t), allocatable :: a3(:,:,:) + + ! Test the 1-dimensional arrays. + call test1 (x1) + call test1 (y1) + p1 => x1 + call test1 (p1) + allocate (a1(5)) + call test1 (a1) + + ! Test the multi-dimensional arrays. + call test3 (x3, 1, 2, 1, 3) + call test3 (y3, 0, 1, -3, -1) + p3 => x3 + call test3 (p3, 1, 2, 1, 3) + allocate (a3(2,3,4)) + call test3 (a3, 1, 2, 1, 3) + +contains + + subroutine testit (a) + use m + class(t) :: a(..) + + integer :: r + r = rank(a) + + block + integer :: s(r) + s = shape(a) + do i = 1, r + if (s(i) .ne. size(a,i)) stop 101 + end do + end block + + end subroutine + + subroutine test1 (a) + use m + class(t) :: a(*) + + call testit (a) + end subroutine + + subroutine test3 (a, l1, u1, l2, u2) + use m + integer :: l1, u1, l2, u2 + class(t) :: a(l1:u1, l2:u2, *) + + call testit (a) + end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/c-interop/size-bindc.f90 b/gcc/testsuite/gfortran.dg/c-interop/size-bindc.f90 new file mode 100644 index 0000000..132ca50 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c-interop/size-bindc.f90 @@ -0,0 +1,106 @@ +! Reported as pr94070. +! { dg-do run } +! +! TS 29113 +! 6.4.2 SIZE +! +! The description of the intrinsic function SIZE in ISO/IEC 1539-1:2010 +! is changed in the following cases: +! +! (1) for an assumed-rank object that is associated with an assumed-size +! array, the result has the value −1 if DIM is present and equal to the +! rank of ARRAY, and a negative value that is equal to +! PRODUCT ( [ (SIZE (ARRAY, I, KIND), I=1, RANK (ARRAY)) ] ) +! if DIM is not present; +! +! (2) for an assumed-rank object that is associated with a scalar, the +! result has the value 1. +! +! The idea here is that the main program passes some arrays to a test +! subroutine with an assumed-size dummy, which in turn passes that to a +! subroutine with an assumed-rank dummy. + +program test + + ! Define some arrays for testing. + integer, target :: x1(5) + integer :: y1(0:9) + integer, pointer :: p1(:) + integer, allocatable :: a1(:) + integer, target :: x3(2,3,4) + integer :: y3(0:1,-3:-1,4) + integer, pointer :: p3(:,:,:) + integer, allocatable :: a3(:,:,:) + integer :: x + + ! Test the 1-dimensional arrays. + call test1 (x1) + call test1 (y1) + p1 => x1 + call test1 (p1) + allocate (a1(5)) + call test1 (a1) + + ! Test the multi-dimensional arrays. + call test3 (x3, 1, 2, 1, 3) + call test3 (y3, 0, 1, -3, -1) + p3 => x3 + call test3 (p3, 1, 2, 1, 3) + allocate (a3(2,3,4)) + call test3 (a3, 1, 2, 1, 3) + + ! Test scalars. + call test0 (x) + call test0 (-1) + call test0 (x1(1)) + +contains + + subroutine testit (a, r, sizes) bind(c) + integer :: a(..) + integer :: r + integer :: sizes(r) + + integer :: totalsize, thissize + totalsize = 1 + + if (r .ne. rank(a)) stop 101 + + do i = 1, r + thissize = size (a, i) + print *, 'got size ', thissize, ' expected ', sizes(i) + if (thissize .ne. sizes(i)) stop 102 + totalsize = totalsize * thissize + end do + + if (size(a) .ne. totalsize) stop 103 + end subroutine + + subroutine test0 (a) bind(c) + integer :: a(..) + + if (size (a) .ne. 1) stop 103 + end subroutine + + subroutine test1 (a) bind(c) + integer :: a(*) + + integer :: sizes(1) + sizes(1) = -1 + call testit (a, 1, sizes) + end subroutine + + subroutine test3 (a, l1, u1, l2, u2) bind(c) + implicit none + integer :: l1, u1, l2, u2 + integer :: a(l1:u1, l2:u2, *) + + integer :: sizes(3) + sizes(1) = u1 - l1 + 1 + sizes(2) = u2 - l2 + 1 + sizes(3) = -1 + + call testit (a, 3, sizes) + end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/c-interop/size-poly.f90 b/gcc/testsuite/gfortran.dg/c-interop/size-poly.f90 new file mode 100644 index 0000000..2241ab8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c-interop/size-poly.f90 @@ -0,0 +1,118 @@ +! Reported as pr94070. +! { dg-do run } +! +! TS 29113 +! 6.4.2 SIZE +! +! The description of the intrinsic function SIZE in ISO/IEC 1539-1:2010 +! is changed in the following cases: +! +! (1) for an assumed-rank object that is associated with an assumed-size +! array, the result has the value −1 if DIM is present and equal to the +! rank of ARRAY, and a negative value that is equal to +! PRODUCT ( [ (SIZE (ARRAY, I, KIND), I=1, RANK (ARRAY)) ] ) +! if DIM is not present; +! +! (2) for an assumed-rank object that is associated with a scalar, the +! result has the value 1. +! +! The idea here is that the main program passes some arrays to a test +! subroutine with an assumed-size dummy, which in turn passes that to a +! subroutine with an assumed-rank dummy. +! +! This is the polymorphic version of size.f90. + +module m + type :: t + integer :: id + real :: xyz(3) + end type +end module + +program test + use m + + ! Define some arrays for testing. + type(t), target :: x1(5) + type(t) :: y1(0:9) + class(t), pointer :: p1(:) + class(t), allocatable :: a1(:) + type(t), target :: x3(2,3,4) + type(t) :: y3(0:1,-3:-1,4) + class(t), pointer :: p3(:,:,:) + type(t), allocatable :: a3(:,:,:) + type(t) :: x + + ! Test the 1-dimensional arrays. + call test1 (x1) + call test1 (y1) + p1 => x1 + call test1 (p1) + allocate (a1(5)) + call test1 (a1) + + ! Test the multi-dimensional arrays. + call test3 (x3, 1, 2, 1, 3) + call test3 (y3, 0, 1, -3, -1) + p3 => x3 + call test3 (p3, 1, 2, 1, 3) + allocate (a3(2,3,4)) + call test3 (a3, 1, 2, 1, 3) + + ! Test scalars. + call test0 (x) + call test0 (x1(1)) + +contains + + subroutine testit (a, r, sizes) + use m + class(t) :: a(..) + integer :: r + integer :: sizes(r) + + integer :: totalsize, thissize + totalsize = 1 + + if (r .ne. rank(a)) stop 101 + + do i = 1, r + thissize = size (a, i) + print *, 'got size ', thissize, ' expected ', sizes(i) + if (thissize .ne. sizes(i)) stop 102 + totalsize = totalsize * thissize + end do + + if (size(a) .ne. totalsize) stop 103 + end subroutine + + subroutine test0 (a) + use m + class(t) :: a(..) + + if (size (a) .ne. 1) stop 103 + end subroutine + + subroutine test1 (a) + use m + class(t) :: a(*) + + integer :: sizes(1) + sizes(1) = -1 + call testit (a, 1, sizes) + end subroutine + + subroutine test3 (a, l1, u1, l2, u2) + use m + integer :: l1, u1, l2, u2 + class(t) :: a(l1:u1, l2:u2, *) + + integer :: sizes(3) + sizes(1) = u1 - l1 + 1 + sizes(2) = u2 - l2 + 1 + sizes(3) = -1 + + call testit (a, 3, sizes) + end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/c-interop/ubound-bindc.f90 b/gcc/testsuite/gfortran.dg/c-interop/ubound-bindc.f90 new file mode 100644 index 0000000..e771836 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c-interop/ubound-bindc.f90 @@ -0,0 +1,129 @@ +! { dg-do run } +! +! TS 29113 +! 6.4.3 UBOUND +! +! The description of the intrinsic function UBOUND in ISO/IEC +! 1539-1:2010 is changed for an assumed-rank object that is associated +! with an assumed-size array; the result of UBOUND (ARRAY, RANK(ARRAY), +! KIND) has a value equal to LBOUND (ARRAY, RANK (ARRAY), KIND) −2 with +! KIND omitted from LBOUND if it was omitted from UBOUND. +! +! NOTE 6.2 +! If LBOUND or UBOUND is invoked for an assumed-rank object that is +! associated with a scalar and DIM is absent, the result is a zero-sized +! array. LBOUND or UBOUND cannot be invoked for an assumed-rank object +! that is associated with a scalar if DIM is present because the rank of +! a scalar is zero and DIM must be ≥ 1. +! +! The idea here is that the main program passes some arrays to a test +! subroutine with an assumed-size dummy, which in turn passes that to a +! subroutine with an assumed-rank dummy. + +program test + + ! Define some arrays for testing. + integer, target :: x1(5) + integer :: y1(0:9) + integer, pointer :: p1(:) + integer, allocatable :: a1(:) + integer, target :: x3(2,3,4) + integer :: y3(0:1,-3:-1,4) + integer, pointer :: p3(:,:,:) + integer, allocatable :: a3(:,:,:) + integer :: x + + ! Test the 1-dimensional arrays. + call test1 (x1) + call testit2(x1, shape(x1)) + call test1 (y1) + call testit2(y1, shape(y1)) + p1 => x1 + call testit2(p1, shape(p1)) + call testit2p(p1, lbound(p1), shape(p1)) + call test1 (p1) + p1(77:) => x1 + call testit2p(p1, [77], shape(p1)) + allocate (a1(5)) + call testit2(a1, shape(a1)) + call testit2a(a1, lbound(a1), shape(a1)) + call test1 (a1) + deallocate(a1) + allocate (a1(-38:5)) + call test1 (a1) + call testit2(a1, shape(a1)) + call testit2a(a1, [-38], shape(a1)) + + ! Test the multi-dimensional arrays. + call test3 (x3, 1, 2, 1, 3) + call test3 (y3, 0, 1, -3, -1) + p3 => x3 + call test3 (p3, 1, 2, 1, 3) + allocate (a3(2,3,4)) + call test3 (a3, 1, 2, 1, 3) + + ! Test some scalars. + call test0 (x) + call test0 (-1) + call test0 (x1(1)) + +contains + + subroutine testit (a) bind(c) + integer :: a(..) + integer :: r + r = rank(a) + if (any (lbound (a) .ne. 1)) stop 101 + if (ubound (a, r) .ne. -1) stop 102 + end subroutine + + subroutine testit2(a, shape) bind(c) + integer :: a(..) + integer :: shape(:) + if (rank(a) /= size(shape)) stop 111 + if (any (lbound(a) /= 1)) stop 112 + if (any (ubound(a) /= shape)) stop 113 + end subroutine + + subroutine testit2a(a,lbound2, shape2) bind(c) + integer, allocatable :: a(..) + integer :: lbound2(:), shape2(:) + if (rank(a) /= size(shape2)) stop 121 + if (any (lbound(a) /= lbound2)) stop 122 + if (any (ubound(a) /= lbound2 + shape2 - 1)) stop 123 + if (any (shape(a) /= shape2)) stop 124 + if (sum (shape(a)) /= size(a)) stop 125 + end subroutine + + subroutine testit2p(a, lbound2, shape2) bind(c) + integer, pointer :: a(..) + integer :: lbound2(:), shape2(:) + if (rank(a) /= size(shape2)) stop 131 + if (any (lbound(a) /= lbound2)) stop 132 + if (any (ubound(a) /= lbound2 + shape2 - 1)) stop 133 + if (any (shape(a) /= shape2)) stop 134 + if (sum (shape(a)) /= size(a)) stop 135 + end subroutine + + subroutine test0 (a) bind(c) + integer :: a(..) + if (rank (a) .ne. 0) stop 141 + if (size (lbound (a)) .ne. 0) stop 142 + if (size (ubound (a)) .ne. 0) stop 143 + end subroutine + + subroutine test1 (a) bind(c) + integer :: a(*) + + call testit (a) + end subroutine + + subroutine test3 (a, l1, u1, l2, u2) bind(c) + implicit none + integer :: l1, u1, l2, u2 + integer :: a(l1:u1, l2:u2, *) + + call testit (a) + end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/c-interop/ubound-poly.f90 b/gcc/testsuite/gfortran.dg/c-interop/ubound-poly.f90 new file mode 100644 index 0000000..333a253 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c-interop/ubound-poly.f90 @@ -0,0 +1,145 @@ +! { dg-do run } +! +! TS 29113 +! 6.4.3 UBOUND +! +! The description of the intrinsic function UBOUND in ISO/IEC +! 1539-1:2010 is changed for an assumed-rank object that is associated +! with an assumed-size array; the result of UBOUND (ARRAY, RANK(ARRAY), +! KIND) has a value equal to LBOUND (ARRAY, RANK (ARRAY), KIND) −2 with +! KIND omitted from LBOUND if it was omitted from UBOUND. +! +! NOTE 6.2 +! If LBOUND or UBOUND is invoked for an assumed-rank object that is +! associated with a scalar and DIM is absent, the result is a zero-sized +! array. LBOUND or UBOUND cannot be invoked for an assumed-rank object +! that is associated with a scalar if DIM is present because the rank of +! a scalar is zero and DIM must be ≥ 1. +! +! The idea here is that the main program passes some arrays to a test +! subroutine with an assumed-size dummy, which in turn passes that to a +! subroutine with an assumed-rank dummy. +! +! This is like ubound.f90, but using polymorphic arrays instead of integer +! arrays. + +module m + type :: t + integer :: id + real :: xyz(3) + end type +end module + +program test + use m + + ! Define some arrays for testing. + type(t), target :: x1(5) + type(t) :: y1(0:9) + class(t), pointer :: p1(:) + class(t), allocatable :: a1(:) + type(t), target :: x3(2,3,4) + type(t) :: y3(0:1,-3:-1,4) + class(t), pointer :: p3(:,:,:) + type(t), allocatable :: a3(:,:,:) + type(t) :: x + + ! Test the 1-dimensional arrays. + call test1 (x1) + call testit2(x1, shape(x1)) + call test1 (y1) + call testit2(y1, shape(y1)) + p1 => x1 + call testit2(p1, shape(p1)) + call testit2p(p1, lbound(p1), shape(p1)) + call test1 (p1) + p1(77:) => x1 + call testit2p(p1, [77], shape(p1)) + allocate (a1(5)) + call testit2(a1, shape(a1)) + call testit2a(a1, lbound(a1), shape(a1)) + call test1 (a1) + deallocate(a1) + allocate (a1(-38:5)) + call test1 (a1) + call testit2(a1, shape(a1)) + call testit2a(a1, [-38], shape(a1)) + + ! Test the multi-dimensional arrays. + call test3 (x3, 1, 2, 1, 3) + call test3 (y3, 0, 1, -3, -1) + p3 => x3 + call test3 (p3, 1, 2, 1, 3) + allocate (a3(2,3,4)) + call test3 (a3, 1, 2, 1, 3) + + ! Test some scalars. + call test0 (x) + call test0 (x1(1)) + +contains + + subroutine testit (a) + use m + class(t) :: a(..) + integer :: r + r = rank(a) + if (any (lbound (a) .ne. 1)) stop 101 + if (ubound (a, r) .ne. -1) stop 102 + end subroutine + + subroutine testit2(a, shape) + use m + class(t) :: a(..) + integer :: shape(:) + if (rank(a) /= size(shape)) stop 111 + if (any (lbound(a) /= 1)) stop 112 + if (any (ubound(a) /= shape)) stop 113 + end subroutine + + subroutine testit2a(a,lbound2, shape2) + use m + class(t), allocatable :: a(..) + integer :: lbound2(:), shape2(:) + if (rank(a) /= size(shape2)) stop 121 + if (any (lbound(a) /= lbound2)) stop 122 + if (any (ubound(a) /= lbound2 + shape2 - 1)) stop 123 + if (any (shape(a) /= shape2)) stop 124 + if (sum (shape(a)) /= size(a)) stop 125 + end subroutine + + subroutine testit2p(a, lbound2, shape2) + use m + class(t), pointer :: a(..) + integer :: lbound2(:), shape2(:) + if (rank(a) /= size(shape2)) stop 131 + if (any (lbound(a) /= lbound2)) stop 132 + if (any (ubound(a) /= lbound2 + shape2 - 1)) stop 133 + if (any (shape(a) /= shape2)) stop 134 + if (sum (shape(a)) /= size(a)) stop 135 + end subroutine + + subroutine test0 (a) + use m + class(t) :: a(..) + if (rank (a) .ne. 0) stop 141 + if (size (lbound (a)) .ne. 0) stop 142 + if (size (ubound (a)) .ne. 0) stop 143 + end subroutine + + subroutine test1 (a) + use m + class(t) :: a(*) + + call testit (a) + end subroutine + + subroutine test3 (a, l1, u1, l2, u2) + use m + integer :: l1, u1, l2, u2 + class(t) :: a(l1:u1, l2:u2, *) + + call testit (a) + end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 b/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 index d60dd72..1bfddc7 100644 --- a/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 @@ -265,6 +265,7 @@ subroutine f2 end do !$omp end do !$omp sections + !$omp section block !$omp cancel parallel ! { dg-error "not closely nested inside" } !$omp cancel do ! { dg-error "not closely nested inside" } @@ -417,6 +418,7 @@ subroutine f2 !$omp end ordered end do !$omp sections + !$omp section block !$omp cancel parallel ! { dg-error "not closely nested inside" } !$omp cancel do ! { dg-error "not closely nested inside" } @@ -515,6 +517,7 @@ subroutine f3 end do !$omp end do nowait !$omp sections + !$omp section block !$omp cancel sections ! { dg-warning "nowait" } end block diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-15.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-15.f90 index b2ad96a..4a88e3e 100644 --- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-15.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-15.f90 @@ -14,6 +14,13 @@ contains subroutine base () end subroutine + subroutine variant2 () + end subroutine + + subroutine base2 () + !$omp declare variant (base2: variant2) match (construct={parallel}) + end subroutine + subroutine test1 () !$omp target !$omp parallel @@ -21,4 +28,10 @@ contains !$omp end parallel !$omp end target end subroutine + + subroutine test2 () + !$omp parallel + call base2 () ! { dg-final { scan-tree-dump-times "variant2 \\\(\\\);" 1 "gimple" } } + !$omp end parallel + end subroutine end module diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-16.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-16.f90 index fc97322..5e34d47 100644 --- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-16.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-16.f90 @@ -10,15 +10,27 @@ module main subroutine base () !$omp declare variant (variant) match (construct={parallel}) end subroutine + + subroutine base2 () + !$omp declare variant (base2: variant2) match (construct={target}) + end subroutine end interface - contains subroutine variant () end subroutine + subroutine variant2 () + end subroutine + subroutine test () !$omp parallel call base () ! { dg-final { scan-tree-dump-times "variant \\\(\\\);" 1 "gimple" } } !$omp end parallel end subroutine + + subroutine test2 () + !$omp target + call base2 () ! { dg-final { scan-tree-dump-times "variant2 \\\(\\\);" 1 "gimple" } } + !$omp end target + end subroutine end module diff --git a/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 b/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 index cd2e39a..5d0d200 100644 --- a/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 @@ -7,7 +7,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -33,7 +33,7 @@ subroutine f1 !$omp end sections !$omp sections !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -72,7 +72,7 @@ subroutine f1 !$omp sections !$omp section !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -105,7 +105,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -129,7 +129,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -150,7 +150,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -171,7 +171,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -195,7 +195,7 @@ subroutine f1 block; end block end do !$omp sections - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -224,7 +224,7 @@ subroutine f1 block; end block end do !$omp sections - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -257,7 +257,7 @@ subroutine f2 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections diff --git a/gcc/testsuite/gfortran.dg/gomp/reduction4.f90 b/gcc/testsuite/gfortran.dg/gomp/reduction4.f90 index 52d504b..71b4231 100644 --- a/gcc/testsuite/gfortran.dg/gomp/reduction4.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/reduction4.f90 @@ -137,7 +137,7 @@ end ! { dg-final { scan-tree-dump-times "#pragma omp sections reduction\\(task,\\\+:a\\)" 1 "original" } } ! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) reduction\\(\\\+:a\\)" 2 "original" } } ! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) reduction\\(task,\\\+:a\\)" 1 "original" } } -! { dg-final { scan-tree-dump-times "#pragma omp target in_reduction\\(\\\+:b\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp target map\\(always,tofrom:b\\) in_reduction\\(\\\+:b\\)" 1 "original" } } ! { dg-final { scan-tree-dump-times "#pragma omp task in_reduction\\(\\\+:a\\)" 1 "original" } } ! { dg-final { scan-tree-dump-times "#pragma omp teams reduction\\(\\\+:b\\)" 2 "original" } } ! { dg-final { scan-tree-dump-times "#pragma omp taskloop reduction\\(\\\+:a\\) in_reduction\\(\\\+:b\\)" 2 "original" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 new file mode 100644 index 0000000..ef8507e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 @@ -0,0 +1,214 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x, i, n + + x = 0 + n = 10 + + !$omp parallel + block + call do_work + end block + + !$omp parallel + block + call do_work + end block + !$omp end parallel + + !$omp teams + block + call do_work + end block + + !$omp teams + block + call do_work + end block + !$omp end teams + + !$omp masked + block + x = x + 1 + end block + + !$omp masked + block + x = x + 1 + end block + !$omp end masked + + !$omp scope + block + call do_work + end block + + !$omp scope + block + call do_work + end block + !$omp end scope + + !$omp single + block + x = x + 1 + end block + + !$omp single + block + x = x + 1 + end block + !$omp end single + + !$omp workshare + block + x = x + 1 + end block + + !$omp workshare + block + x = x + 1 + end block + !$omp end workshare + + !$omp task + block + call do_work + end block + + !$omp task + block + call do_work + end block + !$omp end task + + !$omp target data map(x) + block + x = x + 1 + end block + + !$omp target data map(x) + block + x = x + 1 + end block + !$omp end target data + + !$omp target + block + x = x + 1 + end block + + !$omp target + block + x = x + 1 + end block + !$omp end target + + !$omp parallel workshare + block + x = x + 1 + end block + + !$omp parallel workshare + block + x = x + 1 + end block + !$omp end parallel workshare + + !$omp parallel masked + block + x = x + 1 + end block + + !$omp parallel masked + block + x = x + 1 + end block + !$omp end parallel masked + + !$omp target parallel + block + call do_work + end block + + !$omp target parallel + block + call do_work + end block + !$omp end target parallel + + !$omp target teams + block + call do_work + end block + + !$omp target teams + block + call do_work + end block + !$omp end target teams + + !$omp critical + block + x = x + 1 + end block + + !$omp critical + block + x = x + 1 + end block + !$omp end critical + + !$omp taskgroup + block + x = x + 1 + end block + + !$omp taskgroup + block + x = x + 1 + end block + !$omp end taskgroup + + !$omp do ordered + do i = 1, n + !$omp ordered + block + call do_work + end block + end do + + !$omp do ordered + do i = 1, n + !$omp ordered + block + call do_work + end block + !$omp end ordered + end do + + !$omp master + block + x = x + 1 + end block + + !$omp master + block + x = x + 1 + end block + !$omp end master + + !$omp parallel master + block + x = x + 1 + end block + + !$omp parallel master + block + x = x + 1 + end block + !$omp end parallel master + +end program diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 new file mode 100644 index 0000000..ad4d08a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 @@ -0,0 +1,139 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x, i, n + + x = 0 + n = 10 + + !$omp parallel + block + call do_work + end block + call do_work + !$omp end parallel ! { dg-error "Unexpected !.OMP END PARALLEL statement" } + + !$omp teams + block + call do_work + end block + call do_work + !$omp end teams ! { dg-error "Unexpected !.OMP END TEAMS statement" } + + !$omp masked + block + x = x + 1 + end block + x = x + 1 + !$omp end masked ! { dg-error "Unexpected !.OMP END MASKED statement" } + + !$omp scope + block + call do_work + end block + call do_work + !$omp end scope ! { dg-error "Unexpected !.OMP END SCOPE statement" } + + !$omp single + block + x = x + 1 + end block + x = x + 1 + !$omp end single ! { dg-error "Unexpected !.OMP END SINGLE statement" } + + !$omp workshare + block + x = x + 1 + end block + x = x + 1 + !$omp end workshare ! { dg-error "Unexpected !.OMP END WORKSHARE statement" } + + !$omp task + block + call do_work + end block + call do_work + !$omp end task ! { dg-error "Unexpected !.OMP END TASK statement" } + + !$omp target data map(x) + block + x = x + 1 + end block + x = x + 1 + !$omp end target data ! { dg-error "Unexpected !.OMP END TARGET DATA statement" } + + !$omp target + block + x = x + 1 + end block + x = x + 1 + !$omp end target ! { dg-error "Unexpected !.OMP END TARGET statement" } + + !$omp parallel workshare + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel workshare ! { dg-error "Unexpected !.OMP END PARALLEL WORKSHARE statement" } + + !$omp parallel masked + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel masked ! { dg-error "Unexpected !.OMP END PARALLEL MASKED statement" } + + !$omp target parallel + block + call do_work + end block + call do_work + !$omp end target parallel ! { dg-error "Unexpected !.OMP END TARGET PARALLEL statement" } + + !$omp target teams + block + call do_work + end block + call do_work + !$omp end target teams ! { dg-error "Unexpected !.OMP END TARGET TEAMS statement" } + + !$omp critical + block + x = x + 1 + end block + x = x + 1 + !$omp end critical ! { dg-error "Unexpected !.OMP END CRITICAL statement" } + + !$omp taskgroup + block + x = x + 1 + end block + x = x + 1 + !$omp end taskgroup ! { dg-error "Unexpected !.OMP END TASKGROUP statement" } + + !$omp do ordered + do i = 1, n + !$omp ordered + block + call do_work + end block + call do_work + !$omp end ordered ! { dg-error "Unexpected !.OMP END ORDERED statement" } + end do + + !$omp master + block + x = x + 1 + end block + x = x + 1 + !$omp end master ! { dg-error "Unexpected !.OMP END MASTER statement" } + + !$omp parallel master + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel master ! { dg-error "Unexpected !.OMP END PARALLEL MASTER statement" } + +end program diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 new file mode 100644 index 0000000..ae85fa0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 @@ -0,0 +1,52 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x, y + + x = 0 + y = 0 + + !$omp parallel + !$omp parallel + block + call do_work + end block + !$omp end parallel + !$omp end parallel + + !$omp workshare + block + x = 1 + !$omp critical + block + y = 3 + end block + end block + + !$omp sections + block + !$omp section + block + x = 1 + end block + x = x + 2 + !$omp section + call do_work + end block + + !$omp sections + !$omp section + block + end block + x = 1 + !$omp end sections + + !$omp sections + block + block + end block + x = 1 + end block + +end program main diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 9ebca7a..1c8b1eb 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -7580,6 +7580,188 @@ proc check_effective_target_vect_element_align_preferred { } { && [check_effective_target_vect_variable_length] }] } +# Return true if vectorization of v2qi/v4qi/v8qi/v16qi/v2hi store is enabed. +# Return zero if the desirable pattern isn't found. +# It's used by Warray-bounds/Wstringop-overflow testcases which are +# regressed by O2 vectorization, refer to PR102697/PR102462/PR102706 +proc check_vect_slp_aligned_store_usage { pattern macro } { + global tool + + set result [check_compile slp_aligned_store_usage assembly { + char a[16] __attribute__ ((aligned (16))); + short b[4] __attribute__((aligned(8))); + int c[4] __attribute__((aligned(16))); + #ifdef TEST_V8QI + void + foo () + { + a[0] = 0; + a[1] = 1; + a[2] = 2; + a[3] = 3; + a[4] = 4; + a[5] = 5; + a[6] = 6; + a[7] = 7; + } + #elif TEST_V16QI + void + foo1 () + { + a[0] = 0; + a[1] = 1; + a[2] = 2; + a[3] = 3; + a[4] = 4; + a[5] = 5; + a[6] = 6; + a[7] = 7; + a[8] = 8; + a[9] = 9; + a[10] = 10; + a[11] = 11; + a[12] = 12; + a[13] = 13; + a[14] = 14; + a[15] = 15; + } + #elif TEST_V4QI + void + foo2 () + { + a[0] = 0; + a[1] = 1; + a[2] = 2; + a[3] = 3; + } + #elif TEST_V2QI + void + foo3 () + { + a[0] = 0; + a[1] = 1; + } + #elif TEST_V2HI + void + foo4 () + { + b[0] = 0; + b[1] = 1; + } + #elif TEST_V4HI + void + foo5 () + { + b[0] = 0; + b[1] = 1; + b[2] = 2; + b[3] = 3; + } + #elif TEST_V2SI + void + foo6 () + { + c[0] = 0; + c[1] = 1; + } + #elif TEST_V4SI + void + foo7 () + { + c[0] = 0; + c[1] = 1; + c[2] = 2; + c[3] = 3; + } + #endif + } "-O2 -fopt-info-all -D$macro" ] + + # Get compiler emitted messages and delete generated file. + set lines [lindex $result 0] + set output [lindex $result 1] + remote_file build delete $output + + # Check pattern exits in lines, set it to zero if not found. + if { [regexp $pattern $lines] } then { + return 1 + } + + return 0 +} + +# Return the true if target support vectorization of 2-byte char stores +# with 2-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v2qi_store { } { + set pattern {add new stmt: MEM <vector\(2\) char>} + set macro "TEST_V2QI" + return [check_cached_effective_target vect_slp_v2qi_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro] }] + +} + +# Return the true if target support vectorization of 4-byte char stores +# with 4-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v4qi_store { } { + set pattern {add new stmt: MEM <vector\(4\) char>} + set macro "TEST_V4QI" + return [check_cached_effective_target vect_slp_v4qi_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + +# Return the true if target support vectorization of 8-byte char stores +# with 8-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v8qi_store { } { + set pattern {add new stmt: MEM <vector\(8\) char>} + set macro "TEST_V8QI" + return [check_cached_effective_target vect_slp_v8qi_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + +# Return the true if target support vectorization of 16-byte char stores +# with 16-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v16qi_store { } { + set pattern {add new stmt: MEM <vector\(16\) char>} + set macro "TEST_V16QI" + return [check_cached_effective_target vect_slp_v16qi_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + +# Return the true if target support vectorization of 4-byte short stores +# with 4-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v2hi_store { } { + set pattern {add new stmt: MEM <vector\(2\) short int>} + set macro "TEST_V2HI" + return [check_cached_effective_target vect_slp_v2hi_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + +# Return the true if target support vectorization of 8-byte short stores +# with 8-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v4hi_store { } { + set pattern {add new stmt: MEM <vector\(4\) short int>} + set macro "TEST_V4HI" + return [check_cached_effective_target vect_slp_v4hi_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + +# Return the true if target support vectorization of 8-byte int stores +# with 8-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v2si_store { } { + set pattern {add new stmt: MEM <vector\(2\) int>} + set macro "TEST_V2SI" + return [check_cached_effective_target vect_slp_v2si_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + +# Return the true if target support vectorization of 16-byte int stores +# with 16-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v4si_store { } { + set pattern {add new stmt: MEM <vector\(4\) int>} + set macro "TEST_V4SI" + return [check_cached_effective_target vect_slp_v4si_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + # Return 1 if we can align stack data to the preferred vector alignment. proc check_effective_target_vect_align_stack_vars { } { diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 4b4b0b5..b3a27bc 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see #include "value-prof.h" #include "tree-inline.h" #include "tree-ssa-live.h" +#include "tree-ssa-dce.h" #include "omp-general.h" #include "omp-expand.h" #include "tree-cfgcleanup.h" @@ -9666,13 +9667,52 @@ make_pass_warn_unused_result (gcc::context *ctxt) return new pass_warn_unused_result (ctxt); } +/* Maybe Remove stores to variables we marked write-only. + Return true if a store was removed. */ +static bool +maybe_remove_writeonly_store (gimple_stmt_iterator &gsi, gimple *stmt, + bitmap dce_ssa_names) +{ + /* Keep access when store has side effect, i.e. in case when source + is volatile. */ + if (!gimple_store_p (stmt) + || gimple_has_side_effects (stmt) + || optimize_debug) + return false; + + tree lhs = get_base_address (gimple_get_lhs (stmt)); + + if (!VAR_P (lhs) + || (!TREE_STATIC (lhs) && !DECL_EXTERNAL (lhs)) + || !varpool_node::get (lhs)->writeonly) + return false; + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Removing statement, writes" + " to write only var:\n"); + print_gimple_stmt (dump_file, stmt, 0, + TDF_VOPS|TDF_MEMSYMS); + } + + /* Mark ssa name defining to be checked for simple dce. */ + if (gimple_assign_single_p (stmt)) + { + tree rhs = gimple_assign_rhs1 (stmt); + if (TREE_CODE (rhs) == SSA_NAME + && !SSA_NAME_IS_DEFAULT_DEF (rhs)) + bitmap_set_bit (dce_ssa_names, SSA_NAME_VERSION (rhs)); + } + unlink_stmt_vdef (stmt); + gsi_remove (&gsi, true); + release_defs (stmt); + return true; +} + /* IPA passes, compilation of earlier functions or inlining might have changed some properties, such as marked functions nothrow, pure, const or noreturn. - Remove redundant edges and basic blocks, and create new ones if necessary. - - This pass can't be executed as stand alone pass from pass manager, because - in between inlining and this fixup the verify_flow_info would fail. */ + Remove redundant edges and basic blocks, and create new ones if necessary. */ unsigned int execute_fixup_cfg (void) @@ -9685,6 +9725,7 @@ execute_fixup_cfg (void) profile_count num = node->count; profile_count den = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; bool scale = num.initialized_p () && !(num == den); + auto_bitmap dce_ssa_names; if (scale) { @@ -9724,26 +9765,13 @@ execute_fixup_cfg (void) todo |= TODO_cleanup_cfg; } - /* Remove stores to variables we marked write-only. - Keep access when store has side effect, i.e. in case when source - is volatile. */ - if (gimple_store_p (stmt) - && !gimple_has_side_effects (stmt) - && !optimize_debug) + /* Remove stores to variables we marked write-only. */ + if (maybe_remove_writeonly_store (gsi, stmt, dce_ssa_names)) { - tree lhs = get_base_address (gimple_get_lhs (stmt)); - - if (VAR_P (lhs) - && (TREE_STATIC (lhs) || DECL_EXTERNAL (lhs)) - && varpool_node::get (lhs)->writeonly) - { - unlink_stmt_vdef (stmt); - gsi_remove (&gsi, true); - release_defs (stmt); - todo |= TODO_update_ssa | TODO_cleanup_cfg; - continue; - } + todo |= TODO_update_ssa | TODO_cleanup_cfg; + continue; } + /* For calls we can simply remove LHS when it is known to be write-only. */ if (is_gimple_call (stmt) @@ -9804,6 +9832,8 @@ execute_fixup_cfg (void) && (todo & TODO_cleanup_cfg)) loops_state_set (LOOPS_NEED_FIXUP); + simple_dce_from_worklist (dce_ssa_names); + return todo; } diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index 57bac06..46f4ffe 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -757,6 +757,9 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, *var = NULL_TREE; *off = NULL_TREE; + if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type)) + return false; + switch (code) { case INTEGER_CST: diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index 15dcc1e..b165dc0 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -2490,7 +2490,7 @@ predicate_rhs_code (gassign *stmt, tree mask, tree cond, */ static void -predicate_statements (loop_p loop) +predicate_statements (loop_p loop, edge pe) { unsigned int i, orig_loop_num_nodes = loop->num_nodes; auto_vec<int, 1> vect_sizes; @@ -2596,8 +2596,7 @@ predicate_statements (loop_p loop) if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt2)) && expr_invariant_in_loop_p (loop, gimple_assign_rhs1 (stmt2))) - gsi_insert_on_edge_immediate (loop_preheader_edge (loop), - stmt2); + gsi_insert_on_edge_immediate (pe, stmt2); else if (first) { gsi_insert_before (&gsi, stmt2, GSI_NEW_STMT); @@ -2679,7 +2678,7 @@ remove_conditions_and_labels (loop_p loop) blocks. Replace PHI nodes with conditional modify expressions. */ static void -combine_blocks (class loop *loop) +combine_blocks (class loop *loop, edge pe) { basic_block bb, exit_bb, merge_target_bb; unsigned int orig_loop_num_nodes = loop->num_nodes; @@ -2692,7 +2691,7 @@ combine_blocks (class loop *loop) predicate_all_scalar_phis (loop); if (need_to_predicate || need_to_rewrite_undefined) - predicate_statements (loop); + predicate_statements (loop, pe); /* Merge basic blocks. */ exit_bb = NULL; @@ -3187,6 +3186,7 @@ tree_if_conversion (class loop *loop, vec<gimple *> *preds) bool aggressive_if_conv; class loop *rloop; bitmap exit_bbs; + edge pe; again: rloop = NULL; @@ -3218,6 +3218,9 @@ tree_if_conversion (class loop *loop, vec<gimple *> *preds) || loop->dont_vectorize)) goto cleanup; + /* The edge to insert invariant stmts on. */ + pe = loop_preheader_edge (loop); + /* Since we have no cost model, always version loops unless the user specified -ftree-loop-if-convert or unless versioning is required. Either version this loop, or if the pattern is right for outer-loop @@ -3255,12 +3258,18 @@ tree_if_conversion (class loop *loop, vec<gimple *> *preds) gcc_assert (nloop->inner && nloop->inner->next == NULL); rloop = nloop->inner; } + else + /* If we versioned loop then make sure to insert invariant + stmts before the .LOOP_VECTORIZED check since the vectorizer + will re-use that for things like runtime alias versioning + whose condition can end up using those invariants. */ + pe = single_pred_edge (gimple_bb (preds->last ())); } /* Now all statements are if-convertible. Combine all the basic blocks into one huge basic block doing the if-conversion on-the-fly. */ - combine_blocks (loop); + combine_blocks (loop, pe); /* Perform local CSE, this esp. helps the vectorizer analysis if loads and stores are involved. CSE only the loop body, not the entry diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index 6a4dc72..4334e05 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -45,13 +45,6 @@ struct object_size_info unsigned int *stack, *tos; }; -static const unsigned HOST_WIDE_INT unknown[4] = { - HOST_WIDE_INT_M1U, - HOST_WIDE_INT_M1U, - 0, - 0 -}; - static tree compute_object_offset (const_tree, const_tree); static bool addr_object_size (struct object_size_info *, const_tree, int, unsigned HOST_WIDE_INT *); @@ -82,6 +75,11 @@ static bitmap computed[4]; /* Maximum value of offset we consider to be addition. */ static unsigned HOST_WIDE_INT offset_limit; +static inline unsigned HOST_WIDE_INT +unknown (int object_size_type) +{ + return ((unsigned HOST_WIDE_INT) -((object_size_type >> 1) ^ 1)); +} /* Initialize OFFSET_LIMIT variable. */ static void @@ -204,7 +202,7 @@ decl_init_size (tree decl, bool min) /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR. OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. - If unknown, return unknown[object_size_type]. */ + If unknown, return unknown (object_size_type). */ static bool addr_object_size (struct object_size_info *osi, const_tree ptr, @@ -216,7 +214,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, /* Set to unknown and overwrite just before returning if the size could be determined. */ - *psize = unknown[object_size_type]; + *psize = unknown (object_size_type); pt_var = TREE_OPERAND (ptr, 0); while (handled_component_p (pt_var)) @@ -244,9 +242,9 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, SSA_NAME_VERSION (var))) sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)]; else - sz = unknown[object_size_type]; + sz = unknown (object_size_type); } - if (sz != unknown[object_size_type]) + if (sz != unknown (object_size_type)) { offset_int mem_offset; if (mem_ref_offset (pt_var).is_constant (&mem_offset)) @@ -257,13 +255,13 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, else if (wi::fits_uhwi_p (dsz)) sz = dsz.to_uhwi (); else - sz = unknown[object_size_type]; + sz = unknown (object_size_type); } else - sz = unknown[object_size_type]; + sz = unknown (object_size_type); } - if (sz != unknown[object_size_type] && sz < offset_limit) + if (sz != unknown (object_size_type) && sz < offset_limit) pt_var_size = size_int (sz); } else if (DECL_P (pt_var)) @@ -445,7 +443,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL. Handles calls to functions declared with attribute alloc_size. OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. - If unknown, return unknown[object_size_type]. */ + If unknown, return unknown (object_size_type). */ static unsigned HOST_WIDE_INT alloc_object_size (const gcall *call, int object_size_type) @@ -459,7 +457,7 @@ alloc_object_size (const gcall *call, int object_size_type) calltype = gimple_call_fntype (call); if (!calltype) - return unknown[object_size_type]; + return unknown (object_size_type); /* Set to positions of alloc_size arguments. */ int arg1 = -1, arg2 = -1; @@ -479,7 +477,7 @@ alloc_object_size (const gcall *call, int object_size_type) || (arg2 >= 0 && (arg2 >= (int)gimple_call_num_args (call) || TREE_CODE (gimple_call_arg (call, arg2)) != INTEGER_CST))) - return unknown[object_size_type]; + return unknown (object_size_type); tree bytes = NULL_TREE; if (arg2 >= 0) @@ -492,7 +490,7 @@ alloc_object_size (const gcall *call, int object_size_type) if (bytes && tree_fits_uhwi_p (bytes)) return tree_to_uhwi (bytes); - return unknown[object_size_type]; + return unknown (object_size_type); } @@ -534,7 +532,7 @@ compute_builtin_object_size (tree ptr, int object_size_type, /* Set to unknown and overwrite just before returning if the size could be determined. */ - *psize = unknown[object_size_type]; + *psize = unknown (object_size_type); if (! offset_limit) init_offset_limit (); @@ -674,7 +672,7 @@ compute_builtin_object_size (tree ptr, int object_size_type, { EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi) if (object_sizes[object_size_type][i] - != unknown[object_size_type]) + != unknown (object_size_type)) { print_generic_expr (dump_file, ssa_name (i), dump_flags); @@ -692,7 +690,7 @@ compute_builtin_object_size (tree ptr, int object_size_type, } *psize = object_sizes[object_size_type][SSA_NAME_VERSION (ptr)]; - return *psize != unknown[object_size_type]; + return *psize != unknown (object_size_type); } /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */ @@ -705,7 +703,7 @@ expr_object_size (struct object_size_info *osi, tree ptr, tree value) unsigned HOST_WIDE_INT bytes; gcc_assert (object_sizes[object_size_type][varno] - != unknown[object_size_type]); + != unknown (object_size_type)); gcc_assert (osi->pass == 0); if (TREE_CODE (value) == WITH_SIZE_EXPR) @@ -718,7 +716,7 @@ expr_object_size (struct object_size_info *osi, tree ptr, tree value) if (TREE_CODE (value) == ADDR_EXPR) addr_object_size (osi, value, object_size_type, &bytes); else - bytes = unknown[object_size_type]; + bytes = unknown (object_size_type); if ((object_size_type & 2) == 0) { @@ -745,7 +743,7 @@ call_object_size (struct object_size_info *osi, tree ptr, gcall *call) gcc_assert (is_gimple_call (call)); gcc_assert (object_sizes[object_size_type][varno] - != unknown[object_size_type]); + != unknown (object_size_type)); gcc_assert (osi->pass == 0); bytes = alloc_object_size (call, object_size_type); @@ -770,24 +768,12 @@ unknown_object_size (struct object_size_info *osi, tree ptr) { int object_size_type = osi->object_size_type; unsigned int varno = SSA_NAME_VERSION (ptr); - unsigned HOST_WIDE_INT bytes; + unsigned HOST_WIDE_INT bytes = unknown (object_size_type); - gcc_assert (object_sizes[object_size_type][varno] - != unknown[object_size_type]); - gcc_assert (osi->pass == 0); + gcc_checking_assert (object_sizes[object_size_type][varno] != bytes); + gcc_checking_assert (osi->pass == 0); - bytes = unknown[object_size_type]; - - if ((object_size_type & 2) == 0) - { - if (object_sizes[object_size_type][varno] < bytes) - object_sizes[object_size_type][varno] = bytes; - } - else - { - if (object_sizes[object_size_type][varno] > bytes) - object_sizes[object_size_type][varno] = bytes; - } + object_sizes[object_size_type][varno] = bytes; } @@ -802,11 +788,11 @@ merge_object_sizes (struct object_size_info *osi, tree dest, tree orig, unsigned int varno = SSA_NAME_VERSION (dest); unsigned HOST_WIDE_INT orig_bytes; - if (object_sizes[object_size_type][varno] == unknown[object_size_type]) + if (object_sizes[object_size_type][varno] == unknown (object_size_type)) return false; if (offset >= offset_limit) { - object_sizes[object_size_type][varno] = unknown[object_size_type]; + object_sizes[object_size_type][varno] = unknown (object_size_type); return false; } @@ -814,7 +800,7 @@ merge_object_sizes (struct object_size_info *osi, tree dest, tree orig, collect_object_sizes_for (osi, orig); orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)]; - if (orig_bytes != unknown[object_size_type]) + if (orig_bytes != unknown (object_size_type)) orig_bytes = (offset > orig_bytes) ? HOST_WIDE_INT_0U : orig_bytes - offset; @@ -865,7 +851,7 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) else gcc_unreachable (); - if (object_sizes[object_size_type][varno] == unknown[object_size_type]) + if (object_sizes[object_size_type][varno] == unknown (object_size_type)) return false; /* Handle PTR + OFFSET here. */ @@ -874,7 +860,7 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) || TREE_CODE (op0) == ADDR_EXPR)) { if (! tree_fits_uhwi_p (op1)) - bytes = unknown[object_size_type]; + bytes = unknown (object_size_type); else if (TREE_CODE (op0) == SSA_NAME) return merge_object_sizes (osi, var, op0, tree_to_uhwi (op1)); else @@ -883,10 +869,10 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) /* op0 will be ADDR_EXPR here. */ addr_object_size (osi, op0, object_size_type, &bytes); - if (bytes == unknown[object_size_type]) + if (bytes == unknown (object_size_type)) ; else if (off > offset_limit) - bytes = unknown[object_size_type]; + bytes = unknown (object_size_type); else if (off > bytes) bytes = 0; else @@ -894,7 +880,7 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) } } else - bytes = unknown[object_size_type]; + bytes = unknown (object_size_type); if ((object_size_type & 2) == 0) { @@ -924,7 +910,7 @@ cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt) gcc_assert (gimple_assign_rhs_code (stmt) == COND_EXPR); - if (object_sizes[object_size_type][varno] == unknown[object_size_type]) + if (object_sizes[object_size_type][varno] == unknown (object_size_type)) return false; then_ = gimple_assign_rhs2 (stmt); @@ -935,7 +921,7 @@ cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt) else expr_object_size (osi, var, then_); - if (object_sizes[object_size_type][varno] == unknown[object_size_type]) + if (object_sizes[object_size_type][varno] == unknown (object_size_type)) return reexamine; if (TREE_CODE (else_) == SSA_NAME) @@ -956,9 +942,9 @@ cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt) object size is object size of the first operand minus the constant. If the constant is bigger than the number of remaining bytes until the end of the object, object size is 0, but if it is instead a pointer - subtraction, object size is unknown[object_size_type]. + subtraction, object size is unknown (object_size_type). To differentiate addition from subtraction, ADDR_EXPR returns - unknown[object_size_type] for all objects bigger than half of the address + unknown (object_size_type) for all objects bigger than half of the address space, and constants less than half of the address space are considered addition, while bigger constants subtraction. For a memcpy like GIMPLE_CALL that always returns one of its arguments, the @@ -1030,7 +1016,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) expr_object_size (osi, var, rhs); } else - unknown_object_size (osi, var); + unknown_object_size (osi, var); break; } @@ -1053,7 +1039,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) case GIMPLE_ASM: /* Pointers defined by __asm__ statements can point anywhere. */ - object_sizes[object_size_type][varno] = unknown[object_size_type]; + object_sizes[object_size_type][varno] = unknown (object_size_type); break; case GIMPLE_NOP: @@ -1062,7 +1048,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) expr_object_size (osi, var, SSA_NAME_VAR (var)); else /* Uninitialized SSA names point nowhere. */ - object_sizes[object_size_type][varno] = unknown[object_size_type]; + object_sizes[object_size_type][varno] = unknown (object_size_type); break; case GIMPLE_PHI: @@ -1074,7 +1060,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) tree rhs = gimple_phi_arg (stmt, i)->def; if (object_sizes[object_size_type][varno] - == unknown[object_size_type]) + == unknown (object_size_type)) break; if (TREE_CODE (rhs) == SSA_NAME) @@ -1090,7 +1076,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) } if (! reexamine - || object_sizes[object_size_type][varno] == unknown[object_size_type]) + || object_sizes[object_size_type][varno] == unknown (object_size_type)) { bitmap_set_bit (computed[object_size_type], varno); bitmap_clear_bit (osi->reexamine, varno); @@ -1298,6 +1284,10 @@ object_sizes_execute (function *fun, bool insert_min_max_p) if (!gimple_call_builtin_p (call, BUILT_IN_OBJECT_SIZE)) continue; + tree lhs = gimple_call_lhs (call); + if (!lhs) + continue; + init_object_sizes (); /* If insert_min_max_p, only attempt to fold @@ -1312,11 +1302,9 @@ object_sizes_execute (function *fun, bool insert_min_max_p) { unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost); tree ptr = gimple_call_arg (call, 0); - tree lhs = gimple_call_lhs (call); if ((object_size_type == 1 || object_size_type == 3) && (TREE_CODE (ptr) == ADDR_EXPR - || TREE_CODE (ptr) == SSA_NAME) - && lhs) + || TREE_CODE (ptr) == SSA_NAME)) { tree type = TREE_TYPE (lhs); unsigned HOST_WIDE_INT bytes; @@ -1339,10 +1327,6 @@ object_sizes_execute (function *fun, bool insert_min_max_p) continue; } - tree lhs = gimple_call_lhs (call); - if (!lhs) - continue; - result = gimple_fold_stmt_to_constant (call, do_valueize); if (!result) { diff --git a/gcc/tree-ssa-threadbackward.c b/gcc/tree-ssa-threadbackward.c index 62f936a..38913b0 100644 --- a/gcc/tree-ssa-threadbackward.c +++ b/gcc/tree-ssa-threadbackward.c @@ -52,12 +52,10 @@ along with GCC; see the file COPYING3. If not see class back_threader_registry { public: - back_threader_registry (); bool register_path (const vec<basic_block> &, edge taken); bool thread_through_all_blocks (bool may_peel_loop_headers); private: back_jt_path_registry m_lowlevel_registry; - int m_threaded_paths; }; // Class to abstract the profitability code for the backwards threader. @@ -78,7 +76,6 @@ class back_threader { public: back_threader (bool speed_p, bool resolve); - ~back_threader (); void maybe_thread_block (basic_block bb); bool thread_through_all_blocks (bool may_peel_loop_headers); private: @@ -130,10 +127,6 @@ back_threader::back_threader (bool speed_p, bool resolve) m_resolve = resolve; } -back_threader::~back_threader () -{ -} - // Register the current path for jump threading if it's profitable to // do so. // @@ -147,6 +140,10 @@ back_threader::maybe_register_path () if (taken_edge && taken_edge != UNREACHABLE_EDGE) { + // Avoid circular paths. + if (m_visited_bbs.contains (taken_edge->dest)) + return UNREACHABLE_EDGE; + bool irreducible = false; bool profitable = m_profit.profitable_path_p (m_path, m_name, taken_edge, &irreducible); @@ -574,11 +571,6 @@ back_threader::debug () dump (stderr); } -back_threader_registry::back_threader_registry () -{ - m_threaded_paths = 0; -} - bool back_threader_registry::thread_through_all_blocks (bool may_peel_loop_headers) { @@ -620,6 +612,15 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path, if (m_path.length () <= 1) return false; + if (m_path.length () > (unsigned) param_max_fsm_thread_length) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " FAIL: Jump-thread path not considered: " + "the number of basic blocks on the path " + "exceeds PARAM_MAX_FSM_THREAD_LENGTH.\n"); + return false; + } + int n_insns = 0; gimple_stmt_iterator gsi; loop_p loop = m_path[0]->loop_father; @@ -919,9 +920,7 @@ back_threader_registry::register_path (const vec<basic_block> &m_path, m_lowlevel_registry.push_edge (jump_thread_path, taken_edge, EDGE_NO_COPY_SRC_BLOCK); - - if (m_lowlevel_registry.register_jump_thread (jump_thread_path)) - ++m_threaded_paths; + m_lowlevel_registry.register_jump_thread (jump_thread_path); return true; } @@ -1059,7 +1058,7 @@ public: {} opt_pass * clone (void) override { - return new pass_thread_jumps (m_ctxt); + return new pass_thread_jumps_full (m_ctxt); } bool gate (function *) override { diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c index 32ce1e3..8e6f043 100644 --- a/gcc/tree-ssa-threadupdate.c +++ b/gcc/tree-ssa-threadupdate.c @@ -278,7 +278,7 @@ cancel_thread (vec<jump_thread_edge *> *path, const char *reason = NULL) if (dump_file && (dump_flags & TDF_DETAILS)) { if (reason) - fprintf (dump_file, "%s:\n", reason); + fprintf (dump_file, "%s: ", reason); dump_jump_thread_path (dump_file, *path, false); fprintf (dump_file, "\n"); @@ -2295,12 +2295,6 @@ back_jt_path_registry::adjust_paths_after_duplication (unsigned curr_path_num) { vec<jump_thread_edge *> *curr_path = m_paths[curr_path_num]; - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "just threaded: "); - debug_path (dump_file, curr_path_num); - } - /* Iterate through all the other paths and adjust them. */ for (unsigned cand_path_num = 0; cand_path_num < m_paths.length (); ) { @@ -2409,12 +2403,6 @@ back_jt_path_registry::duplicate_thread_path (edge entry, if (!can_copy_bbs_p (region, n_region)) return false; - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nabout to thread: "); - debug_path (dump_file, current_path_no); - } - /* Some sanity checking. Note that we do not check for all possible missuses of the functions. I.e. if you ask to copy something weird, it will work, but the state of structures probably will not be @@ -2771,6 +2759,7 @@ jt_path_registry::cancel_invalid_paths (vec<jump_thread_edge *> &path) bool seen_latch = false; int loops_crossed = 0; bool crossed_latch = false; + bool crossed_loop_header = false; // Use ->dest here instead of ->src to ignore the first block. The // first block is allowed to be in a different loop, since it'll be // redirected. See similar comment in profitable_path_p: "we don't @@ -2804,6 +2793,14 @@ jt_path_registry::cancel_invalid_paths (vec<jump_thread_edge *> &path) ++loops_crossed; } + // ?? Avoid threading through loop headers that remain in the + // loop, as such threadings tend to create sub-loops which + // _might_ be OK ??. + if (e->dest->loop_father->header == e->dest + && !flow_loop_nested_p (exit->dest->loop_father, + e->dest->loop_father)) + crossed_loop_header = true; + if (flag_checking && !m_backedge_threads) gcc_assert ((path[i]->e->flags & EDGE_DFS_BACK) == 0); } @@ -2829,6 +2826,21 @@ jt_path_registry::cancel_invalid_paths (vec<jump_thread_edge *> &path) cancel_thread (&path, "Path crosses loops"); return true; } + // The path should either start and end in the same loop or exit the + // loop it starts in but never enter a loop. This also catches + // creating irreducible loops, not only rotation. + if (entry->src->loop_father != exit->dest->loop_father + && !flow_loop_nested_p (exit->src->loop_father, + entry->dest->loop_father)) + { + cancel_thread (&path, "Path rotates loop"); + return true; + } + if (crossed_loop_header) + { + cancel_thread (&path, "Path crosses loop header but does not exit it"); + return true; + } return false; } diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index a19045f..556ae97 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -1396,7 +1396,9 @@ vector_alignment_reachable_p (dr_vec_info *dr_info) static void vect_get_data_access_cost (vec_info *vinfo, dr_vec_info *dr_info, - unsigned int *inside_cost, + dr_alignment_support alignment_support_scheme, + int misalignment, + unsigned int *inside_cost, unsigned int *outside_cost, stmt_vector_for_cost *body_cost_vec, stmt_vector_for_cost *prologue_cost_vec) @@ -1411,10 +1413,12 @@ vect_get_data_access_cost (vec_info *vinfo, dr_vec_info *dr_info, ncopies = vect_get_num_copies (loop_vinfo, STMT_VINFO_VECTYPE (stmt_info)); if (DR_IS_READ (dr_info->dr)) - vect_get_load_cost (vinfo, stmt_info, ncopies, true, inside_cost, + vect_get_load_cost (vinfo, stmt_info, ncopies, alignment_support_scheme, + misalignment, true, inside_cost, outside_cost, prologue_cost_vec, body_cost_vec, false); else - vect_get_store_cost (vinfo,stmt_info, ncopies, inside_cost, body_cost_vec); + vect_get_store_cost (vinfo,stmt_info, ncopies, alignment_support_scheme, + misalignment, inside_cost, body_cost_vec); if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, @@ -1465,13 +1469,10 @@ peel_info_hasher::equal (const _vect_peel_info *a, const _vect_peel_info *b) static void vect_peeling_hash_insert (hash_table<peel_info_hasher> *peeling_htab, loop_vec_info loop_vinfo, dr_vec_info *dr_info, - int npeel) + int npeel, bool supportable_if_not_aligned) { struct _vect_peel_info elem, *slot; _vect_peel_info **new_slot; - tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt); - bool supportable_dr_alignment - = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, true); elem.npeel = npeel; slot = peeling_htab->find (&elem); @@ -1487,7 +1488,9 @@ vect_peeling_hash_insert (hash_table<peel_info_hasher> *peeling_htab, *new_slot = slot; } - if (!supportable_dr_alignment + /* If this DR is not supported with unknown misalignment then bias + this slot when the cost model is disabled. */ + if (!supportable_if_not_aligned && unlimited_cost_model (LOOP_VINFO_LOOP (loop_vinfo))) slot->count += VECT_MAX_COST; } @@ -1526,29 +1529,49 @@ vect_get_peeling_costs_all_drs (loop_vec_info loop_vinfo, unsigned int *outside_cost, stmt_vector_for_cost *body_cost_vec, stmt_vector_for_cost *prologue_cost_vec, - unsigned int npeel, - bool unknown_misalignment) + unsigned int npeel) { vec<data_reference_p> datarefs = LOOP_VINFO_DATAREFS (loop_vinfo); + bool dr0_alignment_known_p + = (dr0_info + && known_alignment_for_access_p (dr0_info, + STMT_VINFO_VECTYPE (dr0_info->stmt))); + for (data_reference *dr : datarefs) { dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr); if (!vect_relevant_for_alignment_p (dr_info)) continue; - int save_misalignment; - save_misalignment = dr_info->misalignment; + tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt); + dr_alignment_support alignment_support_scheme; + int misalignment; + unsigned HOST_WIDE_INT alignment; + if (npeel == 0) - ; - else if (unknown_misalignment && dr_info == dr0_info) - SET_DR_MISALIGNMENT (dr_info, - vect_dr_misalign_for_aligned_access (dr0_info)); + misalignment = dr_misalignment (dr_info, vectype); + else if (dr_info == dr0_info + || vect_dr_aligned_if_peeled_dr_is (dr_info, dr0_info)) + misalignment = 0; + else if (!dr0_alignment_known_p + || !known_alignment_for_access_p (dr_info, vectype) + || !DR_TARGET_ALIGNMENT (dr_info).is_constant (&alignment)) + misalignment = DR_MISALIGNMENT_UNKNOWN; else - vect_update_misalignment_for_peel (dr_info, dr0_info, npeel); - vect_get_data_access_cost (loop_vinfo, dr_info, inside_cost, outside_cost, + { + misalignment = dr_misalignment (dr_info, vectype); + misalignment += npeel * TREE_INT_CST_LOW (DR_STEP (dr_info->dr)); + misalignment &= alignment - 1; + } + alignment_support_scheme + = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, + misalignment); + + vect_get_data_access_cost (loop_vinfo, dr_info, + alignment_support_scheme, misalignment, + inside_cost, outside_cost, body_cost_vec, prologue_cost_vec); - SET_DR_MISALIGNMENT (dr_info, save_misalignment); } } @@ -1572,7 +1595,7 @@ vect_peeling_hash_get_lowest_cost (_vect_peel_info **slot, vect_get_peeling_costs_all_drs (loop_vinfo, elem->dr_info, &inside_cost, &outside_cost, &body_cost_vec, - &prologue_cost_vec, elem->npeel, false); + &prologue_cost_vec, elem->npeel); body_cost_vec.release (); @@ -1644,26 +1667,38 @@ vect_peeling_supportable (loop_vec_info loop_vinfo, dr_vec_info *dr0_info, vec<data_reference_p> datarefs = LOOP_VINFO_DATAREFS (loop_vinfo); enum dr_alignment_support supportable_dr_alignment; + bool dr0_alignment_known_p + = known_alignment_for_access_p (dr0_info, + STMT_VINFO_VECTYPE (dr0_info->stmt)); + /* Ensure that all data refs can be vectorized after the peel. */ for (data_reference *dr : datarefs) { - int save_misalignment; - if (dr == dr0_info->dr) continue; dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr); - if (!vect_relevant_for_alignment_p (dr_info)) + if (!vect_relevant_for_alignment_p (dr_info) + || vect_dr_aligned_if_peeled_dr_is (dr_info, dr0_info)) continue; - save_misalignment = dr_info->misalignment; - vect_update_misalignment_for_peel (dr_info, dr0_info, npeel); tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt); + int misalignment; + unsigned HOST_WIDE_INT alignment; + if (!dr0_alignment_known_p + || !known_alignment_for_access_p (dr_info, vectype) + || !DR_TARGET_ALIGNMENT (dr_info).is_constant (&alignment)) + misalignment = DR_MISALIGNMENT_UNKNOWN; + else + { + misalignment = dr_misalignment (dr_info, vectype); + misalignment += npeel * TREE_INT_CST_LOW (DR_STEP (dr_info->dr)); + misalignment &= alignment - 1; + } supportable_dr_alignment - = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, false); - SET_DR_MISALIGNMENT (dr_info, save_misalignment); - - if (!supportable_dr_alignment) + = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, + misalignment); + if (supportable_dr_alignment == dr_unaligned_unsupported) return false; } @@ -1802,7 +1837,6 @@ opt_result vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) { class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); - enum dr_alignment_support supportable_dr_alignment; dr_vec_info *first_store = NULL; dr_vec_info *dr0_info = NULL; struct data_reference *dr; @@ -1911,8 +1945,6 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) stmt_vec_info stmt_info = dr_info->stmt; tree vectype = STMT_VINFO_VECTYPE (stmt_info); - supportable_dr_alignment - = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, true); do_peeling = vector_alignment_reachable_p (dr_info); if (do_peeling) { @@ -1956,11 +1988,20 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) } /* Save info about DR in the hash table. Also include peeling - amounts according to the explanation above. */ + amounts according to the explanation above. Indicate + the alignment status when the ref is not aligned. + ??? Rather than using unknown alignment here we should + prune all entries from the peeling hashtable which cause + DRs to be not supported. */ + bool supportable_if_not_aligned + = targetm.vectorize.support_vector_misalignment + (TYPE_MODE (vectype), TREE_TYPE (DR_REF (dr_info->dr)), + DR_MISALIGNMENT_UNKNOWN, false); while (known_le (npeel_tmp, nscalars)) { vect_peeling_hash_insert (&peeling_htab, loop_vinfo, - dr_info, npeel_tmp); + dr_info, npeel_tmp, + supportable_if_not_aligned); npeel_tmp += MAX (1, target_align / dr_size); } @@ -1999,11 +2040,14 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) /* Check for data refs with unsupportable alignment that can be peeled. */ - if (!supportable_dr_alignment) - { - one_dr_unsupportable = true; - unsupportable_dr_info = dr_info; - } + enum dr_alignment_support supportable_dr_alignment + = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, + DR_MISALIGNMENT_UNKNOWN); + if (supportable_dr_alignment == dr_unaligned_unsupported) + { + one_dr_unsupportable = true; + unsupportable_dr_info = dr_info; + } if (!first_store && DR_IS_WRITE (dr)) { @@ -2055,7 +2099,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) vect_get_peeling_costs_all_drs (loop_vinfo, dr0_info, &load_inside_cost, &load_outside_cost, - &dummy, &dummy, estimated_npeels, true); + &dummy, &dummy, estimated_npeels); dummy.release (); if (first_store) @@ -2065,7 +2109,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) &store_inside_cost, &store_outside_cost, &dummy, &dummy, - estimated_npeels, true); + estimated_npeels); dummy.release (); } else @@ -2153,8 +2197,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) stmt_vector_for_cost dummy; dummy.create (2); vect_get_peeling_costs_all_drs (loop_vinfo, NULL, &nopeel_inside_cost, - &nopeel_outside_cost, &dummy, &dummy, - 0, false); + &nopeel_outside_cost, &dummy, &dummy, 0); dummy.release (); /* Add epilogue costs. As we do not peel for alignment here, no prologue @@ -2343,7 +2386,8 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr); stmt_vec_info stmt_info = dr_info->stmt; tree vectype = STMT_VINFO_VECTYPE (stmt_info); - if (aligned_access_p (dr_info, vectype) + int misalignment; + if ((misalignment = dr_misalignment (dr_info, vectype)) == 0 || !vect_relevant_for_alignment_p (dr_info)) continue; @@ -2353,14 +2397,14 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) break; } - supportable_dr_alignment + enum dr_alignment_support supportable_dr_alignment = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, - false); - if (!supportable_dr_alignment) + misalignment); + if (supportable_dr_alignment == dr_unaligned_unsupported) { - if (known_alignment_for_access_p (dr_info, vectype) - || LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).length () - >= (unsigned) param_vect_max_version_for_alignment_checks) + if (misalignment != DR_MISALIGNMENT_UNKNOWN + || (LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).length () + >= (unsigned) param_vect_max_version_for_alignment_checks)) { do_versioning = false; break; @@ -3303,8 +3347,10 @@ vect_vfa_access_size (vec_info *vinfo, dr_vec_info *dr_info) access_size *= DR_GROUP_SIZE (stmt_vinfo) - DR_GROUP_GAP (stmt_vinfo); } tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo); + int misalignment; if (STMT_VINFO_VEC_STMTS (stmt_vinfo).exists () - && (vect_supportable_dr_alignment (vinfo, dr_info, vectype, false) + && ((misalignment = dr_misalignment (dr_info, vectype)), true) + && (vect_supportable_dr_alignment (vinfo, dr_info, vectype, misalignment) == dr_explicit_realign_optimized)) { /* We might access a full vector's worth. */ @@ -6620,7 +6666,6 @@ vect_can_force_dr_alignment_p (const_tree decl, poly_uint64 alignment) return (known_le (alignment, (unsigned HOST_WIDE_INT) MAX_STACK_ALIGNMENT)); } - /* Return whether the data reference DR_INFO is supported with respect to its alignment. If CHECK_ALIGNED_ACCESSES is TRUE, check if the access is supported even @@ -6629,7 +6674,7 @@ vect_can_force_dr_alignment_p (const_tree decl, poly_uint64 alignment) enum dr_alignment_support vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info, - tree vectype, bool check_aligned_accesses) + tree vectype, int misalignment) { data_reference *dr = dr_info->dr; stmt_vec_info stmt_info = dr_info->stmt; @@ -6638,7 +6683,7 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info, class loop *vect_loop = NULL; bool nested_in_vect_loop = false; - if (aligned_access_p (dr_info, vectype) && !check_aligned_accesses) + if (misalignment == 0) return dr_aligned; /* For now assume all conditional loads/stores support unaligned @@ -6720,9 +6765,6 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info, if (DR_IS_READ (dr)) { - bool is_packed = false; - tree type = (TREE_TYPE (DR_REF (dr))); - if (optab_handler (vec_realign_load_optab, mode) != CODE_FOR_nothing && (!targetm.vectorize.builtin_mask_for_load || targetm.vectorize.builtin_mask_for_load ())) @@ -6744,26 +6786,15 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info, else return dr_explicit_realign_optimized; } - if (!known_alignment_for_access_p (dr_info, vectype)) - is_packed = not_size_aligned (DR_REF (dr)); - - if (targetm.vectorize.support_vector_misalignment - (mode, type, dr_misalignment (dr_info, vectype), is_packed)) - /* Can't software pipeline the loads, but can at least do them. */ - return dr_unaligned_supported; } - else - { - bool is_packed = false; - tree type = (TREE_TYPE (DR_REF (dr))); - if (!known_alignment_for_access_p (dr_info, vectype)) - is_packed = not_size_aligned (DR_REF (dr)); - - if (targetm.vectorize.support_vector_misalignment - (mode, type, dr_misalignment (dr_info, vectype), is_packed)) - return dr_unaligned_supported; - } + bool is_packed = false; + tree type = TREE_TYPE (DR_REF (dr)); + if (misalignment == DR_MISALIGNMENT_UNKNOWN) + is_packed = not_size_aligned (DR_REF (dr)); + if (targetm.vectorize.support_vector_misalignment (mode, type, misalignment, + is_packed)) + return dr_unaligned_supported; /* Unsupported. */ return dr_unaligned_unsupported; diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 709bcb6..eff4640 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -975,7 +975,6 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap, (gimple_call_internal_fn (call_stmt)))) || gimple_call_tail_p (call_stmt) || gimple_call_noreturn_p (call_stmt) - || !gimple_call_nothrow_p (call_stmt) || gimple_call_chain (call_stmt)) { if (dump_enabled_p ()) diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index f5e1941..8f52745 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -909,6 +909,8 @@ cfun_returns (tree decl) static void vect_model_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, vect_memory_access_type memory_access_type, + dr_alignment_support alignment_support_scheme, + int misalignment, vec_load_store_type vls_type, slp_tree slp_node, stmt_vector_for_cost *cost_vec) { @@ -969,7 +971,8 @@ vect_model_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, scalar_store, stmt_info, 0, vect_body); } else - vect_get_store_cost (vinfo, stmt_info, ncopies, &inside_cost, cost_vec); + vect_get_store_cost (vinfo, stmt_info, ncopies, alignment_support_scheme, + misalignment, &inside_cost, cost_vec); if (memory_access_type == VMAT_ELEMENTWISE || memory_access_type == VMAT_STRIDED_SLP) @@ -1021,15 +1024,12 @@ vect_model_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, /* Calculate cost of DR's memory access. */ void -vect_get_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, +vect_get_store_cost (vec_info *, stmt_vec_info stmt_info, int ncopies, + dr_alignment_support alignment_support_scheme, + int misalignment, unsigned int *inside_cost, stmt_vector_for_cost *body_cost_vec) { - dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info); - tree vectype = STMT_VINFO_VECTYPE (stmt_info); - int alignment_support_scheme - = vect_supportable_dr_alignment (vinfo, dr_info, vectype, false); - switch (alignment_support_scheme) { case dr_aligned: @@ -1049,8 +1049,7 @@ vect_get_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, /* Here, we assign an additional cost for the unaligned store. */ *inside_cost += record_stmt_cost (body_cost_vec, ncopies, unaligned_store, stmt_info, - dr_misalignment (dr_info, vectype), - vect_body); + misalignment, vect_body); if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "vect_model_store_cost: unaligned supported by " @@ -1085,6 +1084,8 @@ static void vect_model_load_cost (vec_info *vinfo, stmt_vec_info stmt_info, unsigned ncopies, poly_uint64 vf, vect_memory_access_type memory_access_type, + dr_alignment_support alignment_support_scheme, + int misalignment, gather_scatter_info *gs_info, slp_tree slp_node, stmt_vector_for_cost *cost_vec) @@ -1144,7 +1145,8 @@ vect_model_load_cost (vec_info *vinfo, dump_printf_loc (MSG_NOTE, vect_location, "vect_model_load_cost: %d unused vectors.\n", gaps); - vect_get_load_cost (vinfo, stmt_info, ncopies * gaps, false, + vect_get_load_cost (vinfo, stmt_info, ncopies * gaps, + alignment_support_scheme, misalignment, false, &inside_cost, &prologue_cost, cost_vec, cost_vec, true); } @@ -1189,8 +1191,16 @@ vect_model_load_cost (vec_info *vinfo, ncopies * assumed_nunits, scalar_load, stmt_info, 0, vect_body); } + else if (memory_access_type == VMAT_INVARIANT) + { + /* Invariant loads will ideally be hoisted and splat to a vector. */ + prologue_cost += record_stmt_cost (cost_vec, 1, + scalar_to_vec, stmt_info, 0, + vect_prologue); + } else - vect_get_load_cost (vinfo, stmt_info, ncopies, first_stmt_p, + vect_get_load_cost (vinfo, stmt_info, ncopies, + alignment_support_scheme, misalignment, first_stmt_p, &inside_cost, &prologue_cost, cost_vec, cost_vec, true); if (memory_access_type == VMAT_ELEMENTWISE @@ -1209,18 +1219,15 @@ vect_model_load_cost (vec_info *vinfo, /* Calculate cost of DR's memory access. */ void -vect_get_load_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, +vect_get_load_cost (vec_info *, stmt_vec_info stmt_info, int ncopies, + dr_alignment_support alignment_support_scheme, + int misalignment, bool add_realign_cost, unsigned int *inside_cost, unsigned int *prologue_cost, stmt_vector_for_cost *prologue_cost_vec, stmt_vector_for_cost *body_cost_vec, bool record_prologue_costs) { - dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info); - tree vectype = STMT_VINFO_VECTYPE (stmt_info); - int alignment_support_scheme - = vect_supportable_dr_alignment (vinfo, dr_info, vectype, false); - switch (alignment_support_scheme) { case dr_aligned: @@ -1239,8 +1246,7 @@ vect_get_load_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, /* Here, we assign an additional cost for the unaligned load. */ *inside_cost += record_stmt_cost (body_cost_vec, ncopies, unaligned_load, stmt_info, - dr_misalignment (dr_info, vectype), - vect_body); + misalignment, vect_body); if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, @@ -1967,13 +1973,14 @@ perm_mask_for_reverse (tree vectype) /* A subroutine of get_load_store_type, with a subset of the same arguments. Handle the case where STMT_INFO is a load or store that - accesses consecutive elements with a negative step. */ + accesses consecutive elements with a negative step. Sets *POFFSET + to the offset to be applied to the DR for the first access. */ static vect_memory_access_type get_negative_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, tree vectype, vec_load_store_type vls_type, - unsigned int ncopies) + unsigned int ncopies, poly_int64 *poffset) { dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info); dr_alignment_support alignment_support_scheme; @@ -1986,8 +1993,9 @@ get_negative_load_store_type (vec_info *vinfo, return VMAT_ELEMENTWISE; } - alignment_support_scheme = vect_supportable_dr_alignment (vinfo, dr_info, - vectype, false); + int misalignment = dr_misalignment (dr_info, vectype); + alignment_support_scheme + = vect_supportable_dr_alignment (vinfo, dr_info, vectype, misalignment); if (alignment_support_scheme != dr_aligned && alignment_support_scheme != dr_unaligned_supported) { @@ -2003,6 +2011,7 @@ get_negative_load_store_type (vec_info *vinfo, dump_printf_loc (MSG_NOTE, vect_location, "negative step with invariant source;" " no permute needed.\n"); + *poffset = -TYPE_VECTOR_SUBPARTS (vectype) + 1; return VMAT_CONTIGUOUS_DOWN; } @@ -2014,6 +2023,7 @@ get_negative_load_store_type (vec_info *vinfo, return VMAT_ELEMENTWISE; } + *poffset = -TYPE_VECTOR_SUBPARTS (vectype) + 1; return VMAT_CONTIGUOUS_REVERSE; } @@ -2108,7 +2118,9 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, tree vectype, slp_tree slp_node, bool masked_p, vec_load_store_type vls_type, vect_memory_access_type *memory_access_type, + poly_int64 *poffset, dr_alignment_support *alignment_support_scheme, + int *misalignment, gather_scatter_info *gs_info) { loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo); @@ -2180,15 +2192,15 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, can do half-vector operations avoid the epilogue peeling by simply loading half of the vector only. Usually the construction with an upper zero half will be elided. */ - dr_alignment_support alignment_support_scheme; + dr_alignment_support alss; + int misalign = dr_misalignment (first_dr_info, vectype); tree half_vtype; if (overrun_p && !masked_p - && (((alignment_support_scheme - = vect_supportable_dr_alignment (vinfo, first_dr_info, - vectype, false))) + && (((alss = vect_supportable_dr_alignment (vinfo, first_dr_info, + vectype, misalign))) == dr_aligned - || alignment_support_scheme == dr_unaligned_supported) + || alss == dr_unaligned_supported) && known_eq (nunits, (group_size - gap) * 2) && known_eq (nunits, group_size) && (vector_vector_composition_type (vectype, 2, &half_vtype) @@ -2209,7 +2221,7 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, /* ??? The VMAT_CONTIGUOUS_REVERSE code generation is only correct for single element "interleaving" SLP. */ *memory_access_type = get_negative_load_store_type - (vinfo, stmt_info, vectype, vls_type, 1); + (vinfo, stmt_info, vectype, vls_type, 1, poffset); else { /* Try to use consecutive accesses of DR_GROUP_SIZE elements, @@ -2294,10 +2306,17 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, if (*memory_access_type == VMAT_GATHER_SCATTER || *memory_access_type == VMAT_ELEMENTWISE) - *alignment_support_scheme = dr_unaligned_supported; + { + *alignment_support_scheme = dr_unaligned_supported; + *misalignment = DR_MISALIGNMENT_UNKNOWN; + } else - *alignment_support_scheme - = vect_supportable_dr_alignment (vinfo, first_dr_info, vectype, false); + { + *misalignment = dr_misalignment (first_dr_info, vectype); + *alignment_support_scheme + = vect_supportable_dr_alignment (vinfo, first_dr_info, vectype, + *misalignment); + } if (vls_type != VLS_LOAD && first_stmt_info == stmt_info) { @@ -2337,7 +2356,9 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, storing it in *MEMORY_ACCESS_TYPE if so. If we decide to use gathers or scatters, fill in GS_INFO accordingly. In addition *ALIGNMENT_SUPPORT_SCHEME is filled out and false is returned if - the target does not support the alignment scheme. + the target does not support the alignment scheme. *MISALIGNMENT + is set according to the alignment of the access (including + DR_MISALIGNMENT_UNKNOWN when it is unknown). SLP says whether we're performing SLP rather than loop vectorization. MASKED_P is true if the statement is conditional on a vectorized mask. @@ -2350,11 +2371,15 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, bool masked_p, vec_load_store_type vls_type, unsigned int ncopies, vect_memory_access_type *memory_access_type, + poly_int64 *poffset, dr_alignment_support *alignment_support_scheme, + int *misalignment, gather_scatter_info *gs_info) { loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo); poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype); + *misalignment = DR_MISALIGNMENT_UNKNOWN; + *poffset = 0; if (STMT_VINFO_GATHER_SCATTER_P (stmt_info)) { *memory_access_type = VMAT_GATHER_SCATTER; @@ -2401,8 +2426,9 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, { if (!get_group_load_store_type (vinfo, stmt_info, vectype, slp_node, masked_p, - vls_type, memory_access_type, - alignment_support_scheme, gs_info)) + vls_type, memory_access_type, poffset, + alignment_support_scheme, + misalignment, gs_info)) return false; } else if (STMT_VINFO_STRIDED_P (stmt_info)) @@ -2432,13 +2458,15 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, { if (cmp < 0) *memory_access_type = get_negative_load_store_type - (vinfo, stmt_info, vectype, vls_type, ncopies); + (vinfo, stmt_info, vectype, vls_type, ncopies, poffset); else *memory_access_type = VMAT_CONTIGUOUS; + *misalignment = dr_misalignment (STMT_VINFO_DR_INFO (stmt_info), + vectype); *alignment_support_scheme = vect_supportable_dr_alignment (vinfo, STMT_VINFO_DR_INFO (stmt_info), - vectype, false); + vectype, *misalignment); } } @@ -7228,7 +7256,6 @@ vectorizable_store (vec_info *vinfo, unsigned int group_size, i; vec<tree> oprnds = vNULL; vec<tree> result_chain = vNULL; - tree offset = NULL_TREE; vec<tree> vec_oprnds = vNULL; bool slp = (slp_node != NULL); unsigned int vec_num; @@ -7337,9 +7364,11 @@ vectorizable_store (vec_info *vinfo, vect_memory_access_type memory_access_type; enum dr_alignment_support alignment_support_scheme; + int misalignment; + poly_int64 poffset; if (!get_load_store_type (vinfo, stmt_info, vectype, slp_node, mask, vls_type, - ncopies, &memory_access_type, - &alignment_support_scheme, &gs_info)) + ncopies, &memory_access_type, &poffset, + &alignment_support_scheme, &misalignment, &gs_info)) return false; if (mask) @@ -7422,7 +7451,8 @@ vectorizable_store (vec_info *vinfo, STMT_VINFO_TYPE (stmt_info) = store_vec_info_type; vect_model_store_cost (vinfo, stmt_info, ncopies, - memory_access_type, vls_type, slp_node, cost_vec); + memory_access_type, alignment_support_scheme, + misalignment, vls_type, slp_node, cost_vec); return true; } gcc_assert (memory_access_type == STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info)); @@ -7904,14 +7934,6 @@ vectorizable_store (vec_info *vinfo, auto_vec<tree> dr_chain (group_size); oprnds.create (group_size); - /* Gather-scatter accesses perform only component accesses, alignment - is irrelevant for them. */ - if (memory_access_type == VMAT_GATHER_SCATTER) - alignment_support_scheme = dr_unaligned_supported; - else - alignment_support_scheme - = vect_supportable_dr_alignment (vinfo, first_dr_info, vectype, false); - gcc_assert (alignment_support_scheme); vec_loop_masks *loop_masks = (loop_vinfo && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo) @@ -7934,9 +7956,9 @@ vectorizable_store (vec_info *vinfo, || alignment_support_scheme == dr_aligned || alignment_support_scheme == dr_unaligned_supported); - if (memory_access_type == VMAT_CONTIGUOUS_DOWN - || memory_access_type == VMAT_CONTIGUOUS_REVERSE) - offset = size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1); + tree offset = NULL_TREE; + if (!known_eq (poffset, 0)) + offset = size_int (poffset); tree bump; tree vec_offset = NULL_TREE; @@ -8221,16 +8243,18 @@ vectorizable_store (vec_info *vinfo, vec_oprnd = result_chain[i]; align = known_alignment (DR_TARGET_ALIGNMENT (first_dr_info)); - if (aligned_access_p (first_dr_info, vectype)) - misalign = 0; - else if (dr_misalignment (first_dr_info, vectype) - == DR_MISALIGNMENT_UNKNOWN) + if (alignment_support_scheme == dr_aligned) + { + gcc_assert (aligned_access_p (first_dr_info, vectype)); + misalign = 0; + } + else if (misalignment == DR_MISALIGNMENT_UNKNOWN) { align = dr_alignment (vect_dr_behavior (vinfo, first_dr_info)); misalign = 0; } else - misalign = dr_misalignment (first_dr_info, vectype); + misalign = misalignment; if (dataref_offset == NULL_TREE && TREE_CODE (dataref_ptr) == SSA_NAME) set_ptr_info_alignment (get_ptr_info (dataref_ptr), align, @@ -8307,8 +8331,8 @@ vectorizable_store (vec_info *vinfo, dataref_offset ? dataref_offset : build_int_cst (ref_type, 0)); - if (aligned_access_p (first_dr_info, vectype)) - ; + if (alignment_support_scheme == dr_aligned) + gcc_assert (aligned_access_p (first_dr_info, vectype)); else TREE_TYPE (data_ref) = build_aligned_type (TREE_TYPE (data_ref), @@ -8489,7 +8513,6 @@ vectorizable_load (vec_info *vinfo, unsigned int group_size; poly_uint64 group_gap_adj; tree msq = NULL_TREE, lsq; - tree offset = NULL_TREE; tree byte_offset = NULL_TREE; tree realignment_token = NULL_TREE; gphi *phi = NULL; @@ -8698,9 +8721,11 @@ vectorizable_load (vec_info *vinfo, vect_memory_access_type memory_access_type; enum dr_alignment_support alignment_support_scheme; + int misalignment; + poly_int64 poffset; if (!get_load_store_type (vinfo, stmt_info, vectype, slp_node, mask, VLS_LOAD, - ncopies, &memory_access_type, - &alignment_support_scheme, &gs_info)) + ncopies, &memory_access_type, &poffset, + &alignment_support_scheme, &misalignment, &gs_info)) return false; if (mask) @@ -8763,6 +8788,7 @@ vectorizable_load (vec_info *vinfo, STMT_VINFO_TYPE (stmt_info) = load_vec_info_type; vect_model_load_cost (vinfo, stmt_info, ncopies, vf, memory_access_type, + alignment_support_scheme, misalignment, &gs_info, slp_node, cost_vec); return true; } @@ -9283,6 +9309,9 @@ vectorizable_load (vec_info *vinfo, else at_loop = loop; + tree offset = NULL_TREE; + if (!known_eq (poffset, 0)) + offset = size_int (poffset); if (memory_access_type == VMAT_CONTIGUOUS_REVERSE) offset = size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1); @@ -9558,14 +9587,14 @@ vectorizable_load (vec_info *vinfo, gcc_assert (aligned_access_p (first_dr_info, vectype)); misalign = 0; } - else if (dr_misalignment (first_dr_info, vectype) == -1) + else if (misalignment == DR_MISALIGNMENT_UNKNOWN) { align = dr_alignment (vect_dr_behavior (vinfo, first_dr_info)); misalign = 0; } else - misalign = dr_misalignment (first_dr_info, vectype); + misalign = misalignment; if (dataref_offset == NULL_TREE && TREE_CODE (dataref_ptr) == SSA_NAME) set_ptr_info_alignment (get_ptr_info (dataref_ptr), diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 4aa84ac..866d813 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -1957,11 +1957,13 @@ extern bool vect_nop_conversion_p (stmt_vec_info); extern opt_result vect_analyze_stmt (vec_info *, stmt_vec_info, bool *, slp_tree, slp_instance, stmt_vector_for_cost *); -extern void vect_get_load_cost (vec_info *, stmt_vec_info, int, bool, +extern void vect_get_load_cost (vec_info *, stmt_vec_info, int, + dr_alignment_support, int, bool, unsigned int *, unsigned int *, stmt_vector_for_cost *, stmt_vector_for_cost *, bool); extern void vect_get_store_cost (vec_info *, stmt_vec_info, int, + dr_alignment_support, int, unsigned int *, stmt_vector_for_cost *); extern bool vect_supportable_shift (vec_info *, enum tree_code, tree); extern tree vect_gen_perm_mask_any (tree, const vec_perm_indices &); @@ -1978,7 +1980,7 @@ extern opt_tree vect_get_mask_type_for_stmt (stmt_vec_info, unsigned int = 0); /* In tree-vect-data-refs.c. */ extern bool vect_can_force_dr_alignment_p (const_tree, poly_uint64); extern enum dr_alignment_support vect_supportable_dr_alignment - (vec_info *, dr_vec_info *, tree, bool); + (vec_info *, dr_vec_info *, tree, int); extern tree vect_get_smallest_scalar_type (stmt_vec_info, tree); extern opt_result vect_analyze_data_ref_dependences (loop_vec_info, unsigned int *); extern bool vect_slp_analyze_instance_dependence (vec_info *, slp_instance); diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 3fca7fd..67d866d 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,7 @@ +2021-10-18 Martin Liska <mliska@suse.cz> + + * charset.c (convert_oct): Remove unused but set variable. + 2021-10-06 Jakub Jelinek <jakub@redhat.com> * init.c (lang_defaults): Implement P2334R1, enable elifdef for diff --git a/libffi/.gitattributes b/libffi/.gitattributes new file mode 100644 index 0000000..f7d3833 --- /dev/null +++ b/libffi/.gitattributes @@ -0,0 +1,4 @@ +* text=auto + +*.sln text eol=crlf +*.vcxproj* text eol=crlf diff --git a/libffi/ChangeLog b/libffi/ChangeLog index 1048153..e8fe0e0 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,88 @@ +2021-10-20 H.J. Lu <hjl.tools@gmail.com> + + * LOCAL_PATCHES: New file. + +2021-10-20 H.J. Lu <hjl.tools@gmail.com> + + * testsuite/lib/libffi.exp (load_gcc_lib): Load library from GCC + testsuite. + Load target-supports.exp and target-supports-dg.exp. + (libffi-init): Use libraries in GCC build tree. + (libffi_target_compile): Link with -shared-libgcc -lstdc++ for + C++ sources. + +2021-10-20 H.J. Lu <hjl.tools@gmail.com> + + * Makefile.am (AUTOMAKE_OPTIONS): Add info-in-builddir. + (ACLOCAL_AMFLAGS): Set to -I .. -I ../config. + (SUBDIRS): Don't add doc. + (TEXINFO_TEX): New. + (MAKEINFOFLAGS): Likewise. + (info_TEXINFOS): Likewise. + (STAMP_GENINSRC): Likewise. + (STAMP_BUILD_INFO): Likewise. + (all-local): Likewise. + (stamp-geninsrc): Likewise. + (doc/libffi.info): Likewise. + (stamp-build-info:): Likewise. + (CLEANFILES): Likewise. + (MAINTAINERCLEANFILES): Likewise. + (AM_MAKEFLAGS): Likewise. + (all-recursive): Likewise. + (install-recursive): Likewise. + (mostlyclean-recursive): Likewise. + (clean-recursive): Likewise. + (distclean-recursive): Likewise. + (maintainer-clean-recursive): Likewise. + (LTLDFLAGS): Replace libtool-ldflags with ../libtool-ldflags. + (AM_CFLAGS): Add -g -fexceptions. + (libffi.map-sun): Replace make_sunver.pl with + ../contrib/make_sunver.pl. + (dist-hook): Removed. + Include $(top_srcdir)/../multilib.am. + * configure.ac: Add AM_ENABLE_MULTILIB. + Remove the frv*-elf check. + (AX_ENABLE_BUILDDIR): Removed. + (AM_INIT_AUTOMAKE): Add [no-dist]. + Add --enable-generated-files-in-srcdir. + (C_CONFIG_MACRO_DIR): Removed. + (AX_COMPILER_VENDOR): Likewise. + (AX_CC_MAXOPT): Likewise. + (AX_CFLAGS_WARN_ALL): Likewise. + Remove the GCC check. + (SYMBOL_UNDERSCORE): Removed. + (AX_CHECK_COMPILE_FLAG): Likewise. + Remove --disable-docs. + (ACX_CHECK_PROG_VER): Check makeinfo. + (BUILD_DOCS): Updated. + (exec-static-tramp): Don't enable use of static exec trampolines + by default. + Remove --disable-multi-os-directory. + (GCC_WITH_TOOLEXECLIBDIR): New. + Support cross host. + Support --enable-multilib. + * include/Makefile.am (nodist_include_HEADERS): Removed. + (gcc_version): New. + (toollibffidir): Likewise. + (toollibffi_HEADERS): Likewise. + * Makefile.in: Regenerate. + (GCC_BASE_VER): New. + (AC_CONFIG_FILES): Remove doc/Makefile. + (AC_CONFIG_LINKS): New. + * aclocal.m4: Likewise. + * configure: Likewise. + * fficonfig.h.in: Likewise. + * mdate-sh: Likewise. + * include/Makefile.in: Likewise. + * man/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + +2021-10-20 H.J. Lu <hjl.tools@gmail.com> + + * HOWTO_MERGE: New file. + * autogen.sh: Likewise. + * merge.sh: Likewise. + 2021-08-30 YunQiang Su <yunqiang.su@cipunited.com> PR libffi/83636 diff --git a/libffi/ChangeLog.libffi b/libffi/ChangeLog.libffi index f3ee8b0..8de1ca7 100644 --- a/libffi/ChangeLog.libffi +++ b/libffi/ChangeLog.libffi @@ -1,3 +1,6015 @@ +Libffi change logs used to be maintained in separate ChangeLog files. +These days we generate them directly from the git commit messages. +The old ChangeLog files are saved here in order to maintain the historical +record. + +============================================================================= +From the old ChangeLog.libffi-3.1 file... + +2014-03-16 Josh Triplett <josh@joshtriplett.org> + + * ChangeLog: Archive to ChangeLog.libffi-3.1 and delete. Future + changelogs will come from git, with autogenerated snapshots shipped in + distributed tarballs. + +2014-03-16 Josh Triplett <josh@joshtriplett.org> + + Add support for stdcall, thiscall, and fastcall on non-Windows + x86-32. + + Linux supports the stdcall calling convention, either via + functions explicitly declared with the stdcall attribute, or via + code compiled with -mrtd which effectively makes stdcall the + default. + + This introduces FFI_STDCALL, FFI_THISCALL, and FFI_FASTCALL on + non-Windows x86-32 platforms, as non-default calling conventions. + + * Makefile.am: Compile in src/x86/win32.S on non-Windows x86-32. + * src/x86/ffitarget.h: Add FFI_STDCALL, FFI_THISCALL, and + FFI_FASTCALL on non-Windows x86-32. Increase trampoline size to + accomodate these calling conventions, and unify some ifdeffery. + * src/x86/ffi.c: Add support for FFI_STDCALL, FFI_THISCALL, and + FFI_FASTCALL on non-Windows x86-32 platforms; update ifdeffery. + * src/x86/win32.S: Support compiling on non-Windows x86-32 + platforms. On those platforms, avoid redefining the SYSV symbols + already provided by src/x86/sysv.S. + * testsuite/libffi.call/closure_stdcall.c: Run on non-Windows. + #define __stdcall if needed. + * testsuite/libffi.call/closure_thiscall.c: Run on non-Windows. + #define __fastcall if needed. + * testsuite/libffi.call/fastthis1_win32.c: Run on non-Windows. + * testsuite/libffi.call/fastthis2_win32.c: Ditto. + * testsuite/libffi.call/fastthis3_win32.c: Ditto. + * testsuite/libffi.call/many2_win32.c: Ditto. + * testsuite/libffi.call/many_win32.c: Ditto. + * testsuite/libffi.call/strlen2_win32.c: Ditto. + * testsuite/libffi.call/strlen_win32.c: Ditto. + * testsuite/libffi.call/struct1_win32.c: Ditto. + * testsuite/libffi.call/struct2_win32.c: Ditto. + +2014-03-16 Josh Triplett <josh@joshtriplett.org> + + * prep_cif.c: Remove unnecessary ifdef for X86_WIN32. + ffi_prep_cif_core had a special case for X86_WIN32, checking for + FFI_THISCALL in addition to the FFI_FIRST_ABI-to-FFI_LAST_ABI + range before returning FFI_BAD_ABI. However, on X86_WIN32, + FFI_THISCALL already falls in that range, making the special case + unnecessary. Remove it. + +2014-03-16 Josh Triplett <josh@joshtriplett.org> + + * testsuite/libffi.call/closure_stdcall.c, + testsuite/libffi.call/closure_thiscall.c: Remove fragile stack + pointer checks. These files included inline assembly to save the + stack pointer before and after the call, and compare the values. + However, compilers can and do leave the stack in different states + for these two pieces of inline assembly, such as by saving a + temporary value on the stack across the call; observed with gcc + -Os, and verified as spurious through careful inspection of + disassembly. + +2014-03-16 Josh Triplett <josh@joshtriplett.org> + + * testsuite/libffi.call/many.c: Avoid spurious failure due to + excess floating-point precision. + * testsuite/libffi.call/many_win32.c: Ditto. + +2014-03-16 Josh Triplett <josh@joshtriplett.org> + + * libtool-ldflags: Re-add. + +2014-03-16 Josh Triplett <josh@joshtriplett.org> + + * Makefile.in, aclocal.m4, compile, config.guess, config.sub, + configure, depcomp, include/Makefile.in, install-sh, + libtool-ldflags, ltmain.sh, m4/libtool.m4, m4/ltoptions.m4, + m4/ltsugar.m4, m4/ltversion.m4, m4/lt~obsolete.m4, + man/Makefile.in, mdate-sh, missing, testsuite/Makefile.in: Delete + autogenerated files from version control. + * .gitignore: Add autogenerated files. + * autogen.sh: New script to generate the autogenerated files. + * README: Document requirement to run autogen.sh when building + directly from version control. + * .travis.yml: Run autogen.sh + +2014-03-14 Anthony Green <green@moxielogic.com> + + * configure, Makefile.in: Rebuilt. + +2014-03-10 Mike Hommey <mh+mozilla@glandium.org> + + * configure.ac: Allow building for mipsel with Android NDK r8. + * Makefile.am (AM_MAKEFLAGS): Replace double quotes with single + quotes. + +2014-03-10 Landry Breuil <landry@openbsd.org> + + * configure.ac: Ensure the linker supports @unwind sections in libffi. + +2014-03-01 Anthony Green <green@moxielogic.com> + + * Makefile.am (EXTRA_DIST): Replace old scripts with + generate-darwin-source-and-headers.py. + * Makefile.in: Rebuilt. + +2014-02-28 Anthony Green <green@moxielogic.com> + + * Makefile.am (AM_CFLAGS): Reintroduce missing -DFFI_DEBUG for + --enable-debug builds. + * Makefile.in: Rebuilt. + +2014-02-28 Makoto Kato <m_kato@ga2.so-net.ne.jp> + + * src/closures.c: Fix build failure when using clang for Android. + +2014-02-28 Marcin Wojdyr <wojdyr@gmail.com> + + * libffi.pc.in (toolexeclibdir): use -L${toolexeclibdir} instead + of -L${libdir}. + +2014-02-28 Paulo Pizarro <paulo.pizarro@gmail.com> + + * src/bfin/sysv.S: Calling functions in shared libraries requires + considering the GOT. + +2014-02-28 Josh Triplett <josh@joshtriplett.org> + + * src/x86/ffi64.c (classify_argument): Handle case where + FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE. + +2014-02-28 Anthony Green <green@moxielogic.com> + + * ltmain.sh: Generate with libtool-2.4.2.418. + * m4/libtool.m4, m4/ltoptions.m4, m4/ltversion.m4: Ditto. + * configure: Rebuilt. + +2014-02-28 Dominik Vogt <vogt@linux.vnet.ibm.com> + + * configure.ac (AC_ARG_ENABLE struct): Fix typo in help + message. + (AC_ARG_ENABLE raw_api): Ditto. + * configure, fficonfig.h.in: Rebuilt. + +2014-02-28 Will Newton <will.newton@linaro.org> + + * src/arm/sysv.S: Initialize IP register with FP. + +2014-02-28 Yufeng Zhang <yufeng.zhang@arm.com> + + * src/aarch64/sysv.S (ffi_closure_SYSV): Use x29 as the + main CFA reg; update cfi_rel_offset. + +2014-02-15 Marcus Comstedt <marcus@mc.pp.se> + + * src/powerpc/ffi_linux64.c, src/powerpc/linux64_closure.S: Remove + assumption on contents of r11 in closure. + +2014-02-09 Heiher <r@hev.cc> + + * src/mips/n32.S: Fix call floating point va function. + +2014-01-21 Zachary Waldowski <zach@waldowski.me> + + * src/aarch64/ffi.c: Fix missing semicolons on assertions under + debug mode. + +2013-12-30 Zachary Waldowski <zach@waldowski.me> + + * .gitignore: Exclude darwin_* generated source and build_* trees. + * src/aarch64/ffi.c, src/arm/ffi.c, src/x86/ffi.c: Inhibit Clang + previous prototype warnings. + * src/arm/ffi.c: Prevent NULL dereference, fix short type warning + * src/dlmalloc.c: Fix warnings from set_segment_flags return type, + and the native use of size_t for malloc on platforms + * src/arm/sysv.S: Use unified syntax. Clang clean-ups for + ARM_FUNC_START. + * generate-osx-source-and-headers.py: Remove. + * build-ios.sh: Remove. + * libffi.xcodeproj/project.pbxproj: Rebuild targets. Include + x86_64+aarch64 pieces in library. Export headers properly. + * src/x86/ffi64.c: More Clang warning clean-ups. + * src/closures.c (open_temp_exec_file_dir): Use size_t. + * src/prep_cif.c (ffi_prep_cif_core): Cast ALIGN result. + * src/aarch64/sysv.S: Use CNAME for global symbols. Only use + .size for ELF targets. + * src/aarch64/ffi.c: Clean up for double == long double. Clean up + from Clang warnings. Use Clang cache invalidation builtin. Use + size_t in place of unsigned in many places. Accommodate for + differences in Apple AArch64 ABI. + +2013-12-02 Daniel RodrÃguez Troitiño <drodrigueztroitino@yahoo.es> + + * generate-darwin-source-and-headers.py: Clean up, modernize, + merged version of previous scripts. + +2013-11-21 Anthony Green <green@moxielogic.com> + + * configure, Makefile.in, include/Makefile.in, include/ffi.h.in, + man/Makefile.in, testsuite/Makefile.in, fficonfig.h.in: Rebuilt. + +2013-11-21 Alan Modra <amodra@gmail.com> + + * Makefile.am (EXTRA_DIST): Add new src/powerpc files. + (nodist_libffi_la_SOURCES <POWERPC, POWERPC_FREEBSD>): Likewise. + * configure.ac (HAVE_LONG_DOUBLE_VARIANT): Define for powerpc. + * include/ffi.h.in (ffi_prep_types): Declare. + * src/prep_cif.c (ffi_prep_cif_core): Call ffi_prep_types. + * src/types.c (FFI_NONCONST_TYPEDEF): Define and use for + HAVE_LONG_DOUBLE_VARIANT. + * src/powerpc/ffi_powerpc.h: New file. + * src/powerpc/ffi.c: Split into.. + * src/powerpc/ffi_sysv.c: ..new file, and.. + * src/powerpc/ffi_linux64.c: ..new file, rewriting parts. + * src/powerpc/ffitarget.h (enum ffi_abi): Rewrite powerpc ABI + selection as bits controlling features. + * src/powerpc/linux64.S: For consistency, use POWERPC64 rather + than __powerpc64__. + * src/powerpc/linux64_closure.S: Likewise. + * src/powerpc/ppc_closure.S: Likewise. Move .note.FNU-stack + inside guard. + * src/powerpc/sysv.S: Likewise. + * configure: Regenerate. + * fficonfig.h.in: Regenerate. + * Makefile.in: Regenerate. + +2013-11-20 Alan Modra <amodra@gmail.com> + + * src/powerpc/ffi.c (ffi_prep_cif_machdep_core): Use + NUM_FPR_ARG_REGISTERS64 and NUM_GPR_ARG_REGISTERS64 not their + 32-bit versions for 64-bit code. + * src/powerpc/linux64_closure.S: Don't use the return value area + as a parameter save area on ELFv2. + +2013-11-18 Iain Sandoe <iain@codesourcery.com> + + * src/powerpc/darwin.S (EH): Correct use of pcrel FDE encoding. + * src/powerpc/darwin_closure.S (EH): Likewise. Modernise picbase + labels. + +2013-11-18 Anthony Green <green@moxielogic.com> + + * src/arm/ffi.c (ffi_call): Hoist declaration of temp to top of + function. + * src/arm/ffi.c (ffi_closure_inner): Moderize function declaration + to appease compiler. + Thanks for Gregory P. Smith <greg@krypto.org>. + +2013-11-18 Anthony Green <green@moxielogic.com> + + * README (tested): Mention PowerPC ELFv2. + +2013-11-16 Alan Modra <amodra@gmail.com> + + * src/powerpc/ppc_closure.S: Move errant #endif to where it belongs. + Don't bl .Luint128. + +2013-11-16 Alan Modra <amodra@gmail.com> + + * src/powerpc/ffi.c (ffi_prep_cif_machdep_core): Use #if _CALL_ELF + test to select parameter save sizing for ELFv2 vs. ELFv1. + * src/powerpc/ffitarget.h (FFI_V2_TYPE_FLOAT_HOMOG, + FFI_V2_TYPE_DOUBLE_HOMOG, FFI_V2_TYPE_SMALL_STRUCT): Define. + (FFI_TRAMPOLINE_SIZE): Define variant for ELFv2. + * src/powerpc/ffi.c (FLAG_ARG_NEEDS_PSAVE): Define. + (discover_homogeneous_aggregate): New function. + (ffi_prep_args64): Adjust start of param save area for ELFv2. + Handle homogenous floating point struct parms. + (ffi_prep_cif_machdep_core): Adjust space calculation for ELFv2. + Handle ELFv2 return values. Set FLAG_ARG_NEEDS_PSAVE. Handle + homogenous floating point structs. + (ffi_call): Increase size of smst_buffer for ELFv2. Handle ELFv2. + (flush_icache): Compile for ELFv2. + (ffi_prep_closure_loc): Set up ELFv2 trampoline. + (ffi_closure_helper_LINUX64): Don't return all structs directly + to caller. Handle homogenous floating point structs. Handle + ELFv2 struct return values. + * src/powerpc/linux64.S (ffi_call_LINUX64): Set up r2 for + ELFv2. Adjust toc save location. Call function pointer using + r12. Handle FLAG_RETURNS_SMST. Don't predict branches. + * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Set up r2 + for ELFv2. Define ELFv2 versions of STACKFRAME, PARMSAVE, and + RETVAL. Handle possibly missing parameter save area. Handle + ELFv2 return values. + (.note.GNU-stack): Move inside outer #ifdef. + +2013-11-16 Alan Modra <amodra@gmail.com> + + * src/powerpc/ffi.c (ffi_prep_cif_machdep): Revert 2013-02-08 + change. Do not consume an int arg when returning a small struct + for FFI_SYSV ABI. + (ffi_call): Only use bounce buffer when FLAG_RETURNS_SMST. + Properly copy bounce buffer to destination. + * src/powerpc/sysv.S: Revert 2013-02-08 change. + * src/powerpc/ppc_closure.S: Remove stray '+'. + +2013-11-16 Alan Modra <amodra@gmail.com> + + * src/powerpc/ffi.c (ffi_prep_args64): Align struct parameters + according to __STRUCT_PARM_ALIGN__. + (ffi_prep_cif_machdep_core): Likewise. + (ffi_closure_helper_LINUX64): Likewise. + +2013-11-16 Alan Modra <amodra@gmail.com> + + * src/powerpc/linux64.S (ffi_call_LINUX64): Tweak restore of r28. + (.note.GNU-stack): Move inside outer #ifdef. + * src/powerpc/linux64_closure.S (STACKFRAME, PARMSAVE, + RETVAL): Define and use throughout. + (ffi_closure_LINUX64): Save fprs before buying stack. + (.note.GNU-stack): Move inside outer #ifdef. + +2013-11-16 Alan Modra <amodra@gmail.com> + + * src/powerpc/ffitarget.h (FFI_TARGET_SPECIFIC_VARIADIC): Define. + (FFI_EXTRA_CIF_FIELDS): Define. + * src/powerpc/ffi.c (ffi_prep_args64): Save fprs as per the + ABI, not to both fpr and param save area. + (ffi_prep_cif_machdep_core): Renamed from ffi_prep_cif_machdep. + Keep initial flags. Formatting. Remove dead FFI_LINUX_SOFT_FLOAT + code. + (ffi_prep_cif_machdep, ffi_prep_cif_machdep_var): New functions. + (ffi_closure_helper_LINUX64): Pass floating point as per ABI, + not to both fpr and parameter save areas. + + * libffi/testsuite/libffi.call/cls_double_va.c (main): Correct + function cast and don't call ffi_prep_cif. + * libffi/testsuite/libffi.call/cls_longdouble_va.c (main): Likewise. + +2013-11-15 Andrew Haley <aph@redhat.com> + + * doc/libffi.texi (Closure Example): Fix the sample code. + * doc/libffi.info, doc/stamp-vti, doc/version.texi: Rebuilt. + +2013-11-15 Andrew Haley <aph@redhat.com> + + * testsuite/libffi.call/va_struct1.c (main): Fix broken test. + * testsuite/libffi.call/cls_uint_va.c (cls_ret_T_fn): Likewise + * testsuite/libffi.call/cls_struct_va1.c (test_fn): Likewise. + * testsuite/libffi.call/va_1.c (main): Likewise. + +2013-11-14 David Schneider <david.schneider@bivab.de> + + * src/arm/ffi.c: Fix register allocation for mixed float and + doubles. + * testsuite/libffi.call/cls_many_mixed_float_double.c: Testcase + for many mixed float and double arguments. + +2013-11-13 Alan Modra <amodra@gmail.com> + + * doc/libffi.texi (Simple Example): Correct example code. + * doc/libffi.info, doc/stamp-vti, doc/version.texi: Rebuilt. + +2013-11-13 Anthony Green <green@moxielogic.com> + + * include/ffi_common.h: Respect HAVE_ALLOCA_H for GNU compiler + based build. (Thanks to tmr111116 on github) + +2013-11-09 Anthony Green <green@moxielogic.com> + + * m4/libtool.m4: Refresh. + * configure, Makefile.in: Rebuilt. + * README: Add more notes about next release. + +2013-11-09 Shigeharu TAKENO <shige@iee.niit.ac.jp> + + * m4/ax_gcc_archflag.m4 (ax_gcc_arch): Don't recognize + UltraSPARC-IIi as ultrasparc3. + +2013-11-06 Mark Kettenis <kettenis@gnu.org> + + * src/x86/freebsd.S (ffi_call_SYSV): Align the stack pointer to + 16-bytes. + +2013-11-06 Konstantin Belousov <kib@freebsd.org> + + * src/x86/freebsd.S (ffi_closure_raw_SYSV): Mark the assembler + source as not requiring executable stack. + +2013-11-02 Anthony Green <green@moxielogic.com> + + * doc/libffi.texi (The Basics): Clarify return value buffer size + requirements. Also, NULL result buffer pointers are no longer + supported. + * doc/libffi.info: Rebuilt. + +2013-11-02 Mischa Jonker <mjonker@synopsys.com> + + * Makefile.am (nodist_libffi_la_SOURCES): Fix build error. + * Makefile.in: Rebuilt. + +2013-11-02 David Schneider <david.schneider@bivab.de> + + * src/arm/ffi.c: more robust argument handling for closures on arm hardfloat + * testsuite/libffi.call/many_mixed.c: New file. + * testsuite/libffi.call/cls_many_mixed_args.c: More tests. + +2013-11-02 Vitaly Budovski + + * src/x86/ffi.c (ffi_prep_cif_machdep): Don't align stack for win32. + +2013-10-23 Mark H Weaver <mhw@netris.org> + + * src/mips/ffi.c: Fix handling of uint32_t arguments on the + MIPS N32 ABI. + +2013-10-13 Sandra Loosemore <sandra@codesourcery.com> + + * README: Add Nios II to table of supported platforms. + * Makefile.am (EXTRA_DIST): Add nios2 files. + (nodist_libffi_la_SOURCES): Likewise. + * Makefile.in: Regenerated. + * configure.ac (nios2*-linux*): New host. + (NIOS2): Add AM_CONDITIONAL. + * configure: Regenerated. + * src/nios2/ffi.c: New. + * src/nios2/ffitarget.h: New. + * src/nios2/sysv.S: New. + * src/prep_cif.c (initialize_aggregate): Handle extra structure + alignment via FFI_AGGREGATE_ALIGNMENT. + (ffi_prep_cif_core): Conditionalize structure return for NIOS2. + +2013-10-10 Sandra Loosemore <sandra@codesourcery.com> + + * testsuite/libffi.call/cls_many_mixed_args.c (cls_ret_double_fn): + Fix uninitialized variable. + +2013-10-11 Marcus Shawcroft <marcus.shawcroft@arm.com> + + * testsuite/libffi.call/many.c (many): Replace * with +. + +2013-10-08 OndÅ™ej BÃlka <neleai@seznam.cz> + + * src/aarch64/ffi.c, src/aarch64/sysv.S, src/arm/ffi.c, + src/arm/gentramp.sh, src/bfin/sysv.S, src/closures.c, + src/dlmalloc.c, src/ia64/ffi.c, src/microblaze/ffi.c, + src/microblaze/sysv.S, src/powerpc/darwin_closure.S, + src/powerpc/ffi.c, src/powerpc/ffi_darwin.c, src/sh/ffi.c, + src/tile/tile.S, testsuite/libffi.call/nested_struct11.c: Fix + spelling errors. + +2013-10-08 Anthony Green <green@moxielogic.com> + + * aclocal.m4, compile, config.guess, config.sub, depcomp, + install-sh, mdate-sh, missing, texinfo.tex: Update from upstream. + * configure.ac: Update version to 3.0.14-rc0. + * Makefile.in, configure, Makefile.in, include/Makefile.in, + man/Makefile.in, testsuite/Makefile.in: Rebuilt. + * README: Mention M88K and VAX. + +2013-07-15 Miod Vallat <miod@openbsd.org> + + * Makefile.am, + configure.ac, + src/m88k/ffi.c, + src/m88k/ffitarget.h, + src/m88k/obsd.S, + src/vax/elfbsd.S, + src/vax/ffi.c, + src/vax/ffitarget.h: Add m88k and vax support. + +2013-06-24 Alan Modra <amodra@gmail.com> + + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Move var declaration + before statements. + (ffi_prep_args64): Support little-endian. + (ffi_closure_helper_SYSV, ffi_closure_helper_LINUX64): Likewise. + * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Likewise. + * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Likewise. + +2013-06-12 Mischa Jonker <mjonker@synopsys.com> + + * configure.ac: Add support for ARC. + * Makefile.am: Likewise. + * README: Add ARC details. + * src/arc/arcompact.S: New. + * src/arc/ffi.c: Likewise. + * src/arc/ffitarget.h: Likewise. + +2013-03-28 David Schneider <david.schneider@bivab.de> + + * src/arm/ffi.c: Fix support for ARM hard-float calling convention. + * src/arm/sysv.S: call different methods for SYSV and VFP ABIs. + * testsuite/libffi.call/cls_many_mixed_args.c: testcase for a closure with + mixed arguments, many doubles. + * testsuite/libffi.call/many_double.c: testcase for calling a function using + more than 8 doubles. + * testcase/libffi.call/many.c: use absolute value to check result against an + epsilon + +2013-03-17 Anthony Green <green@moxielogic.com> + + * README: Update for 3.0.13. + * configure.ac: Ditto. + * configure: Rebuilt. + * doc/*: Update version. + +2013-03-17 Dave Korn <dave.korn.cygwin@gmail.com> + + * src/closures.c (is_emutramp_enabled + [!FFI_MMAP_EXEC_EMUTRAMP_PAX]): Move default definition outside + enclosing #if scope. + +2013-03-17 Anthony Green <green@moxielogic.com> + + * configure.ac: Only modify toolexecdir in certain cases. + * configure: Rebuilt. + +2013-03-16 Gilles Talis <gilles.talis@gmail.com> + + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Don't use + fparg_count,etc on __NO_FPRS__ targets. + +2013-03-16 Alan Hourihane <alanh@fairlite.co.uk> + + * src/m68k/sysv.S (epilogue): Don't use extb instruction on + m680000 machines. + +2013-03-16 Alex Gaynor <alex.gaynor@gmail.com> + + * src/x86/ffi.c (ffi_prep_cif_machdep): Always align stack. + +2013-03-13 Markos Chandras <markos.chandras@imgtec.com> + + * configure.ac: Add support for Imagination Technologies Meta. + * Makefile.am: Likewise. + * README: Add Imagination Technologies Meta details. + * src/metag/ffi.c: New. + * src/metag/ffitarget.h: Likewise. + * src/metag/sysv.S: Likewise. + +2013-02-24 Andreas Schwab <schwab@linux-m68k.org> + + * doc/libffi.texi (Structures): Fix missing category argument of + @deftp. + +2013-02-11 Anthony Green <green@moxielogic.com> + + * configure.ac: Update release number to 3.0.12. + * configure: Rebuilt. + * README: Update release info. + +2013-02-10 Anthony Green <green@moxielogic.com> + + * README: Add Moxie. + * src/moxie/ffi.c: Created. + * src/moxie/eabi.S: Created. + * src/moxie/ffitarget.h: Created. + * Makefile.am (nodist_libffi_la_SOURCES): Add Moxie. + * Makefile.in: Rebuilt. + * configure.ac: Add Moxie. + * configure: Rebuilt. + * testsuite/libffi.call/huge_struct.c: Disable format string + warnings for moxie*-*-elf tests. + +2013-02-10 Anthony Green <green@moxielogic.com> + + * Makefile.am (LTLDFLAGS): Fix reference. + * Makefile.in: Rebuilt. + +2013-02-10 Anthony Green <green@moxielogic.com> + + * README: Update supported platforms. Update test results link. + +2013-02-09 Anthony Green <green@moxielogic.com> + + * testsuite/libffi.call/negint.c: Remove forced -O2. + * testsuite/libffi.call/many2.c (foo): Remove GCCism. + * testsuite/libffi.call/ffitest.h: Add default PRIuPTR definition. + + * src/sparc/v8.S (ffi_closure_v8): Import ancient ulonglong + closure return type fix developed by Martin v. Löwis for cpython + fork. + +2013-02-08 Andreas Tobler <andreast@fgznet.ch> + + * src/powerpc/ffi.c (ffi_prep_cif_machdep): Fix small struct + support. + * src/powerpc/sysv.S: Ditto. + +2013-02-08 Anthony Green <green@moxielogic.com> + + * testsuite/libffi.call/cls_longdouble.c: Remove xfail for + arm*-*-*. + +2013-02-08 Anthony Green <green@moxielogic.com> + + * src/sparc/ffi.c (ffi_prep_closure_loc): Fix cache flushing for GCC. + +2013-02-08 Matthias Klose <doko@ubuntu.com> + + * man/ffi_prep_cif.3: Clean up for debian linter. + +2013-02-08 Peter Bergner <bergner@vnet.ibm.com> + + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Account for FP args pushed + on the stack. + +2013-02-08 Anthony Green <green@moxielogic.com> + + * Makefile.am (EXTRA_DIST): Add missing files. + * testsuite/Makefile.am (EXTRA_DIST): Ditto. + * Makefile.in: Rebuilt. + +2013-02-08 Anthony Green <green@moxielogic.com> + + * configure.ac: Move sparc asm config checks to within functions + for compatibility with sun tools. + * configure: Rebuilt. + * src/sparc/ffi.c (ffi_prep_closure_loc): Flush cache on v9 + systems. + * src/sparc/v8.S (ffi_flush_icache): Implement a sparc v9 cache + flusher. + +2013-02-08 Nathan Rossi <nathan.rossi@xilinx.com> + + * src/microblaze/ffi.c (ffi_closure_call_SYSV): Fix handling of + small big-endian structures. + (ffi_prep_args): Ditto. + +2013-02-07 Anthony Green <green@moxielogic.com> + + * src/sparc/v8.S (ffi_call_v8): Fix typo from last patch + (effectively hiding ffi_call_v8). + +2013-02-07 Anthony Green <green@moxielogic.com> + + * configure.ac: Update bug reporting address. + * configure.in: Rebuild. + + * src/sparc/v8.S (ffi_flush_icache): Out-of-line cache flusher for + Sun compiler. + * src/sparc/ffi.c (ffi_call): Remove warning. + Call ffi_flush_icache for non-GCC builds. + (ffi_prep_closure_loc): Use ffi_flush_icache. + + * Makefile.am (EXTRA_DIST): Add libtool-ldflags. + * Makefile.in: Rebuilt. + * libtool-ldflags: New file. + +2013-02-07 Daniel Schepler <dschepler@gmail.com> + + * configure.ac: Correctly identify x32 systems as 64-bit. + * m4/libtool.m4: Remove libtool expr error. + * aclocal.m4, configure: Rebuilt. + +2013-02-07 Anthony Green <green@moxielogic.com> + + * configure.ac: Fix GCC usage test. + * configure: Rebuilt. + * README: Mention LLVM/GCC x86_64 issue. + * testsuite/Makefile.in: Rebuilt. + +2013-02-07 Anthony Green <green@moxielogic.com> + + * testsuite/libffi.call/cls_double_va.c (main): Replace // style + comments with /* */ for xlc compiler. + * testsuite/libffi.call/stret_large.c (main): Ditto. + * testsuite/libffi.call/stret_large2.c (main): Ditto. + * testsuite/libffi.call/nested_struct1.c (main): Ditto. + * testsuite/libffi.call/huge_struct.c (main): Ditto. + * testsuite/libffi.call/float_va.c (main): Ditto. + * testsuite/libffi.call/cls_struct_va1.c (main): Ditto. + * testsuite/libffi.call/cls_pointer_stack.c (main): Ditto. + * testsuite/libffi.call/cls_pointer.c (main): Ditto. + * testsuite/libffi.call/cls_longdouble_va.c (main): Ditto. + +2013-02-06 Anthony Green <green@moxielogic.com> + + * man/ffi_prep_cif.3: Clean up for debian lintian checker. + +2013-02-06 Anthony Green <green@moxielogic.com> + + * Makefile.am (pkgconfigdir): Add missing pkgconfig install bits. + * Makefile.in: Rebuild. + +2013-02-02 Mark H Weaver <mhw@netris.org> + + * src/x86/ffi64.c (ffi_call): Sign-extend integer arguments passed + via general purpose registers. + +2013-01-21 Nathan Rossi <nathan.rossi@xilinx.com> + + * README: Add MicroBlaze details. + * Makefile.am: Add MicroBlaze support. + * configure.ac: Likewise. + * src/microblaze/ffi.c: New. + * src/microblaze/ffitarget.h: Likewise. + * src/microblaze/sysv.S: Likewise. + +2013-01-21 Nathan Rossi <nathan.rossi@xilinx.com> + * testsuite/libffi.call/return_uc.c: Fixed issue. + +2013-01-21 Chris Zankel <chris@zankel.net> + + * README: Add Xtensa support. + * Makefile.am: Likewise. + * configure.ac: Likewise. + * Makefile.in Regenerate. + * configure: Likewise. + * src/prep_cif.c: Handle Xtensa. + * src/xtensa: New directory. + * src/xtensa/ffi.c: New file. + * src/xtensa/ffitarget.h: Ditto. + * src/xtensa/sysv.S: Ditto. + +2013-01-11 Anthony Green <green@moxielogic.com> + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Replace // style + comments with /* */ for xlc compiler. + * src/powerpc/aix.S (ffi_call_AIX): Ditto. + * testsuite/libffi.call/ffitest.h (allocate_mmap): Delete + deprecated inline function. + * testsuite/libffi.special/ffitestcxx.h: Ditto. + * README: Add update for AIX support. + +2013-01-11 Anthony Green <green@moxielogic.com> + + * configure.ac: Robustify pc relative reloc check. + * m4/ax_cc_maxopt.m4: Don't -malign-double. This is an ABI + changing option for 32-bit x86. + * aclocal.m4, configure: Rebuilt. + * README: Update supported target list. + +2013-01-10 Anthony Green <green@moxielogic.com> + + * README (tested): Add Compiler column to table. + +2013-01-10 Anthony Green <green@moxielogic.com> + + * src/x86/ffi64.c (struct register_args): Make sse array and array + of unions for sunpro compiler compatibility. + +2013-01-10 Anthony Green <green@moxielogic.com> + + * configure.ac: Test target platform size_t size. Handle both 32 + and 64-bit builds for x86_64-* and i?86-* targets (allowing for + CFLAG option to change default settings). + * configure, aclocal.m4: Rebuilt. + +2013-01-10 Anthony Green <green@moxielogic.com> + + * testsuite/libffi.special/special.exp: Only run exception + handling tests when using GNU compiler. + + * m4/ax_compiler_vendor.m4: New file. + * configure.ac: Test for compiler vendor and don't use + AX_CFLAGS_WARN_ALL with the sun compiler. + * aclocal.m4, configure: Rebuilt. + +2013-01-10 Anthony Green <green@moxielogic.com> + + * include/ffi_common.h: Don't use GCCisms to define types when + building with the SUNPRO compiler. + +2013-01-10 Anthony Green <green@moxielogic.com> + + * configure.ac: Put local.exp in the right place. + * configure: Rebuilt. + + * src/x86/ffi.c: Update comment about regparm function attributes. + * src/x86/sysv.S (ffi_closure_SYSV): The SUNPRO compiler requires + that all function arguments be passed on the stack (no regparm + support). + +2013-01-08 Anthony Green <green@moxielogic.com> + + * configure.ac: Generate local.exp. This sets CC_FOR_TARGET + when we are using the vendor compiler. + * testsuite/Makefile.am (EXTRA_DEJAGNU_SITE_CONFIG): Point to + ../local.exp. + * configure, testsuite/Makefile.in: Rebuilt. + + * testsuite/libffi.call/call.exp: Run tests with different + options, depending on whether or not we are using gcc or the + vendor compiler. + * testsuite/lib/libffi.exp (libffi-init): Set using_gcc based on + whether or not we are building/testing with gcc. + +2013-01-08 Anthony Green <green@moxielogic.com> + + * configure.ac: Switch x86 solaris target to X86 by default. + * configure: Rebuilt. + +2013-01-08 Anthony Green <green@moxielogic.com> + + * configure.ac: Fix test for read-only eh_frame. + * configure: Rebuilt. + +2013-01-08 Anthony Green <green@moxielogic.com> + + * src/x86/sysv.S, src/x86/unix64.S: Only emit DWARF unwind info + when building with the GNU toolchain. + * testsuite/libffi.call/ffitest.h (CHECK): Fix for Solaris vendor + compiler. + +2013-01-07 Thorsten Glaser <tg@mirbsd.org> + + * testsuite/libffi.call/cls_uchar_va.c, + testsuite/libffi.call/cls_ushort_va.c, + testsuite/libffi.call/va_1.c: Testsuite fixes. + +2013-01-07 Thorsten Glaser <tg@mirbsd.org> + + * src/m68k/ffi.c (CIF_FLAGS_SINT8, CIF_FLAGS_SINT16): Define. + (ffi_prep_cif_machdep): Fix 8-bit and 16-bit signed calls. + * src/m68k/sysv.S (ffi_call_SYSV, ffi_closure_SYSV): Ditto. + +2013-01-04 Anthony Green <green@moxielogic.com> + + * Makefile.am (AM_CFLAGS): Don't automatically add -fexceptions + and -Wall. This is set in the configure script after testing for + GCC. + * Makefile.in: Rebuilt. + +2013-01-02 rofl0r <https://github.com/rofl0r> + + * src/powerpc/ffi.c (ffi_prep_cif_machdep): Fix build error on ppc + when long double == double. + +2013-01-02 Reini Urban <rurban@x-ray.at> + + * Makefile.am (libffi_la_LDFLAGS): Add -no-undefined to LDFLAGS + (required for shared libs on cygwin/mingw). + * Makefile.in: Rebuilt. + +2012-10-31 Alan Modra <amodra@gmail.co> + + * src/powerpc/linux64_closure.S: Add new ABI support. + * src/powerpc/linux64.S: Likewise. + +2012-10-30 Magnus Granberg <zorry@gentoo.org> + Pavel Labushev <pavel.labushev@runbox.ru> + + * configure.ac: New options pax_emutramp + * configure, fficonfig.h.in: Regenerated + * src/closures.c: New function emutramp_enabled_check() and + checks. + +2012-10-30 Frederick Cheung <frederick.cheung@gmail.com> + + * configure.ac: Enable FFI_MAP_EXEC_WRIT for Darwin 12 (mountain + lion) and future version. + * configure: Rebuild. + +2012-10-30 James Greenhalgh <james.greenhalgh at arm.com> + Marcus Shawcroft <marcus.shawcroft at arm.com> + + * README: Add details of aarch64 port. + * src/aarch64/ffi.c: New. + * src/aarch64/ffitarget.h: Likewise. + * src/aarch64/sysv.S: Likewise. + * Makefile.am: Support aarch64. + * configure.ac: Support aarch64. + * Makefile.in, configure: Rebuilt. + +2012-10-30 James Greenhalgh <james.greenhalgh at arm.com> + Marcus Shawcroft <marcus.shawcroft at arm.com> + + * testsuite/lib/libffi.exp: Add support for aarch64. + * testsuite/libffi.call/cls_struct_va1.c: New. + * testsuite/libffi.call/cls_uchar_va.c: Likewise. + * testsuite/libffi.call/cls_uint_va.c: Likewise. + * testsuite/libffi.call/cls_ulong_va.c: Likewise. + * testsuite/libffi.call/cls_ushort_va.c: Likewise. + * testsuite/libffi.call/nested_struct11.c: Likewise. + * testsuite/libffi.call/uninitialized.c: Likewise. + * testsuite/libffi.call/va_1.c: Likewise. + * testsuite/libffi.call/va_struct1.c: Likewise. + * testsuite/libffi.call/va_struct2.c: Likewise. + * testsuite/libffi.call/va_struct3.c: Likewise. + +2012-10-12 Walter Lee <walt@tilera.com> + + * Makefile.am: Add TILE-Gx/TILEPro support. + * configure.ac: Likewise. + * Makefile.in: Regenerate. + * configure: Likewise. + * src/prep_cif.c (ffi_prep_cif_core): Handle TILE-Gx/TILEPro. + * src/tile: New directory. + * src/tile/ffi.c: New file. + * src/tile/ffitarget.h: Ditto. + * src/tile/tile.S: Ditto. + +2012-10-12 Matthias Klose <doko@ubuntu.com> + + * generate-osx-source-and-headers.py: Normalize whitespace. + +2012-09-14 David Edelsohn <dje.gcc@gmail.com> + + * configure: Regenerated. + +2012-08-26 Andrew Pinski <apinski@cavium.com> + + PR libffi/53014 + * src/mips/ffi.c (ffi_prep_closure_loc): Allow n32 with soft-float and n64 with + soft-float. + +2012-08-08 Uros Bizjak <ubizjak@gmail.com> + + * src/s390/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test, + just return FFI_BAD_ABI when things are wrong. + +2012-07-18 H.J. Lu <hongjiu.lu@intel.com> + + PR libffi/53982 + PR libffi/53973 + * src/x86/ffitarget.h: Check __ILP32__ instead of __LP64__ for x32. + (FFI_SIZEOF_JAVA_RAW): Defined to 4 for x32. + +2012-05-16 H.J. Lu <hongjiu.lu@intel.com> + + * configure: Regenerated. + +2012-05-05 Nicolas Lelong + + * libffi.xcodeproj/project.pbxproj: Fixes. + * README: Update for iOS builds. + +2012-04-23 Alexandre Keunecke I. de Mendonca <alexandre.keunecke@gmail.com> + + * configure.ac: Add Blackfin/sysv support + * Makefile.am: Add Blackfin/sysv support + * src/bfin/ffi.c: Add Blackfin/sysv support + * src/bfin/ffitarget.h: Add Blackfin/sysv support + +2012-04-11 Anthony Green <green@moxielogic.com> + + * Makefile.am (EXTRA_DIST): Add new script. + * Makefile.in: Rebuilt. + +2012-04-11 Zachary Waldowski <zwaldowski@gmail.com> + + * generate-ios-source-and-headers.py, + libffi.xcodeproj/project.pbxproj: Support a Mac static library via + Xcode. Set iOS compatibility to 4.0. Move iOS trampoline + generation into an Xcode "run script" phase. Include both as + Xcode build scripts. Don't always regenerate config files. + +2012-04-10 Anthony Green <green@moxielogic.com> + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Add missing semicolon. + +2012-04-06 Anthony Green <green@moxielogic.com> + + * Makefile.am (EXTRA_DIST): Add new iOS/xcode files. + * Makefile.in: Rebuilt. + +2012-04-06 Mike Lewis <mikelikespie@gmail.com> + + * generate-ios-source-and-headers.py: New file. + * libffi.xcodeproj/project.pbxproj: New file. + * README: Update instructions on building iOS binary. + * build-ios.sh: Delete. + +2012-04-06 Anthony Green <green@moxielogic.com> + + * src/x86/ffi64.c (UINT128): Define differently for Intel and GNU + compilers, then use it. + +2012-04-06 H.J. Lu <hongjiu.lu@intel.com> + + * m4/libtool.m4 (_LT_ENABLE_LOCK): Support x32. + +2012-04-06 Anthony Green <green@moxielogic.com> + + * testsuite/Makefile.am (EXTRA_DIST): Add missing test cases. + * testsuite/Makefile.in: Rebuilt. + +2012-04-05 Zachary Waldowski <zwaldowski@gmail.com> + + * include/ffi.h.in: Add missing trampoline table fields. + * src/arm/sysv.S: Fix ENTRY definition, and wrap symbol references + in CNAME. + * src/x86/ffi.c: Wrap Windows specific code in ifdefs. + +2012-04-02 Peter Bergner <bergner@vnet.ibm.com> + + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Declare double_tmp. + Silence casting pointer to integer of different size warning. + Delete goto to previously deleted label. + (ffi_call): Silence possibly undefined warning. + (ffi_closure_helper_SYSV): Declare variable type. + +2012-04-02 Peter Rosin <peda@lysator.liu.se> + + * src/x86/win32.S (ffi_call_win32): Sign/zero extend the return + value in the Intel version as is already done for the AT&T version. + (ffi_closure_SYSV): Likewise. + (ffi_closure_raw_SYSV): Likewise. + (ffi_closure_STDCALL): Likewise. + +2012-03-29 Peter Rosin <peda@lysator.liu.se> + + * src/x86/win32.S (ffi_closure_raw_THISCALL): Unify the frame + generation, fix the ENDP label and remove the surplus third arg + from the 'lea' insn. + +2012-03-29 Peter Rosin <peda@lysator.liu.se> + + * src/x86/win32.S (ffi_closure_raw_SYSV): Make the 'stubraw' label + visible outside the PROC, so that ffi_closure_raw_THISCALL can see + it. Also instruct the assembler to add a frame to the function. + +2012-03-23 Peter Rosin <peda@lysator.liu.se> + + * Makefile.am (AM_CPPFLAGS): Add -DFFI_BUILDING. + * Makefile.in: Rebuilt. + * include/ffi.h.in [MSVC]: Add __declspec(dllimport) decorations + to all data exports, when compiling libffi clients using MSVC. + +2012-03-29 Peter Rosin <peda@lysator.liu.se> + + * src/x86/ffitarget.h (ffi_abi): Add new ABI FFI_MS_CDECL and + make it the default for MSVC. + (FFI_TYPE_MS_STRUCT): New structure return convention. + * src/x86/ffi.c (ffi_prep_cif_machdep): Tweak the structure + return convention for FFI_MS_CDECL to be FFI_TYPE_MS_STRUCT + instead of an ordinary FFI_TYPE_STRUCT. + (ffi_prep_args): Treat FFI_TYPE_MS_STRUCT as FFI_TYPE_STRUCT. + (ffi_call): Likewise. + (ffi_prep_incoming_args_SYSV): Likewise. + (ffi_raw_call): Likewise. + (ffi_prep_closure_loc): Treat FFI_MS_CDECL as FFI_SYSV. + * src/x86/win32.S (ffi_closure_SYSV): For FFI_TYPE_MS_STRUCT, + return a pointer to the result structure in eax and don't pop + that pointer from the stack, the caller takes care of it. + (ffi_call_win32): Treat FFI_TYPE_MS_STRUCT as FFI_TYPE_STRUCT. + (ffi_closure_raw_SYSV): Likewise. + +2012-03-22 Peter Rosin <peda@lysator.liu.se> + + * testsuite/libffi.call/closure_stdcall.c [MSVC]: Add inline + assembly version with Intel syntax. + * testsuite/libffi.call/closure_thiscall.c [MSVC]: Likewise. + +2012-03-23 Peter Rosin <peda@lysator.liu.se> + + * testsuite/libffi.call/ffitest.h: Provide abstration of + __attribute__((fastcall)) in the form of a __FASTCALL__ + define. Define it to __fastcall for MSVC. + * testsuite/libffi.call/fastthis1_win32.c: Use the above. + * testsuite/libffi.call/fastthis2_win32.c: Likewise. + * testsuite/libffi.call/fastthis3_win32.c: Likewise. + * testsuite/libffi.call/strlen2_win32.c: Likewise. + * testsuite/libffi.call/struct1_win32.c: Likewise. + * testsuite/libffi.call/struct2_win32.c: Likewise. + +2012-03-22 Peter Rosin <peda@lysator.liu.se> + + * src/x86/win32.S [MSVC] (ffi_closure_THISCALL): Remove the manual + frame on function entry, MASM adds one automatically. + +2012-03-22 Peter Rosin <peda@lysator.liu.se> + + * testsuite/libffi.call/ffitest.h [MSVC]: Add kludge for missing + bits in the MSVC headers. + +2012-03-22 Peter Rosin <peda@lysator.liu.se> + + * testsuite/libffi.call/cls_12byte.c: Adjust to the C89 style + with no declarations after statements. + * testsuite/libffi.call/cls_16byte.c: Likewise. + * testsuite/libffi.call/cls_18byte.c: Likewise. + * testsuite/libffi.call/cls_19byte.c: Likewise. + * testsuite/libffi.call/cls_1_1byte.c: Likewise. + * testsuite/libffi.call/cls_20byte.c: Likewise. + * testsuite/libffi.call/cls_20byte1.c: Likewise. + * testsuite/libffi.call/cls_24byte.c: Likewise. + * testsuite/libffi.call/cls_2byte.c: Likewise. + * testsuite/libffi.call/cls_3_1byte.c: Likewise. + * testsuite/libffi.call/cls_3byte1.c: Likewise. + * testsuite/libffi.call/cls_3byte2.c: Likewise. + * testsuite/libffi.call/cls_4_1byte.c: Likewise. + * testsuite/libffi.call/cls_4byte.c: Likewise. + * testsuite/libffi.call/cls_5_1_byte.c: Likewise. + * testsuite/libffi.call/cls_5byte.c: Likewise. + * testsuite/libffi.call/cls_64byte.c: Likewise. + * testsuite/libffi.call/cls_6_1_byte.c: Likewise. + * testsuite/libffi.call/cls_6byte.c: Likewise. + * testsuite/libffi.call/cls_7_1_byte.c: Likewise. + * testsuite/libffi.call/cls_7byte.c: Likewise. + * testsuite/libffi.call/cls_8byte.c: Likewise. + * testsuite/libffi.call/cls_9byte1.c: Likewise. + * testsuite/libffi.call/cls_9byte2.c: Likewise. + * testsuite/libffi.call/cls_align_double.c: Likewise. + * testsuite/libffi.call/cls_align_float.c: Likewise. + * testsuite/libffi.call/cls_align_longdouble.c: Likewise. + * testsuite/libffi.call/cls_align_longdouble_split.c: Likewise. + * testsuite/libffi.call/cls_align_longdouble_split2.c: Likewise. + * testsuite/libffi.call/cls_align_pointer.c: Likewise. + * testsuite/libffi.call/cls_align_sint16.c: Likewise. + * testsuite/libffi.call/cls_align_sint32.c: Likewise. + * testsuite/libffi.call/cls_align_sint64.c: Likewise. + * testsuite/libffi.call/cls_align_uint16.c: Likewise. + * testsuite/libffi.call/cls_align_uint32.c: Likewise. + * testsuite/libffi.call/cls_align_uint64.c: Likewise. + * testsuite/libffi.call/cls_dbls_struct.c: Likewise. + * testsuite/libffi.call/cls_pointer_stack.c: Likewise. + * testsuite/libffi.call/err_bad_typedef.c: Likewise. + * testsuite/libffi.call/huge_struct.c: Likewise. + * testsuite/libffi.call/nested_struct.c: Likewise. + * testsuite/libffi.call/nested_struct1.c: Likewise. + * testsuite/libffi.call/nested_struct10.c: Likewise. + * testsuite/libffi.call/nested_struct2.c: Likewise. + * testsuite/libffi.call/nested_struct3.c: Likewise. + * testsuite/libffi.call/nested_struct4.c: Likewise. + * testsuite/libffi.call/nested_struct5.c: Likewise. + * testsuite/libffi.call/nested_struct6.c: Likewise. + * testsuite/libffi.call/nested_struct7.c: Likewise. + * testsuite/libffi.call/nested_struct8.c: Likewise. + * testsuite/libffi.call/nested_struct9.c: Likewise. + * testsuite/libffi.call/stret_large.c: Likewise. + * testsuite/libffi.call/stret_large2.c: Likewise. + * testsuite/libffi.call/stret_medium.c: Likewise. + * testsuite/libffi.call/stret_medium2.c: Likewise. + * testsuite/libffi.call/struct1.c: Likewise. + * testsuite/libffi.call/struct1_win32.c: Likewise. + * testsuite/libffi.call/struct2.c: Likewise. + * testsuite/libffi.call/struct2_win32.c: Likewise. + * testsuite/libffi.call/struct3.c: Likewise. + * testsuite/libffi.call/struct4.c: Likewise. + * testsuite/libffi.call/struct5.c: Likewise. + * testsuite/libffi.call/struct6.c: Likewise. + * testsuite/libffi.call/struct7.c: Likewise. + * testsuite/libffi.call/struct8.c: Likewise. + * testsuite/libffi.call/struct9.c: Likewise. + * testsuite/libffi.call/testclosure.c: Likewise. + +2012-03-21 Peter Rosin <peda@lysator.liu.se> + + * testsuite/libffi.call/float_va.c (float_va_fn): Use %f when + printing doubles (%lf is for long doubles). + (main): Likewise. + +2012-03-21 Peter Rosin <peda@lysator.liu.se> + + * testsuite/lib/target-libpath.exp [*-*-cygwin*, *-*-mingw*] + (set_ld_library_path_env_vars): Add the library search dir to PATH + (and save PATH for later). + (restore_ld_library_path_env_vars): Restore PATH. + +2012-03-21 Peter Rosin <peda@lysator.liu.se> + + * testsuite/lib/target-libpath.exp [*-*-cygwin*, *-*-mingw*] + (set_ld_library_path_env_vars): Add the library search dir to PATH + (and save PATH for later). + (restore_ld_library_path_env_vars): Restore PATH. + +2012-03-20 Peter Rosin <peda@lysator.liu.se> + + * testsuite/libffi.call/strlen2_win32.c (main): Remove bug. + * src/x86/win32.S [MSVC] (ffi_closure_SYSV): Make the 'stub' label + visible outside the PROC, so that ffi_closure_THISCALL can see it. + +2012-03-20 Peter Rosin <peda@lysator.liu.se> + + * testsuite/libffi.call/strlen2_win32.c (main): Remove bug. + * src/x86/win32.S [MSVC] (ffi_closure_SYSV): Make the 'stub' label + visible outside the PROC, so that ffi_closure_THISCALL can see it. + +2012-03-19 Alan Hourihane <alanh@fairlite.co.uk> + + * src/m68k/ffi.c: Add MINT support. + * src/m68k/sysv.S: Ditto. + +2012-03-06 Chung-Lin Tang <cltang@codesourcery.com> + + * src/arm/ffi.c (ffi_call): Add __ARM_EABI__ guard around call to + ffi_call_VFP(). + (ffi_prep_closure_loc): Add __ARM_EABI__ guard around use of + ffi_closure_VFP. + * src/arm/sysv.S: Add __ARM_EABI__ guard around VFP code. + +2012-03-19 chennam <csit@axway.com> + + * src/powerpc/ffi_darwin.c (ffi_prep_closure_loc): Fix AIX closure + support. + +2012-03-13 Kaz Kojima <kkojima@gcc.gnu.org> + + * src/sh/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test, + just return FFI_BAD_ABI when things are wrong. + * src/sh64/ffi.c (ffi_prep_closure_loc): Ditto. + +2012-03-09 David Edelsohn <dje.gcc@gmail.com> + + * src/powerpc/aix_closure.S (ffi_closure_ASM): Adjust for Darwin64 + change to return value of ffi_closure_helper_DARWIN and load type + from return type. + +2012-03-03 H.J. Lu <hongjiu.lu@intel.com> + + * src/x86/ffi64.c (ffi_call): Cast the return value to unsigned + long. + (ffi_prep_closure_loc): Cast to 64bit address in trampoline. + (ffi_closure_unix64_inner): Cast return pointer to unsigned long + first. + + * src/x86/ffitarget.h (FFI_SIZEOF_ARG): Defined to 8 for x32. + (ffi_arg): Set to unsigned long long for x32. + (ffi_sarg): Set to long long for x32. + +2012-03-03 H.J. Lu <hongjiu.lu@intel.com> + + * src/prep_cif.c (ffi_prep_cif_core): Properly check bad ABI. + +2012-03-03 Andoni Morales Alastruey <ylatuya@gmail.com> + + * configure.ac: Add -no-undefined for both 32- and 64-bit x86 + windows-like hosts. + * configure: Rebuilt. + +2012-02-27 Mikael Pettersson <mikpe@it.uu.se> + + PR libffi/52223 + * Makefile.am (FLAGS_TO_PASS): Define. + * Makefile.in: Regenerate. + +2012-02-23 Anthony Green <green@moxielogic.com> + + * src/*/ffitarget.h: Ensure that users never include ffitarget.h + directly. + +2012-02-23 Kai Tietz <ktietz@redhat.com> + + PR libffi/52221 + * src/x86/ffi.c (ffi_closure_raw_THISCALL): New + prototype. + (ffi_prep_raw_closure_loc): Use ffi_closure_raw_THISCALL for + thiscall-convention. + (ffi_raw_call): Use ffi_prep_args_raw. + * src/x86/win32.S (ffi_closure_raw_THISCALL): Add + implementation for stub. + +2012-02-10 Kai Tietz <ktietz@redhat.com> + + * configure.ac (AM_LTLDFLAGS): Add -no-undefine for x64 + windows target. + * configure: Regenerated. + +2012-02-08 Kai Tietz <ktietz@redhat.com> + + * src/prep_cif.c (ffi_prep_cif): Allow for X86_WIN32 + also FFI_THISCALL. + * src/x86/ffi.c (ffi_closure_THISCALL): Add prototype. + (FFI_INIT_TRAMPOLINE_THISCALL): New trampoline code. + (ffi_prep_closure_loc): Add FFI_THISCALL support. + * src/x86/ffitarget.h (FFI_TRAMPOLINE_SIZE): Adjust size. + * src/x86/win32.S (ffi_closure_THISCALL): New closure code + for thiscall-calling convention. + * testsuite/libffi.call/closure_thiscall.c: New test. + +2012-01-28 Kai Tietz <ktietz@redhat.com> + + * src/libffi/src/x86/ffi.c (ffi_call_win32): Add new + argument to prototype for specify calling-convention. + (ffi_call): Add support for stdcall/thiscall convention. + (ffi_prep_args): Likewise. + (ffi_raw_call): Likewise. + * src/x86/ffitarget.h (ffi_abi): Add FFI_THISCALL and + FFI_FASTCALL. + * src/x86/win32.S (_ffi_call_win32): Add support for + fastcall/thiscall calling-convention calls. + * testsuite/libffi.call/fastthis1_win32.c: New test. + * testsuite/libffi.call/fastthis2_win32.c: New test. + * testsuite/libffi.call/fastthis3_win32.c: New test. + * testsuite/libffi.call/strlen2_win32.c: New test. + * testsuite/libffi.call/many2_win32.c: New test. + * testsuite/libffi.call/struct1_win32.c: New test. + * testsuite/libffi.call/struct2_win32.c: New test. + +2012-01-23 Uros Bizjak <ubizjak@gmail.com> + + * src/alpha/ffi.c (ffi_prep_closure_loc): Check for bad ABI. + +2012-01-23 Anthony Green <green@moxielogic.com> + Chris Young <cdyoung@ntlworld.com> + + * configure.ac: Add Amiga support. + * configure: Rebuilt. + +2012-01-23 Dmitry Nadezhin <dmitry.nadezhin@gmail.com> + + * include/ffi_common.h (LIKELY, UNLIKELY): Fix definitions. + +2012-01-23 Andreas Schwab <schwab@linux-m68k.org> + + * src/m68k/sysv.S (ffi_call_SYSV): Properly test for plain + mc68000. Test for __HAVE_68881__ in addition to __MC68881__. + +2012-01-19 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/48496 + * src/ia64/ffi.c (ffi_call): Fix up aliasing violations. + +2012-01-09 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * configure.ac (i?86-*-*): Set TARGET to X86_64. + * configure: Regenerate. + +2011-12-07 Andrew Pinski <apinski@cavium.com> + + PR libffi/50051 + * src/mips/n32.S: Add ".set mips4". + +2011-11-21 Andreas Tobler <andreast@fgznet.ch> + + * configure: Regenerate. + +2011-11-12 David Gilbert <david.gilbert@linaro.org> + + * doc/libffi.texi, include/ffi.h.in, include/ffi_common.h, + man/Makefile.am, man/ffi.3, man/ffi_prep_cif.3, + man/ffi_prep_cif_var.3, src/arm/ffi.c, src/arm/ffitarget.h, + src/cris/ffi.c, src/prep_cif.c, + testsuite/libffi.call/cls_double_va.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/float_va.c: Many changes to support variadic + function calls. + +2011-11-12 Kyle Moffett <Kyle.D.Moffett@boeing.com> + + * src/powerpc/ffi.c, src/powerpc/ffitarget.h, + src/powerpc/ppc_closure.S, src/powerpc/sysv.S: Many changes for + softfloat powerpc variants. + +2011-11-12 Petr Salinger <Petr.Salinger@seznam.cz> + + * configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Fix kfreebsd support. + * configure: Rebuilt. + +2011-11-12 Timothy Wall <twall@users.sf.net> + + * src/arm/ffi.c (ffi_prep_args, ffi_prep_incoming_args_SYSV): Max + alignment of 4 for wince on ARM. + +2011-11-12 Kyle Moffett <Kyle.D.Moffett@boeing.com> + Anthony Green <green@moxielogic.com> + + * src/ppc/sysv.S, src/ppc/ffi.c: Remove use of ppc string + instructions (not available on some cores, like the PPC440). + +2011-11-12 Kimura Wataru <kimuraw@i.nifty.jp> + + * m4/ax_enable_builddir: Change from string comparison to numeric + comparison for wc output. + * configure.ac: Enable FFI_MMAP_EXEC_WRIT for darwin11 aka Mac OS + X 10.7. + * configure: Rebuilt. + +2011-11-12 Anthony Green <green@moxielogic.com> + + * Makefile.am (AM_CCASFLAGS): Add -g option to build assembly + files with debug info. + * Makefile.in: Rebuilt. + +2011-11-12 Jasper Lievisse Adriaanse <jasper@openbsd.org> + + * README: Update list of supported OpenBSD systems. + +2011-11-12 Anthony Green <green@moxielogic.com> + + * libtool-version: Update. + * Makefile.am (nodist_libffi_la_SOURCES): Add src/debug.c if + FFI_DEBUG. + (libffi_la_SOURCES): Remove src/debug.c + (EXTRA_DIST): Add src/debug.c + * Makefile.in: Rebuilt. + * README: Update for 3.0.11. + +2011-11-10 Richard Henderson <rth@redhat.com> + + * configure.ac (GCC_AS_CFI_PSEUDO_OP): Use it instead of inline check. + * configure, aclocal.m4: Rebuild. + +2011-09-04 Iain Sandoe <iains@gcc.gnu.org> + + PR libffi/49594 + * src/powerpc/darwin_closure.S (stubs): Make the stub binding + helper reference track the architecture pointer size. + +2011-08-25 Andrew Haley <aph@redhat.com> + + * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Remove hard-coded assembly + instructions. + * src/arm/sysv.S (ffi_arm_trampoline): Put them here instead. + +2011-07-11 Andrew Haley <aph@redhat.com> + + * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Clear icache. + +2011-06-29 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * testsuite/libffi.call/cls_double_va.c: Move PR number to comment. + * testsuite/libffi.call/cls_longdouble_va.c: Likewise. + +2011-06-29 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + PR libffi/46660 + * testsuite/libffi.call/cls_double_va.c: xfail dg-output on + mips-sgi-irix6*. + * testsuite/libffi.call/cls_longdouble_va.c: Likewise. + +2011-06-14 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * testsuite/libffi.call/huge_struct.c (test_large_fn): Use PRIu8, + PRId8 instead of %hhu, %hhd. + * testsuite/libffi.call/ffitest.h [__alpha__ && __osf__] (PRId8, + PRIu8): Define. + [__sgi__] (PRId8, PRIu8): Define. + +2011-04-29 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * src/alpha/osf.S (UA_SI, FDE_ENCODING, FDE_ENCODE, FDE_ARANGE): + Define. + Use them to handle ELF vs. ECOFF differences. + [__osf__] (_GLOBAL__F_ffi_call_osf): Define. + +2011-03-30 Timothy Wall <twall@users.sf.net> + + * src/powerpc/darwin.S: Fix unknown FDE encoding. + * src/powerpc/darwin_closure.S: ditto. + +2011-02-25 Anthony Green <green@moxielogic.com> + + * src/powerpc/ffi.c (ffi_prep_closure_loc): Allow for more + 32-bit ABIs. + +2011-02-15 Anthony Green <green@moxielogic.com> + + * m4/ax_cc_maxopt.m4: Don't -malign-double or use -ffast-math. + * configure: Rebuilt. + +2011-02-13 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * configure: Regenerate. + +2011-02-13 Anthony Green <green@moxielogic.com> + + * include/ffi_common.h (UNLIKELY, LIKELY): Define. + * src/x86/ffi64.c (UNLIKELY, LIKELY): Remove definition. + * src/prep_cif.c (UNLIKELY, LIKELY): Remove definition. + + * src/prep_cif.c (initialize_aggregate): Convert assertion into + FFI_BAD_TYPEDEF return. Initialize arg size and alignment to 0. + + * src/pa/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test, + just return FFI_BAD_ABI when things are wrong. + * src/arm/ffi.c (ffi_prep_closure_loc): Ditto. + * src/powerpc/ffi.c (ffi_prep_closure_loc): Ditto. + * src/mips/ffi.c (ffi_prep_closure_loc): Ditto. + * src/ia64/ffi.c (ffi_prep_closure_loc): Ditto. + * src/avr32/ffi.c (ffi_prep_closure_loc): Ditto. + +2011-02-11 Anthony Green <green@moxielogic.com> + + * src/sparc/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test, + just return FFI_BAD_ABI when things are wrong. + +2012-02-11 Eric Botcazou <ebotcazou@adacore.com> + + * src/sparc/v9.S (STACKFRAME): Bump to 176. + +2011-02-09 Stuart Shelton <srcshelton@gmail.com> + + http://bugs.gentoo.org/show_bug.cgi?id=286911 + * src/mips/ffitarget.h: Clean up error messages. + * src/java_raw_api.c (ffi_java_translate_args): Cast raw arg to + ffi_raw*. + * include/ffi.h.in: Add pragma for SGI compiler. + +2011-02-09 Anthony Green <green@moxielogic.com> + + * configure.ac: Add powerpc64-*-darwin* support. + +2011-02-09 Anthony Green <green@moxielogic.com> + + * README: Mention Interix. + +2011-02-09 Jonathan Callen <abcd@gentoo.org> + + * configure.ac: Add Interix to win32/cygwin/mingw case. + * configure: Ditto. + * src/closures.c: Treat Interix like Cygwin, instead of as a + generic win32. + +2011-02-09 Anthony Green <green@moxielogic.com> + + * testsuite/libffi.call/err_bad_typedef.c: Remove xfail. + * testsuite/libffi.call/err_bad_abi.c: Remove xfail. + * src/x86/ffi64.c (UNLIKELY, LIKELY): Define. + (ffi_prep_closure_loc): Check for bad ABI. + * src/prep_cif.c (UNLIKELY, LIKELY): Define. + (initialize_aggregate): Check for bad types. + +2011-02-09 Landon Fuller <landonf@plausible.coop> + + * Makefile.am (EXTRA_DIST): Add build-ios.sh, src/arm/gentramp.sh, + src/arm/trampoline.S. + (nodist_libffi_la_SOURCES): Add src/arc/trampoline.S. + * configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Define. + * src/arm/ffi.c (ffi_trampoline_table) + (ffi_closure_trampoline_table_page, ffi_trampoline_table_entry) + (FFI_TRAMPOLINE_CODELOC_CONFIG, FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) + (FFI_TRAMPOLINE_COUNT, ffi_trampoline_lock, ffi_trampoline_tables) + (ffi_trampoline_table_alloc, ffi_closure_alloc, ffi_closure_free): + Define for FFI_EXEC_TRAMPOLINE_TABLE case (iOS). + (ffi_prep_closure_loc): Handl FFI_EXEC_TRAMPOLINE_TABLE case + separately. + * src/arm/sysv.S: Handle Apple iOS host. + * src/closures.c: Handle FFI_EXEC_TRAMPOLINE_TABLE case. + * build-ios.sh: New file. + * fficonfig.h.in, configure, Makefile.in: Rebuilt. + * README: Mention ARM iOS. + +2011-02-08 Oren Held <orenhe@il.ibm.com> + + * src/dlmalloc.c (_STRUCT_MALLINFO): Define in order to avoid + redefinition of mallinfo on HP-UX. + +2011-02-08 Ginn Chen <ginn.chen@oracle.com> + + * src/sparc/ffi.c (ffi_call): Make compatible with Solaris Studio + aggregate return ABI. Flush cache. + (ffi_prep_closure_loc): Flush cache. + +2011-02-11 Anthony Green <green@moxielogic.com> + + From Tom Honermann <tom.honermann@oracle.com>: + * src/powerpc/aix.S (ffi_call_AIX): Support for xlc toolchain on + AIX. Declare .ffi_prep_args. Insert nops after branch + instructions so that the AIX linker can insert TOC reload + instructions. + * src/powerpc/aix_closure.S: Declare .ffi_closure_helper_DARWIN. + +2011-02-08 Ed <ed@kdtc.net> + + * src/powerpc/asm.h: Fix grammar nit in comment. + +2011-02-08 Uli Link <ul.mcamafia@linkitup.de> + + * include/ffi.h.in (FFI_64_BIT_MAX): Define and use. + +2011-02-09 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + PR libffi/46661 + * testsuite/libffi.call/cls_pointer.c (main): Cast void * to + uintptr_t first. + * testsuite/libffi.call/cls_pointer_stack.c (main): Likewise. + +2011-02-08 Rafael Avila de Espindola <respindola@mozilla.com> + + * configure.ac: Fix x86 test for pc related relocs. + * configure: Rebuilt. + +2011-02-07 Joel Sherrill <joel.sherrill@oarcorp.com> + + * libffi/src/m68k/ffi.c: Add RTEMS support for cache flushing. + Handle case when CPU variant does not have long double support. + * libffi/src/m68k/sysv.S: Add support for mc68000, Coldfire, + and cores with soft floating point. + +2011-02-07 Joel Sherrill <joel.sherrill@oarcorp.com> + + * configure.ac: Add mips*-*-rtems* support. + * configure: Regenerate. + * src/mips/ffitarget.h: Ensure needed constants are available + for targets which do not have sgidefs.h. + +2011-01-26 Dave Korn <dave.korn.cygwin@gmail.com> + + PR target/40125 + * configure.ac (AM_LTLDFLAGS): Add -bindir option for windows DLLs. + * configure: Regenerate. + +2010-12-18 Iain Sandoe <iains@gcc.gnu.org> + + PR libffi/29152 + PR libffi/42378 + * src/powerpc/darwin_closure.S: Provide Darwin64 implementation, + update comments. + * src/powerpc/ffitarget.h (POWERPC_DARWIN64): New, + (FFI_TRAMPOLINE_SIZE): Update for Darwin64. + * src/powerpc/darwin.S: Provide Darwin64 implementation, + update comments. + * src/powerpc/ffi_darwin.c: Likewise. + +2010-12-06 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * configure.ac (libffi_cv_as_ascii_pseudo_op): Use double + backslashes. + (libffi_cv_as_string_pseudo_op): Likewise. + * configure: Regenerate. + +2010-12-03 Chung-Lin Tang <cltang@codesourcery.com> + + * src/arm/sysv.S (ffi_closure_SYSV): Add UNWIND to .pad directive. + (ffi_closure_VFP): Same. + (ffi_call_VFP): Move down to before ffi_closure_VFP. Add '.fpu vfp' + directive. + +2010-12-01 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * testsuite/libffi.call/ffitest.h [__sgi] (PRId64, PRIu64): Define. + (PRIuPTR): Define. + +2010-11-29 Richard Henderson <rth@redhat.com> + Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * src/x86/sysv.S (FDE_ENCODING, FDE_ENCODE): Define. + (.eh_frame): Use FDE_ENCODING. + (.LASFDE1, .LASFDE2, LASFDE3): Simplify with FDE_ENCODE. + +2010-11-22 Jacek Caban <jacek@codeweavers.com> + + * configure.ac: Check for symbol underscores on mingw-w64. + * configure: Rebuilt. + * src/x86/win64.S: Correctly access extern symbols in respect to + underscores. + +2010-11-15 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * testsuite/lib/libffi-dg.exp: Rename ... + * testsuite/lib/libffi.exp: ... to this. + * libffi/testsuite/libffi.call/call.exp: Don't load libffi-dg.exp. + * libffi/testsuite/libffi.special/special.exp: Likewise. + +2010-10-28 Chung-Lin Tang <cltang@codesourcery.com> + + * src/arm/ffi.c (ffi_prep_args): Add VFP register argument handling + code, new parameter, and return value. Update comments. + (ffi_prep_cif_machdep): Add case for VFP struct return values. Add + call to layout_vfp_args(). + (ffi_call_SYSV): Update declaration. + (ffi_call_VFP): New declaration. + (ffi_call): Add VFP struct return conditions. Call ffi_call_VFP() + when ABI is FFI_VFP. + (ffi_closure_VFP): New declaration. + (ffi_closure_SYSV_inner): Add new vfp_args parameter, update call to + ffi_prep_incoming_args_SYSV(). + (ffi_prep_incoming_args_SYSV): Update parameters. Add VFP argument + case handling. + (ffi_prep_closure_loc): Pass ffi_closure_VFP to trampoline + construction under VFP hard-float. + (rec_vfp_type_p): New function. + (vfp_type_p): Same. + (place_vfp_arg): Same. + (layout_vfp_args): Same. + * src/arm/ffitarget.h (ffi_abi): Add FFI_VFP. Define FFI_DEFAULT_ABI + based on __ARM_PCS_VFP. + (FFI_EXTRA_CIF_FIELDS): Define for adding VFP hard-float specific + fields. + (FFI_TYPE_STRUCT_VFP_FLOAT): Define internally used type code. + (FFI_TYPE_STRUCT_VFP_DOUBLE): Same. + * src/arm/sysv.S (ffi_call_SYSV): Change call of ffi_prep_args() to + direct call. Move function pointer load upwards. + (ffi_call_VFP): New function. + (ffi_closure_VFP): Same. + + * testsuite/lib/libffi-dg.exp (check-flags): New function. + (dg-skip-if): New function. + * testsuite/libffi.call/cls_double_va.c: Skip if target is arm*-*-* + and compiler options include -mfloat-abi=hard. + * testsuite/libffi.call/cls_longdouble_va.c: Same. + +2010-10-01 Jakub Jelinek <jakub@redhat.com> + + PR libffi/45677 + * src/x86/ffi64.c (ffi_prep_cif_machdep): Ensure cif->bytes is + a multiple of 8. + * testsuite/libffi.call/many2.c: New test. + +2010-08-20 Mark Wielaard <mjw@redhat.com> + + * src/closures.c (open_temp_exec_file_mnt): Check if getmntent_r + returns NULL. + +2010-08-09 Andreas Tobler <andreast@fgznet.ch> + + * configure.ac: Add target powerpc64-*-freebsd*. + * configure: Regenerate. + * testsuite/libffi.call/cls_align_longdouble_split.c: Pass + -mlong-double-128 only to linux targets. + * testsuite/libffi.call/cls_align_longdouble_split2.c: Likewise. + * testsuite/libffi.call/cls_longdouble.c: Likewise. + * testsuite/libffi.call/huge_struct.c: Likewise. + +2010-08-05 Dan Witte <dwitte@mozilla.com> + + * Makefile.am: Pass FFI_DEBUG define to msvcc.sh for linking to the + debug CRT when --enable-debug is given. + * configure.ac: Define it. + * msvcc.sh: Translate -g and -DFFI_DEBUG appropriately. + +2010-08-04 Dan Witte <dwitte@mozilla.com> + + * src/x86/ffitarget.h: Add X86_ANY define for all x86/x86_64 + platforms. + * src/x86/ffi.c: Remove redundant ifdef checks. + * src/prep_cif.c: Push stack space computation into src/x86/ffi.c + for X86_ANY so return value space doesn't get added twice. + +2010-08-03 Neil Rashbrooke <neil@parkwaycc.co.uk> + + * msvcc.sh: Don't pass -safeseh to ml64 because behavior is buggy. + +2010-07-22 Dan Witte <dwitte@mozilla.com> + + * src/*/ffitarget.h: Make FFI_LAST_ABI one past the last valid ABI. + * src/prep_cif.c: Fix ABI assertion. + * src/cris/ffi.c: Ditto. + +2010-07-10 Evan Phoenix <evan@fallingsnow.net> + + * src/closures.c (selinux_enabled_check): Fix strncmp usage bug. + +2010-07-07 Dan Horák <dan@danny.cz> + + * include/ffi.h.in: Protect #define with #ifndef. + * src/powerpc/ffitarget.h: Ditto. + * src/s390/ffitarget.h: Ditto. + * src/sparc/ffitarget.h: Ditto. + +2010-07-07 Neil Roberts <neil@linux.intel.com> + + * src/x86/sysv.S (ffi_call_SYSV): Align the stack pointer to + 16-bytes. + +2010-07-02 Jakub Jelinek <jakub@redhat.com> + + * Makefile.am (AM_MAKEFLAGS): Pass also mandir to submakes. + * Makefile.in: Regenerated. + +2010-05-19 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * configure.ac (libffi_cv_as_x86_pcrel): Check for illegal in as + output, too. + (libffi_cv_as_ascii_pseudo_op): Check for .ascii. + (libffi_cv_as_string_pseudo_op): Check for .string. + * configure: Regenerate. + * fficonfig.h.in: Regenerate. + * src/x86/sysv.S (.eh_frame): Use .ascii, .string or error. + +2010-05-11 Dan Witte <dwitte@mozilla.com> + + * doc/libffi.tex: Document previous change. + +2010-05-11 Makoto Kato <m_kato@ga2.so-net.ne.jp> + + * src/x86/ffi.c (ffi_call): Don't copy structs passed by value. + +2010-05-05 Michael Kohler <michaelkohler@live.com> + + * src/dlmalloc.c (dlfree): Fix spelling. + * src/ia64/ffi.c (ffi_prep_cif_machdep): Ditto. + * configure.ac: Ditto. + * configure: Rebuilt. + +2010-04-13 Dan Witte <dwitte@mozilla.com> + + * msvcc.sh: Build with -W3 instead of -Wall. + * src/powerpc/ffi_darwin.c: Remove build warnings. + * src/x86/ffi.c: Ditto. + * src/x86/ffitarget.h: Ditto. + +2010-04-12 Dan Witte <dwitte@mozilla.com> + Walter Meinl <wuno@lsvw.de> + + * configure.ac: Add OS/2 support. + * configure: Rebuilt. + * src/closures.c: Ditto. + * src/dlmalloc.c: Ditto. + * src/x86/win32.S: Ditto. + +2010-04-07 Jakub Jelinek <jakub@redhat.com> + + * testsuite/libffi.call/err_bad_abi.c: Remove unused args variable. + +2010-04-02 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * Makefile.in: Regenerate. + * aclocal.m4: Regenerate. + * include/Makefile.in: Regenerate. + * man/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2010-03-30 Dan Witte <dwitte@mozilla.com> + + * msvcc.sh: Disable build warnings. + * README (tested): Clarify windows build procedure. + +2010-03-15 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * configure.ac (libffi_cv_as_x86_64_unwind_section_type): New test. + * configure: Regenerate. + * fficonfig.h.in: Regenerate. + * libffi/src/x86/unix64.S (.eh_frame) + [HAVE_AS_X86_64_UNWIND_SECTION_TYPE]: Use @unwind section type. + +2010-03-14 Matthias Klose <doko@ubuntu.com> + + * src/x86/ffi64.c: Fix typo in comment. + * src/x86/ffi.c: Use /* ... */ comment style. + +2010-02-24 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * doc/libffi.texi (The Closure API): Fix typo. + * doc/libffi.info: Remove. + +2010-02-15 Matthias Klose <doko@ubuntu.com> + + * src/arm/sysv.S (__ARM_ARCH__): Define for processor + __ARM_ARCH_7EM__. + +2010-01-15 Anthony Green <green@redhat.com> + + * README: Add notes on building with Microsoft Visual C++. + +2010-01-15 Daniel Witte <dwitte@mozilla.com> + + * msvcc.sh: New file. + + * src/x86/win32.S: Port assembly routines to MSVC and #ifdef. + * src/x86/ffi.c: Tweak function declaration and remove excess + parens. + * include/ffi.h.in: Add __declspec(align(8)) to typedef struct + ffi_closure. + + * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new + function ffi_call_win32 on X86_WIN32. + * src/x86/win32.S (ffi_call_SYSV): Rename to ffi_call_win32. + (ffi_call_STDCALL): Remove. + + * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code + to ffi_prep_cif_machdep for x86. + * src/x86/ffi.c (ffi_prep_cif_machdep): To here. + +2010-01-15 Oliver Kiddle <okiddle@yahoo.co.uk> + + * src/x86/ffitarget.h (ffi_abi): Check for __i386 and __amd64 for + Sun Studio compiler compatibility. + +2010-01-12 Conrad Irwin <conrad.irwin@gmail.com> + + * doc/libffi.texi: Add closure example. + +2010-01-07 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + PR libffi/40701 + * testsuite/libffi.call/ffitest.h [__alpha__ && __osf__] (PRIdLL, + PRIuLL, PRId64, PRIu64, PRIuPTR): Define. + * testsuite/libffi.call/cls_align_sint64.c: Add -Wno-format on + alpha*-dec-osf*. + * testsuite/libffi.call/cls_align_uint64.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/return_ll1.c: Likewise. + * testsuite/libffi.call/stret_medium2.c: Likewise. + * testsuite/libffi.special/ffitestcxx.h (allocate_mmap): Cast + MAP_FAILED to char *. + +2010-01-06 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * src/mips/n32.S: Use .abicalls and .eh_frame with __GNUC__. + +2009-12-31 Anthony Green <green@redhat.com> + + * README: Update for libffi 3.0.9. + +2009-12-27 Matthias Klose <doko@ubuntu.com> + + * configure.ac (HAVE_LONG_DOUBLE): Define for mips when + appropriate. + * configure: Rebuilt. + +2009-12-26 Anthony Green <green@redhat.com> + + * testsuite/libffi.call/cls_longdouble_va.c: Mark as xfail for + avr32*-*-*. + * testsuite/libffi.call/cls_double_va.c: Ditto. + +2009-12-26 Andreas Tobler <a.tobler@schweiz.org> + + * testsuite/libffi.call/ffitest.h: Conditionally include stdint.h + and inttypes.h. + * testsuite/libffi.special/unwindtest.cc: Ditto. + +2009-12-26 Andreas Tobler <a.tobler@schweiz.org> + + * configure.ac: Add amd64-*-openbsd*. + * configure: Rebuilt. + * testsuite/lib/libffi-dg.exp (libffi_target_compile): Link + openbsd programs with -lpthread. + +2009-12-26 Anthony Green <green@redhat.com> + + * testsuite/libffi.call/cls_double_va.c, + testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c: Remove xfail for + mips*-*-* and arm*-*-*. + * testsuite/libffi.call/cls_align_longdouble_split.c, + testsuite/libffi.call/cls_align_longdouble_split2.c, + testsuite/libffi.call/stret_medium2.c, + testsuite/libffi.call/stret_medium.c, + testsuite/libffi.call/stret_large.c, + testsuite/libffi.call/stret_large2.c: Remove xfail for arm*-*-*. + +2009-12-31 Kay Tietz <ktietz70@googlemail.com> + + * testsuite/libffi.call/ffitest.h, + testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRuLL): Fix + definitions. + +2009-12-31 Carlo Bramini <carlo.bramix@libero.it> + + * configure.ac (AM_LTLDFLAGS): Define for windows hosts. + * Makefile.am (libffi_la_LDFLAGS): Add AM_LTLDFLAGS. + * configure: Rebuilt. + * Makefile.in: Rebuilt. + +2009-12-31 Anthony Green <green@redhat.com> + Blake Chaffin. + + * testsuite/libffi.call/huge_struct.c: New test case from Blake + Chaffin @ Apple. + +2009-12-28 David Edelsohn <edelsohn@gnu.org> + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Copy abi and nargs to + local variables. + (aix_adjust_aggregate_sizes): New function. + (ffi_prep_cif_machdep): Call it. + +2009-12-26 Andreas Tobler <a.tobler@schweiz.org> + + * configure.ac: Define FFI_MMAP_EXEC_WRIT for the given targets. + * configure: Regenerate. + * fficonfig.h.in: Likewise. + * src/closures.c: Remove the FFI_MMAP_EXEC_WRIT definition for + Solaris/x86. + +2009-12-26 Andreas Schwab <schwab@linux-m68k.org> + + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Advance intarg_count + when a float arguments is passed in memory. + (ffi_closure_helper_SYSV): Mark general registers as used up when + a 64bit or soft-float long double argument is passed in memory. + +2009-12-25 Matthias Klose <doko@ubuntu.com> + + * man/ffi_call.3: Fix #include in examples. + * doc/libffi.texi: Add dircategory. + +2009-12-25 Frank Everdij <f.p.x.everdij@tudelft.nl> + + * include/ffi.h.in: Placed '__GNUC__' ifdef around + '__attribute__((aligned(8)))' in ffi_closure, fixes compile for + IRIX MIPSPro c99. + * include/ffi_common.h: Added '__sgi' define to non + '__attribute__((__mode__()))' integer typedefs. + * src/mips/ffi.c (ffi_call, ffi_closure_mips_inner_O32, + ffi_closure_mips_inner_N32): Added 'defined(_MIPSEB)' to BE check. + (ffi_closure_mips_inner_O32, ffi_closure_mips_inner_N32): Added + FFI_LONGDOUBLE support and alignment(N32 only). + * src/mips/ffitarget.h: Corrected '#include <sgidefs.h>' for IRIX and + fixed non '__attribute__((__mode__()))' integer typedefs. + * src/mips/n32.S: Put '#ifdef linux' around '.abicalls' and '.eh_frame' + since they are Linux/GNU Assembler specific. + +2009-12-25 Bradley Smith <brad@brad-smith.co.uk> + + * configure.ac, Makefile.am, src/avr32/ffi.c, + src/avr32/ffitarget.h, + src/avr32/sysv.S: Add AVR32 port. + * configure, Makefile.in: Rebuilt. + +2009-12-21 Andreas Tobler <a.tobler@schweiz.org> + + * configure.ac: Make i?86 build on FreeBSD and OpenBSD. + * configure: Regenerate. + +2009-12-15 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> + + * testsuite/libffi.call/ffitest.h: Define PRIuPTR on PA HP-UX. + +2009-12-13 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> + + * src/pa/ffi.c (ffi_closure_inner_pa32): Handle FFI_TYPE_LONGDOUBLE + type on HP-UX. + +2012-02-13 Kai Tietz <ktietz@redhat.com> + + PR libffi/52221 + * src/x86/ffi.c (ffi_prep_raw_closure_loc): Add thiscall + support for X86_WIN32. + (FFI_INIT_TRAMPOLINE_THISCALL): Fix displacement. + +2009-12-11 Eric Botcazou <ebotcazou@adacore.com> + + * src/sparc/ffi.c (ffi_closure_sparc_inner_v9): Properly align 'long + double' arguments. + +2009-12-11 Eric Botcazou <ebotcazou@adacore.com> + + * testsuite/libffi.call/ffitest.h: Define PRIuPTR on Solaris < 10. + +2009-12-10 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + PR libffi/40700 + * src/closures.c [X86_64 && __sun__ && __svr4__] + (FFI_MMAP_EXEC_WRIT): Define. + +2009-12-08 David Daney <ddaney@caviumnetworks.com> + + * testsuite/libffi.call/stret_medium.c: Remove xfail for mips*-*-* + * testsuite/libffi.call/cls_align_longdouble_split2.c: Same. + * testsuite/libffi.call/stret_large.c: Same. + * testsuite/libffi.call/cls_align_longdouble_split.c: Same. + * testsuite/libffi.call/stret_large2.c: Same. + * testsuite/libffi.call/stret_medium2.c: Same. + +2009-12-07 David Edelsohn <edelsohn@gnu.org> + + * src/powerpc/aix_closure.S (libffi_closure_ASM): Fix tablejump + typo. + +2009-12-05 David Edelsohn <edelsohn@gnu.org> + + * src/powerpc/aix.S: Update AIX32 code to be consistent with AIX64 + code. + * src/powerpc/aix_closure.S: Same. + +2009-12-05 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * Makefile.in: Regenerate. + * configure: Regenerate. + * include/Makefile.in: Regenerate. + * man/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2009-12-04 David Edelsohn <edelsohn@gnu.org> + + * src/powerpc/aix_closure.S: Reorganize 64-bit code to match + linux64_closure.S. + +2009-12-04 Uros Bizjak <ubizjak@gmail.com> + + PR libffi/41908 + * src/x86/ffi64.c (classify_argument): Update from + gcc/config/i386/i386.c. + (ffi_closure_unix64_inner): Do not use the address of two consecutive + SSE registers directly. + * testsuite/libffi.call/cls_dbls_struct.c (main): Remove xfail + for x86_64 linux targets. + +2009-12-04 David Edelsohn <edelsohn@gnu.org> + + * src/powerpc/ffi_darwin.c (ffi_closure_helper_DARWIN): Increment + pfr for long double split between fpr13 and stack. + +2009-12-03 David Edelsohn <edelsohn@gnu.org> + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Increment next_arg and + fparg_count twice for long double. + +2009-12-03 David Edelsohn <edelsohn@gnu.org> + + PR libffi/42243 + * src/powerpc/ffi_darwin.c (ffi_prep_args): Remove extra parentheses. + +2009-12-03 Uros Bizjak <ubizjak@gmail.com> + + * testsuite/libffi.call/cls_longdouble_va.c (main): Fix format string. + Remove xfails for x86 linux targets. + +2009-12-02 David Edelsohn <edelsohn@gnu.org> + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Fix typo in INT64 + case. + +2009-12-01 David Edelsohn <edelsohn@gnu.org> + + * src/powerpc/aix.S (ffi_call_AIX): Convert to more standard + register usage. Call ffi_prep_args directly. Add long double + return value support. + * src/powerpc/ffi_darwin.c (ffi_prep_args): Double arg increment + applies to FFI_TYPE_DOUBLE. Correct fpr_base increment typo. + Separate FFI_TYPE_SINT32 and FFI_TYPE_UINT32 cases. + (ffi_prep_cif_machdep): Only 16 byte stack alignment in 64 bit + mode. + (ffi_closure_helper_DARWIN): Remove nf and ng counters. Move temp + into case. + * src/powerpc/aix_closure.S: Maintain 16 byte stack alignment. + Allocate result area between params and FPRs. + +2009-11-30 David Edelsohn <edelsohn@gnu.org> + + PR target/35484 + * src/powerpc/ffitarget.h (POWERPC64): Define for PPC64 Linux and + AIX64. + * src/powerpc/aix.S: Implement AIX64 version. + * src/powerpc/aix_closure.S: Implement AIX64 version. + (ffi_closure_ASM): Use extsb, lha and displament addresses. + * src/powerpc/ffi_darwin.c (ffi_prep_args): Implement AIX64 + support. + (ffi_prep_cif_machdep): Same. + (ffi_call): Same. + (ffi_closure_helper_DARWIN): Same. + +2009-11-02 Andreas Tobler <a.tobler@schweiz.org> + + PR libffi/41908 + * testsuite/libffi.call/testclosure.c: New test. + +2009-09-28 Kai Tietz <kai.tietz@onevision.com> + + * src/x86/win64.S (_ffi_call_win64 stack): Remove for gnu + assembly version use of ___chkstk. + +2009-09-23 Matthias Klose <doko@ubuntu.com> + + PR libffi/40242, PR libffi/41443 + * src/arm/sysv.S (__ARM_ARCH__): Define for processors + __ARM_ARCH_6T2__, __ARM_ARCH_6M__, __ARM_ARCH_7__, + __ARM_ARCH_7A__, __ARM_ARCH_7R__, __ARM_ARCH_7M__. + Change the conditionals to __SOFTFP__ || __ARM_EABI__ + for -mfloat-abi=softfp to work. + +2009-09-17 Loren J. Rittle <ljrittle@acm.org> + + PR testsuite/32843 (strikes again) + * src/x86/ffi.c (ffi_prep_cif_machdep): Add X86_FREEBSD to + enable proper extension on char and short. + +2009-09-15 David Daney <ddaney@caviumnetworks.com> + + * src/java_raw_api.c (ffi_java_raw_to_rvalue): Remove special + handling for FFI_TYPE_POINTER. + * src/mips/ffitarget.h (FFI_TYPE_STRUCT_D_SOFT, + FFI_TYPE_STRUCT_F_SOFT, FFI_TYPE_STRUCT_DD_SOFT, + FFI_TYPE_STRUCT_FF_SOFT, FFI_TYPE_STRUCT_FD_SOFT, + FFI_TYPE_STRUCT_DF_SOFT, FFI_TYPE_STRUCT_SOFT): New defines. + (FFI_N32_SOFT_FLOAT, FFI_N64_SOFT_FLOAT): New ffi_abi enumerations. + (enum ffi_abi): Set FFI_DEFAULT_ABI for soft-float. + * src/mips/n32.S (ffi_call_N32): Add handling for soft-float + structure and pointer returns. + (ffi_closure_N32): Add handling for pointer returns. + * src/mips/ffi.c (ffi_prep_args, calc_n32_struct_flags, + calc_n32_return_struct_flags): Handle soft-float. + (ffi_prep_cif_machdep): Handle soft-float, fix pointer handling. + (ffi_call_N32): Declare proper argument types. + (ffi_call, copy_struct_N32, ffi_closure_mips_inner_N32): Handle + soft-float. + +2009-08-24 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * configure.ac (AC_PREREQ): Bump to 2.64. + +2009-08-22 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * Makefile.am (install-html, install-pdf): Remove. + * Makefile.in: Regenerate. + + * Makefile.in: Regenerate. + * aclocal.m4: Regenerate. + * configure: Regenerate. + * fficonfig.h.in: Regenerate. + * include/Makefile.in: Regenerate. + * man/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2011-08-22 Jasper Lievisse Adriaanse <jasper@openbsd.org> + + * configure.ac: Add OpenBSD/hppa and OpenBSD/powerpc support. + * configure: Rebuilt. + +2009-07-30 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * configure.ac (_AC_ARG_VAR_PRECIOUS): Use m4_rename_force. + +2009-07-24 Dave Korn <dave.korn.cygwin@gmail.com> + + PR libffi/40807 + * src/x86/ffi.c (ffi_prep_cif_machdep): Also use sign/zero-extending + return types for X86_WIN32. + * src/x86/win32.S (_ffi_call_SYSV): Handle omitted return types. + (_ffi_call_STDCALL, _ffi_closure_SYSV, _ffi_closure_raw_SYSV, + _ffi_closure_STDCALL): Likewise. + + * src/closures.c (is_selinux_enabled): Define to const 0 for Cygwin. + (dlmmap, dlmunmap): Also use these functions on Cygwin. + +2009-07-11 Richard Sandiford <rdsandiford@googlemail.com> + + PR testsuite/40699 + PR testsuite/40707 + PR testsuite/40709 + * testsuite/lib/libffi-dg.exp: Revert 2009-07-02, 2009-07-01 and + 2009-06-30 commits. + +2009-07-01 Richard Sandiford <r.sandiford@uk.ibm.com> + + * testsuite/lib/libffi-dg.exp (libffi-init): Set ld_library_path + to "" before adding paths. (This reinstates an assignment that + was removed by my 2009-06-30 commit, but changes the initial + value from "." to "".) + +2009-07-01 H.J. Lu <hongjiu.lu@intel.com> + + PR testsuite/40601 + * testsuite/lib/libffi-dg.exp (libffi-init): Properly set + gccdir. Adjust ld_library_path for gcc only if gccdir isn't + empty. + +2009-06-30 Richard Sandiford <r.sandiford@uk.ibm.com> + + * testsuite/lib/libffi-dg.exp (libffi-init): Don't add "." + to ld_library_path. Use add_path. Add just find_libgcc_s + to ld_library_path, not every libgcc multilib directory. + +2009-06-16 Wim Lewis <wiml@hhhh.org> + + * src/powerpc/ffi.c: Avoid clobbering cr3 and cr4, which are + supposed to be callee-saved. + * src/powerpc/sysv.S (small_struct_return_value): Fix overrun of + return buffer for odd-size structs. + +2009-06-16 Andreas Tobler <a.tobler@schweiz.org> + + PR libffi/40444 + * testsuite/lib/libffi-dg.exp (libffi_target_compile): Add + allow_stack_execute for Darwin. + +2009-06-16 Andrew Haley <aph@redhat.com> + + * configure.ac (TARGETDIR): Add missing blank lines. + * configure: Regenerate. + +2009-06-16 Andrew Haley <aph@redhat.com> + + * testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/return_ll1.c, + testsuite/libffi.call/stret_medium2.c: Fix printf format + specifiers. + * testsuite/libffi.call/ffitest.h, + testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRIuLL): Define. + +2009-06-15 Andrew Haley <aph@redhat.com> + + * testsuite/libffi.call/err_bad_typedef.c: xfail everywhere. + * testsuite/libffi.call/err_bad_abi.c: Likewise. + +2009-06-12 Andrew Haley <aph@redhat.com> + + * Makefile.am: Remove info_TEXINFOS. + +2009-06-12 Andrew Haley <aph@redhat.com> + + * ChangeLog.libffi: testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/return_ll1.c, + testsuite/libffi.call/stret_medium2.c: Fix printf format + specifiers. + testsuite/libffi.special/unwindtest.cc: include stdint.h. + +2009-06-11 Timothy Wall <twall@users.sf.net> + + * Makefile.am, + configure.ac, + include/ffi.h.in, + include/ffi_common.h, + src/closures.c, + src/dlmalloc.c, + src/x86/ffi.c, + src/x86/ffitarget.h, + src/x86/win64.S (new), + README: Added win64 support (mingw or MSVC) + * Makefile.in, + include/Makefile.in, + man/Makefile.in, + testsuite/Makefile.in, + configure, + aclocal.m4: Regenerated + * ltcf-c.sh: properly escape cygwin/w32 path + * man/ffi_call.3: Clarify size requirements for return value. + * src/x86/ffi64.c: Fix filename in comment. + * src/x86/win32.S: Remove unused extern. + + * testsuite/libffi.call/closure_fn0.c, + testsuite/libffi.call/closure_fn1.c, + testsuite/libffi.call/closure_fn2.c, + testsuite/libffi.call/closure_fn3.c, + testsuite/libffi.call/closure_fn4.c, + testsuite/libffi.call/closure_fn5.c, + testsuite/libffi.call/closure_fn6.c, + testsuite/libffi.call/closure_stdcall.c, + testsuite/libffi.call/cls_12byte.c, + testsuite/libffi.call/cls_16byte.c, + testsuite/libffi.call/cls_18byte.c, + testsuite/libffi.call/cls_19byte.c, + testsuite/libffi.call/cls_1_1byte.c, + testsuite/libffi.call/cls_20byte.c, + testsuite/libffi.call/cls_20byte1.c, + testsuite/libffi.call/cls_24byte.c, + testsuite/libffi.call/cls_2byte.c, + testsuite/libffi.call/cls_3_1byte.c, + testsuite/libffi.call/cls_3byte1.c, + testsuite/libffi.call/cls_3byte2.c, + testsuite/libffi.call/cls_4_1byte.c, + testsuite/libffi.call/cls_4byte.c, + testsuite/libffi.call/cls_5_1_byte.c, + testsuite/libffi.call/cls_5byte.c, + testsuite/libffi.call/cls_64byte.c, + testsuite/libffi.call/cls_6_1_byte.c, + testsuite/libffi.call/cls_6byte.c, + testsuite/libffi.call/cls_7_1_byte.c, + testsuite/libffi.call/cls_7byte.c, + testsuite/libffi.call/cls_8byte.c, + testsuite/libffi.call/cls_9byte1.c, + testsuite/libffi.call/cls_9byte2.c, + testsuite/libffi.call/cls_align_double.c, + testsuite/libffi.call/cls_align_float.c, + testsuite/libffi.call/cls_align_longdouble.c, + testsuite/libffi.call/cls_align_longdouble_split.c, + testsuite/libffi.call/cls_align_longdouble_split2.c, + testsuite/libffi.call/cls_align_pointer.c, + testsuite/libffi.call/cls_align_sint16.c, + testsuite/libffi.call/cls_align_sint32.c, + testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_align_uint16.c, + testsuite/libffi.call/cls_align_uint32.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_dbls_struct.c, + testsuite/libffi.call/cls_double.c, + testsuite/libffi.call/cls_double_va.c, + testsuite/libffi.call/cls_float.c, + testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_multi_schar.c, + testsuite/libffi.call/cls_multi_sshort.c, + testsuite/libffi.call/cls_multi_sshortchar.c, + testsuite/libffi.call/cls_multi_uchar.c, + testsuite/libffi.call/cls_multi_ushort.c, + testsuite/libffi.call/cls_multi_ushortchar.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c, + testsuite/libffi.call/cls_schar.c, + testsuite/libffi.call/cls_sint.c, + testsuite/libffi.call/cls_sshort.c, + testsuite/libffi.call/cls_uchar.c, + testsuite/libffi.call/cls_uint.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/cls_ushort.c, + testsuite/libffi.call/err_bad_abi.c, + testsuite/libffi.call/err_bad_typedef.c, + testsuite/libffi.call/float2.c, + testsuite/libffi.call/huge_struct.c, + testsuite/libffi.call/nested_struct.c, + testsuite/libffi.call/nested_struct1.c, + testsuite/libffi.call/nested_struct10.c, + testsuite/libffi.call/nested_struct2.c, + testsuite/libffi.call/nested_struct3.c, + testsuite/libffi.call/nested_struct4.c, + testsuite/libffi.call/nested_struct5.c, + testsuite/libffi.call/nested_struct6.c, + testsuite/libffi.call/nested_struct7.c, + testsuite/libffi.call/nested_struct8.c, + testsuite/libffi.call/nested_struct9.c, + testsuite/libffi.call/problem1.c, + testsuite/libffi.call/return_ldl.c, + testsuite/libffi.call/return_ll1.c, + testsuite/libffi.call/stret_large.c, + testsuite/libffi.call/stret_large2.c, + testsuite/libffi.call/stret_medium.c, + testsuite/libffi.call/stret_medium2.c, + testsuite/libffi.special/unwindtest.cc: use ffi_closure_alloc instead + of checking for MMAP. Use intptr_t instead of long casts. + +2009-06-11 Kaz Kojima <kkojima@gcc.gnu.org> + + * testsuite/libffi.call/cls_longdouble_va.c: Add xfail sh*-*-linux-*. + * testsuite/libffi.call/err_bad_abi.c: Add xfail sh*-*-*. + * testsuite/libffi.call/err_bad_typedef.c: Likewise. + +2009-06-09 Andrew Haley <aph@redhat.com> + + * src/x86/freebsd.S: Add missing file. + +2009-06-08 Andrew Haley <aph@redhat.com> + + Import from libffi 3.0.8: + + * doc/libffi.texi: New file. + * doc/libffi.info: Likewise. + * doc/stamp-vti: Likewise. + * man/Makefile.am: New file. + * man/ffi_call.3: New file. + + * Makefile.am (EXTRA_DIST): Add src/x86/darwin64.S, + src/dlmalloc.c. + (nodist_libffi_la_SOURCES): Add X86_FREEBSD. + + * configure.ac: Bump version to 3.0.8. + parisc*-*-linux*: Add. + i386-*-freebsd* | i386-*-openbsd*: Add. + powerpc-*-beos*: Add. + AM_CONDITIONAL X86_FREEBSD: Add. + AC_CONFIG_FILES: Add man/Makefile. + + * include/ffi.h.in (FFI_FN): Change void (*)() to void (*)(void). + +2009-06-08 Andrew Haley <aph@redhat.com> + + * README: Import from libffi 3.0.8. + +2009-06-08 Andrew Haley <aph@redhat.com> + + * testsuite/libffi.call/err_bad_abi.c: Add xfails. + * testsuite/libffi.call/cls_longdouble_va.c: Add xfails. + * testsuite/libffi.call/cls_dbls_struct.c: Add xfail x86_64-*-linux-*. + * testsuite/libffi.call/err_bad_typedef.c: Add xfails. + + * testsuite/libffi.call/stret_medium2.c: Add __UNUSED__ to args. + * testsuite/libffi.call/stret_medium.c: Likewise. + * testsuite/libffi.call/stret_large2.c: Likewise. + * testsuite/libffi.call/stret_large.c: Likewise. + +2008-12-26 Timothy Wall <twall@users.sf.net> + + * testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_align_longdouble.c, + testsuite/libffi.call/cls_align_longdouble_split.c, + testsuite/libffi.call/cls_align_longdouble_split2.c: mark expected + failures on x86_64 cygwin/mingw. + +2008-12-22 Timothy Wall <twall@users.sf.net> + + * testsuite/libffi.call/closure_fn0.c, + testsuite/libffi.call/closure_fn1.c, + testsuite/libffi.call/closure_fn2.c, + testsuite/libffi.call/closure_fn3.c, + testsuite/libffi.call/closure_fn4.c, + testsuite/libffi.call/closure_fn5.c, + testsuite/libffi.call/closure_fn6.c, + testsuite/libffi.call/closure_loc_fn0.c, + testsuite/libffi.call/closure_stdcall.c, + testsuite/libffi.call/cls_align_pointer.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c: use portable cast from + pointer to integer (intptr_t). + * testsuite/libffi.call/cls_longdouble.c: disable for win64. + +2008-07-24 Anthony Green <green@redhat.com> + + * testsuite/libffi.call/cls_dbls_struct.c, + testsuite/libffi.call/cls_double_va.c, + testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c, + testsuite/libffi.call/err_bad_abi.c: Clean up failures from + compiler warnings. + +2008-03-04 Anthony Green <green@redhat.com> + Blake Chaffin + hos@tamanegi.org + + * testsuite/libffi.call/cls_align_longdouble_split2.c + testsuite/libffi.call/cls_align_longdouble_split.c + testsuite/libffi.call/cls_dbls_struct.c + testsuite/libffi.call/cls_double_va.c + testsuite/libffi.call/cls_longdouble.c + testsuite/libffi.call/cls_longdouble_va.c + testsuite/libffi.call/cls_pointer.c + testsuite/libffi.call/cls_pointer_stack.c + testsuite/libffi.call/err_bad_abi.c + testsuite/libffi.call/err_bad_typedef.c + testsuite/libffi.call/stret_large2.c + testsuite/libffi.call/stret_large.c + testsuite/libffi.call/stret_medium2.c + testsuite/libffi.call/stret_medium.c: New tests from Apple. + +2009-06-05 Andrew Haley <aph@redhat.com> + + * src/x86/ffitarget.h, src/x86/ffi.c: Merge stdcall changes from + libffi. + +2009-06-04 Andrew Haley <aph@redhat.com> + + * src/x86/ffitarget.h, src/x86/win32.S, src/x86/ffi.c: Back out + stdcall changes. + +2008-02-26 Anthony Green <green@redhat.com> + Thomas Heller <theller@ctypes.org> + + * src/x86/ffi.c (ffi_closure_SYSV_inner): Change C++ comment to C + comment. + +2008-02-03 Timothy Wall <twall@users.sf.net> + + * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL): Calculate jump return + offset based on code pointer, not data pointer. + +2008-01-31 Timothy Wall <twall@users.sf.net> + + * testsuite/libffi.call/closure_stdcall.c: Add test for stdcall + closures. + * src/x86/ffitarget.h: Increase size of trampoline for stdcall + closures. + * src/x86/win32.S: Add assembly for stdcall closure. + * src/x86/ffi.c: Initialize stdcall closure trampoline. + +2009-06-04 Andrew Haley <aph@redhat.com> + + * include/ffi.h.in: Change void (*)() to void (*)(void). + * src/x86/ffi.c: Likewise. + +2009-06-04 Andrew Haley <aph@redhat.com> + + * src/powerpc/ppc_closure.S: Insert licence header. + * src/powerpc/linux64_closure.S: Likewise. + * src/m68k/sysv.S: Likewise. + + * src/sh64/ffi.c: Change void (*)() to void (*)(void). + * src/powerpc/ffi.c: Likewise. + * src/powerpc/ffi_darwin.c: Likewise. + * src/m32r/ffi.c: Likewise. + * src/sh64/ffi.c: Likewise. + * src/x86/ffi64.c: Likewise. + * src/alpha/ffi.c: Likewise. + * src/alpha/osf.S: Likewise. + * src/frv/ffi.c: Likewise. + * src/s390/ffi.c: Likewise. + * src/pa/ffi.c: Likewise. + * src/pa/hpux32.S: Likewise. + * src/ia64/unix.S: Likewise. + * src/ia64/ffi.c: Likewise. + * src/sparc/ffi.c: Likewise. + * src/mips/ffi.c: Likewise. + * src/sh/ffi.c: Likewise. + +2008-02-15 David Daney <ddaney@avtrex.com> + + * src/mips/ffi.c (USE__BUILTIN___CLEAR_CACHE): + Define (conditionally), and use it to include cachectl.h. + (ffi_prep_closure_loc): Fix cache flushing. + * src/mips/ffitarget.h (_ABIN32, _ABI64, _ABIO32): Define. + +2009-06-04 Andrew Haley <aph@redhat.com> + + include/ffi.h.in, + src/arm/ffitarget.h, + src/arm/ffi.c, + src/arm/sysv.S, + src/powerpc/ffitarget.h, + src/closures.c, + src/sh64/ffitarget.h, + src/sh64/ffi.c, + src/sh64/sysv.S, + src/types.c, + src/x86/ffi64.c, + src/x86/ffitarget.h, + src/x86/win32.S, + src/x86/darwin.S, + src/x86/ffi.c, + src/x86/sysv.S, + src/x86/unix64.S, + src/alpha/ffitarget.h, + src/alpha/ffi.c, + src/alpha/osf.S, + src/m68k/ffitarget.h, + src/frv/ffitarget.h, + src/frv/ffi.c, + src/s390/ffitarget.h, + src/s390/sysv.S, + src/cris/ffitarget.h, + src/pa/linux.S, + src/pa/ffitarget.h, + src/pa/ffi.c, + src/raw_api.c, + src/ia64/ffitarget.h, + src/ia64/unix.S, + src/ia64/ffi.c, + src/ia64/ia64_flags.h, + src/java_raw_api.c, + src/debug.c, + src/sparc/v9.S, + src/sparc/ffitarget.h, + src/sparc/ffi.c, + src/sparc/v8.S, + src/mips/ffitarget.h, + src/mips/n32.S, + src/mips/o32.S, + src/mips/ffi.c, + src/prep_cif.c, + src/sh/ffitarget.h, + src/sh/ffi.c, + src/sh/sysv.S: Update license text. + +2009-05-22 Dave Korn <dave.korn.cygwin@gmail.com> + + * src/x86/win32.S (_ffi_closure_STDCALL): New function. + (.eh_frame): Add FDE for it. + +2009-05-22 Dave Korn <dave.korn.cygwin@gmail.com> + + * configure.ac: Also check if assembler supports pc-relative + relocs on X86_WIN32 targets. + * configure: Regenerate. + * src/x86/win32.S (ffi_prep_args): Declare extern, not global. + (_ffi_call_SYSV): Add missing function type symbol .def and + add EH markup labels. + (_ffi_call_STDCALL): Likewise. + (_ffi_closure_SYSV): Likewise. + (_ffi_closure_raw_SYSV): Likewise. + (.eh_frame): Add hand-crafted EH data. + +2009-04-09 Jakub Jelinek <jakub@redhat.com> + + * testsuite/lib/libffi-dg.exp: Change copyright header to refer to + version 3 of the GNU General Public License and to point readers + at the COPYING3 file and the FSF's license web page. + * testsuite/libffi.call/call.exp: Likewise. + * testsuite/libffi.special/special.exp: Likewise. + +2009-03-01 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * configure: Regenerate. + +2008-12-18 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + PR libffi/26048 + * configure.ac (HAVE_AS_X86_PCREL): New test. + * configure: Regenerate. + * fficonfig.h.in: Regenerate. + * src/x86/sysv.S [!FFI_NO_RAW_API]: Precalculate + RAW_CLOSURE_CIF_OFFSET, RAW_CLOSURE_FUN_OFFSET, + RAW_CLOSURE_USER_DATA_OFFSET for the Solaris 10/x86 assembler. + (.eh_frame): Only use SYMBOL-. iff HAVE_AS_X86_PCREL. + * src/x86/unix64.S (.Lstore_table): Move to .text section. + (.Lload_table): Likewise. + (.eh_frame): Only use SYMBOL-. iff HAVE_AS_X86_PCREL. + +2008-12-18 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * configure: Regenerate. + +2008-11-21 Eric Botcazou <ebotcazou@adacore.com> + + * src/sparc/ffi.c (ffi_prep_cif_machdep): Add support for + signed/unsigned int8/16 return values. + * src/sparc/v8.S (ffi_call_v8): Likewise. + (ffi_closure_v8): Likewise. + +2008-09-26 Peter O'Gorman <pogma@thewrittenword.com> + Steve Ellcey <sje@cup.hp.com> + + * configure: Regenerate for new libtool. + * Makefile.in: Ditto. + * include/Makefile.in: Ditto. + * aclocal.m4: Ditto. + +2008-08-25 Andreas Tobler <a.tobler@schweiz.org> + + * src/powerpc/ffitarget.h (ffi_abi): Add FFI_LINUX and + FFI_LINUX_SOFT_FLOAT to the POWERPC_FREEBSD enum. + Add note about flag bits used for FFI_SYSV_TYPE_SMALL_STRUCT. + Adjust copyright notice. + * src/powerpc/ffi.c: Add two new flags to indicate if we have one + register or two register to use for FFI_SYSV structs. + (ffi_prep_cif_machdep): Pass the right register flag introduced above. + (ffi_closure_helper_SYSV): Fix the return type for + FFI_SYSV_TYPE_SMALL_STRUCT. Comment. + Adjust copyright notice. + +2008-07-16 Kaz Kojima <kkojima@gcc.gnu.org> + + * src/sh/ffi.c (ffi_prep_closure_loc): Turn INSN into an unsigned + int. + +2008-06-17 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * configure: Regenerate. + * include/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2008-06-07 Joseph Myers <joseph@codesourcery.com> + + * configure.ac (parisc*-*-linux*, powerpc-*-sysv*, + powerpc-*-beos*): Remove. + * configure: Regenerate. + +2008-05-09 Julian Brown <julian@codesourcery.com> + + * Makefile.am (LTLDFLAGS): New. + (libffi_la_LDFLAGS): Use above. + * Makefile.in: Regenerate. + +2008-04-18 Paolo Bonzini <bonzini@gnu.org> + + PR bootstrap/35457 + * aclocal.m4: Regenerate. + * configure: Regenerate. + +2008-03-26 Kaz Kojima <kkojima@gcc.gnu.org> + + * src/sh/sysv.S: Add .note.GNU-stack on Linux. + * src/sh64/sysv.S: Likewise. + +2008-03-26 Daniel Jacobowitz <dan@debian.org> + + * src/arm/sysv.S: Fix ARM comment marker. + +2008-03-26 Jakub Jelinek <jakub@redhat.com> + + * src/alpha/osf.S: Add .note.GNU-stack on Linux. + * src/s390/sysv.S: Likewise. + * src/powerpc/ppc_closure.S: Likewise. + * src/powerpc/sysv.S: Likewise. + * src/x86/unix64.S: Likewise. + * src/x86/sysv.S: Likewise. + * src/sparc/v8.S: Likewise. + * src/sparc/v9.S: Likewise. + * src/m68k/sysv.S: Likewise. + * src/arm/sysv.S: Likewise. + +2008-03-16 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * aclocal.m4: Regenerate. + * configure: Likewise. + * Makefile.in: Likewise. + * include/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + +2008-02-12 Bjoern Koenig <bkoenig@alpha-tierchen.de> + Andreas Tobler <a.tobler@schweiz.org> + + * configure.ac: Add amd64-*-freebsd* target. + * configure: Regenerate. + +2008-01-30 H.J. Lu <hongjiu.lu@intel.com> + + PR libffi/34612 + * src/x86/sysv.S (ffi_closure_SYSV): Pop 4 byte from stack when + returning struct. + + * testsuite/libffi.call/call.exp: Add "-O2 -fomit-frame-pointer" + tests. + +2008-01-24 David Edelsohn <edelsohn@gnu.org> + + * configure: Regenerate. + +2008-01-06 Andreas Tobler <a.tobler@schweiz.org> + + * src/x86/ffi.c (ffi_prep_cif_machdep): Fix thinko. + +2008-01-05 Andreas Tobler <a.tobler@schweiz.org> + + PR testsuite/32843 + * src/x86/ffi.c (ffi_prep_cif_machdep): Add code for + signed/unsigned int8/16 for X86_DARWIN. + Updated copyright info. + Handle one and two byte structs with special cif->flags. + * src/x86/ffitarget.h: Add special types for one and two byte structs. + Updated copyright info. + * src/x86/darwin.S (ffi_call_SYSV): Rewrite to use a jump table like + sysv.S + Remove code to pop args from the stack after call. + Special-case signed/unsigned for int8/16, one and two byte structs. + (ffi_closure_raw_SYSV): Handle FFI_TYPE_UINT8, + FFI_TYPE_SINT8, FFI_TYPE_UINT16, FFI_TYPE_SINT16, FFI_TYPE_UINT32, + FFI_TYPE_SINT32. + Updated copyright info. + +2007-12-08 David Daney <ddaney@avtrex.com> + + * src/mips/n32.S (ffi_call_N32): Replace dadd with ADDU, dsub with + SUBU, add with ADDU and use smaller code sequences. + +2007-12-07 David Daney <ddaney@avtrex.com> + + * src/mips/ffi.c (ffi_prep_cif_machdep): Handle long double return + type. + +2007-12-06 David Daney <ddaney@avtrex.com> + + * include/ffi.h.in (FFI_SIZEOF_JAVA_RAW): Define if not already + defined. + (ffi_java_raw): New typedef. + (ffi_java_raw_call, ffi_java_ptrarray_to_raw, + ffi_java_raw_to_ptrarray): Change parameter types from ffi_raw to + ffi_java_raw. + (ffi_java_raw_closure) : Same. + (ffi_prep_java_raw_closure, ffi_prep_java_raw_closure_loc): Change + parameter types. + * src/java_raw_api.c (ffi_java_raw_size): Replace FFI_SIZEOF_ARG with + FFI_SIZEOF_JAVA_RAW. + (ffi_java_raw_to_ptrarray): Change type of raw to ffi_java_raw. + Replace FFI_SIZEOF_ARG with FFI_SIZEOF_JAVA_RAW. Use + sizeof(ffi_java_raw) for alignment calculations. + (ffi_java_ptrarray_to_raw): Same. + (ffi_java_rvalue_to_raw): Add special handling for FFI_TYPE_POINTER + if FFI_SIZEOF_JAVA_RAW == 4. + (ffi_java_raw_to_rvalue): Same. + (ffi_java_raw_call): Change type of raw to ffi_java_raw. + (ffi_java_translate_args): Same. + (ffi_prep_java_raw_closure_loc, ffi_prep_java_raw_closure): Change + parameter types. + * src/mips/ffitarget.h (FFI_SIZEOF_JAVA_RAW): Define for N32 ABI. + +2007-12-06 David Daney <ddaney@avtrex.com> + + * src/mips/n32.S (ffi_closure_N32): Use 64-bit add instruction on + pointer values. + +2007-12-01 Andreas Tobler <a.tobler@schweiz.org> + + PR libffi/31937 + * src/powerpc/ffitarget.h: Introduce new ABI FFI_LINUX_SOFT_FLOAT. + Add local FFI_TYPE_UINT128 to handle soft-float long-double-128. + * src/powerpc/ffi.c: Distinguish between __NO_FPRS__ and not and + set the NUM_FPR_ARG_REGISTERS according to. + Add support for potential soft-float support under hard-float + architecture. + (ffi_prep_args_SYSV): Set NUM_FPR_ARG_REGISTERS to 0 in case of + FFI_LINUX_SOFT_FLOAT, handle float, doubles and long-doubles according + to the FFI_LINUX_SOFT_FLOAT ABI. + (ffi_prep_cif_machdep): Likewise. + (ffi_closure_helper_SYSV): Likewise. + * src/powerpc/ppc_closure.S: Make sure not to store float/double + on archs where __NO_FPRS__ is true. + Add FFI_TYPE_UINT128 support. + * src/powerpc/sysv.S: Add support for soft-float long-double-128. + Adjust copyright notice. + +2007-11-25 Andreas Tobler <a.tobler@schweiz.org> + + * src/closures.c: Move defintion of MAYBE_UNUSED from here to ... + * include/ffi_common.h: ... here. + Update copyright. + +2007-11-17 Andreas Tobler <a.tobler@schweiz.org> + + * src/powerpc/sysv.S: Load correct cr to compare if we have long double. + * src/powerpc/linux64.S: Likewise. + * src/powerpc/ffi.c: Add a comment to show which part goes into cr6. + * testsuite/libffi.call/return_ldl.c: New test. + +2007-09-04 <aph@redhat.com> + + * src/arm/sysv.S (UNWIND): New. + (Whole file): Conditionally compile unwinder directives. + * src/arm/sysv.S: Add unwinder directives. + + * src/arm/ffi.c (ffi_prep_args): Align structs by at least 4 bytes. + Only treat r0 as a struct address if we're actually returning a + struct by address. + Only copy the bytes that are actually within a struct. + (ffi_prep_cif_machdep): A Composite Type not larger than 4 bytes + is returned in r0, not passed by address. + (ffi_call): Allocate a word-sized temporary for the case where + a composite is returned in r0. + (ffi_prep_incoming_args_SYSV): Align as necessary. + +2007-08-05 Steven Newbury <s_j_newbury@yahoo.co.uk> + + * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Use __clear_cache instead of + directly using the sys_cacheflush syscall. + +2007-07-27 Andrew Haley <aph@redhat.com> + + * src/arm/sysv.S (ffi_closure_SYSV): Add soft-float. + +2007-09-03 Maciej W. Rozycki <macro@linux-mips.org> + + * Makefile.am: Unify MIPS_IRIX and MIPS_LINUX into MIPS. + * configure.ac: Likewise. + * Makefile.in: Regenerate. + * include/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + * configure: Likewise. + +2007-08-24 David Daney <ddaney@avtrex.com> + + * testsuite/libffi.call/return_sl.c: New test. + +2007-08-10 David Daney <ddaney@avtrex.com> + + * testsuite/libffi.call/cls_multi_ushort.c, + testsuite/libffi.call/cls_align_uint16.c, + testsuite/libffi.call/nested_struct1.c, + testsuite/libffi.call/nested_struct3.c, + testsuite/libffi.call/cls_7_1_byte.c, + testsuite/libffi.call/nested_struct5.c, + testsuite/libffi.call/cls_double.c, + testsuite/libffi.call/nested_struct7.c, + testsuite/libffi.call/cls_sint.c, + testsuite/libffi.call/nested_struct9.c, + testsuite/libffi.call/cls_20byte1.c, + testsuite/libffi.call/cls_multi_sshortchar.c, + testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_3byte2.c, + testsuite/libffi.call/cls_multi_schar.c, + testsuite/libffi.call/cls_multi_uchar.c, + testsuite/libffi.call/cls_19byte.c, + testsuite/libffi.call/cls_9byte1.c, + testsuite/libffi.call/cls_align_float.c, + testsuite/libffi.call/closure_fn1.c, + testsuite/libffi.call/problem1.c, + testsuite/libffi.call/closure_fn3.c, + testsuite/libffi.call/cls_sshort.c, + testsuite/libffi.call/closure_fn5.c, + testsuite/libffi.call/cls_align_double.c, + testsuite/libffi.call/nested_struct.c, + testsuite/libffi.call/cls_2byte.c, + testsuite/libffi.call/nested_struct10.c, + testsuite/libffi.call/cls_4byte.c, + testsuite/libffi.call/cls_6byte.c, + testsuite/libffi.call/cls_8byte.c, + testsuite/libffi.call/cls_multi_sshort.c, + testsuite/libffi.call/cls_align_sint16.c, + testsuite/libffi.call/cls_align_uint32.c, + testsuite/libffi.call/cls_20byte.c, + testsuite/libffi.call/cls_float.c, + testsuite/libffi.call/nested_struct2.c, + testsuite/libffi.call/cls_5_1_byte.c, + testsuite/libffi.call/nested_struct4.c, + testsuite/libffi.call/cls_24byte.c, + testsuite/libffi.call/nested_struct6.c, + testsuite/libffi.call/cls_64byte.c, + testsuite/libffi.call/nested_struct8.c, + testsuite/libffi.call/cls_uint.c, + testsuite/libffi.call/cls_multi_ushortchar.c, + testsuite/libffi.call/cls_schar.c, + testsuite/libffi.call/cls_uchar.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/cls_align_longdouble.c, + testsuite/libffi.call/cls_1_1byte.c, + testsuite/libffi.call/cls_12byte.c, + testsuite/libffi.call/cls_3_1byte.c, + testsuite/libffi.call/cls_3byte1.c, + testsuite/libffi.call/cls_4_1byte.c, + testsuite/libffi.call/cls_6_1_byte.c, + testsuite/libffi.call/cls_16byte.c, + testsuite/libffi.call/cls_18byte.c, + testsuite/libffi.call/closure_fn0.c, + testsuite/libffi.call/cls_9byte2.c, + testsuite/libffi.call/closure_fn2.c, + testsuite/libffi.call/closure_fn4.c, + testsuite/libffi.call/cls_ushort.c, + testsuite/libffi.call/closure_fn6.c, + testsuite/libffi.call/cls_5byte.c, + testsuite/libffi.call/cls_align_pointer.c, + testsuite/libffi.call/cls_7byte.c, + testsuite/libffi.call/cls_align_sint32.c, + testsuite/libffi.special/unwindtest_ffi_call.cc, + testsuite/libffi.special/unwindtest.cc: Remove xfail for mips64*-*-*. + +2007-08-10 David Daney <ddaney@avtrex.com> + + PR libffi/28313 + * configure.ac: Don't treat mips64 as a special case. + * Makefile.am (nodist_libffi_la_SOURCES): Add n32.S. + * configure: Regenerate + * Makefile.in: Ditto. + * fficonfig.h.in: Ditto. + * src/mips/ffitarget.h (REG_L, REG_S, SUBU, ADDU, SRL, LI): Indent. + (LA, EH_FRAME_ALIGN, FDE_ADDR_BYTES): New preprocessor macros. + (FFI_DEFAULT_ABI): Set for n64 case. + (FFI_CLOSURES, FFI_TRAMPOLINE_SIZE): Define for n32 and n64 cases. + * src/mips/n32.S (ffi_call_N32): Add debug macros and labels for FDE. + (ffi_closure_N32): New function. + (.eh_frame): New section + * src/mips/o32.S: Clean up comments. + (ffi_closure_O32): Pass ffi_closure parameter in $12. + * src/mips/ffi.c: Use FFI_MIPS_N32 instead of + _MIPS_SIM == _ABIN32 throughout. + (FFI_MIPS_STOP_HERE): New, use in place of + ffi_stop_here. + (ffi_prep_args): Use unsigned long to hold pointer values. Rewrite + to support n32/n64 ABIs. + (calc_n32_struct_flags): Rewrite. + (calc_n32_return_struct_flags): Remove unused variable. Reverse + position of flag bits. + (ffi_prep_cif_machdep): Rewrite n32 portion. + (ffi_call): Enable for n64. Add special handling for small structure + return values. + (ffi_prep_closure_loc): Add n32 and n64 support. + (ffi_closure_mips_inner_O32): Add cast to silence warning. + (copy_struct_N32, ffi_closure_mips_inner_N32): New functions. + +2007-08-08 David Daney <ddaney@avtrex.com> + + * testsuite/libffi.call/ffitest.h (ffi_type_mylong): Remove definition. + * testsuite/libffi.call/cls_align_uint16.c (main): Use correct type + specifiers. + * testsuite/libffi.call/nested_struct1.c (main): Ditto. + * testsuite/libffi.call/cls_sint.c (main): Ditto. + * testsuite/libffi.call/nested_struct9.c (main): Ditto. + * testsuite/libffi.call/cls_20byte1.c (main): Ditto. + * testsuite/libffi.call/cls_9byte1.c (main): Ditto. + * testsuite/libffi.call/closure_fn1.c (main): Ditto. + * testsuite/libffi.call/closure_fn3.c (main): Ditto. + * testsuite/libffi.call/return_dbl2.c (main): Ditto. + * testsuite/libffi.call/cls_sshort.c (main): Ditto. + * testsuite/libffi.call/return_fl3.c (main): Ditto. + * testsuite/libffi.call/closure_fn5.c (main): Ditto. + * testsuite/libffi.call/nested_struct.c (main): Ditto. + * testsuite/libffi.call/nested_struct10.c (main): Ditto. + * testsuite/libffi.call/return_ll1.c (main): Ditto. + * testsuite/libffi.call/cls_8byte.c (main): Ditto. + * testsuite/libffi.call/cls_align_uint32.c (main): Ditto. + * testsuite/libffi.call/cls_align_sint16.c (main): Ditto. + * testsuite/libffi.call/cls_20byte.c (main): Ditto. + * testsuite/libffi.call/nested_struct2.c (main): Ditto. + * testsuite/libffi.call/cls_24byte.c (main): Ditto. + * testsuite/libffi.call/nested_struct6.c (main): Ditto. + * testsuite/libffi.call/cls_uint.c (main): Ditto. + * testsuite/libffi.call/cls_12byte.c (main): Ditto. + * testsuite/libffi.call/cls_16byte.c (main): Ditto. + * testsuite/libffi.call/closure_fn0.c (main): Ditto. + * testsuite/libffi.call/cls_9byte2.c (main): Ditto. + * testsuite/libffi.call/closure_fn2.c (main): Ditto. + * testsuite/libffi.call/return_dbl1.c (main): Ditto. + * testsuite/libffi.call/closure_fn4.c (main): Ditto. + * testsuite/libffi.call/closure_fn6.c (main): Ditto. + * testsuite/libffi.call/cls_align_sint32.c (main): Ditto. + +2007-08-07 Andrew Haley <aph@redhat.com> + + * src/x86/sysv.S (ffi_closure_raw_SYSV): Fix typo in previous + checkin. + +2007-08-06 Andrew Haley <aph@redhat.com> + + PR testsuite/32843 + * src/x86/sysv.S (ffi_closure_raw_SYSV): Handle FFI_TYPE_UINT8, + FFI_TYPE_SINT8, FFI_TYPE_UINT16, FFI_TYPE_SINT16, FFI_TYPE_UINT32, + FFI_TYPE_SINT32. + +2007-08-02 David Daney <ddaney@avtrex.com> + + * testsuite/libffi.call/return_ul.c (main): Define return type as + ffi_arg. Use proper printf conversion specifier. + +2007-07-30 Andrew Haley <aph@redhat.com> + + PR testsuite/32843 + * src/x86/ffi.c (ffi_prep_cif_machdep): in x86 case, add code for + signed/unsigned int8/16. + * src/x86/sysv.S (ffi_call_SYSV): Rewrite to: + Use a jump table. + Remove code to pop args from the stack after call. + Special-case signed/unsigned int8/16. + * testsuite/libffi.call/return_sc.c (main): Revert. + +2007-07-26 Richard Guenther <rguenther@suse.de> + + PR testsuite/32843 + * testsuite/libffi.call/return_sc.c (main): Verify call + result as signed char, not ffi_arg. + +2007-07-16 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * configure.ac (i?86-*-solaris2.1[0-9]): Set TARGET to X86_64. + * configure: Regenerate. + +2007-07-11 David Daney <ddaney@avtrex.com> + + * src/mips/ffi.c: Don't include sys/cachectl.h. + (ffi_prep_closure_loc): Use __builtin___clear_cache() instead of + cacheflush(). + +2007-05-18 Aurelien Jarno <aurelien@aurel32.net> + + * src/arm/ffi.c (ffi_prep_closure_loc): Renamed and ajusted + from (ffi_prep_closure): ... this. + (FFI_INIT_TRAMPOLINE): Adjust. + +2005-12-31 Phil Blundell <pb@reciva.com> + + * src/arm/ffi.c (ffi_prep_incoming_args_SYSV, + ffi_closure_SYSV_inner, ffi_prep_closure): New, add closure support. + * src/arm/sysv.S(ffi_closure_SYSV): Likewise. + * src/arm/ffitarget.h (FFI_TRAMPOLINE_SIZE): Likewise. + (FFI_CLOSURES): Enable closure support. + +2007-07-03 Andrew Haley <aph@hedges.billgatliff.com> + + * testsuite/libffi.call/cls_multi_ushort.c, + testsuite/libffi.call/cls_align_uint16.c, + testsuite/libffi.call/nested_struct1.c, + testsuite/libffi.call/nested_struct3.c, + testsuite/libffi.call/cls_7_1_byte.c, + testsuite/libffi.call/cls_double.c, + testsuite/libffi.call/nested_struct5.c, + testsuite/libffi.call/nested_struct7.c, + testsuite/libffi.call/cls_sint.c, + testsuite/libffi.call/nested_struct9.c, + testsuite/libffi.call/cls_20byte1.c, + testsuite/libffi.call/cls_multi_sshortchar.c, + testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_3byte2.c, + testsuite/libffi.call/cls_multi_schar.c, + testsuite/libffi.call/cls_multi_uchar.c, + testsuite/libffi.call/cls_19byte.c, + testsuite/libffi.call/cls_9byte1.c, + testsuite/libffi.call/cls_align_float.c, + testsuite/libffi.call/closure_fn1.c, + testsuite/libffi.call/problem1.c, + testsuite/libffi.call/closure_fn3.c, + testsuite/libffi.call/cls_sshort.c, + testsuite/libffi.call/closure_fn5.c, + testsuite/libffi.call/cls_align_double.c, + testsuite/libffi.call/cls_2byte.c, + testsuite/libffi.call/nested_struct.c, + testsuite/libffi.call/nested_struct10.c, + testsuite/libffi.call/cls_4byte.c, + testsuite/libffi.call/cls_6byte.c, + testsuite/libffi.call/cls_8byte.c, + testsuite/libffi.call/cls_multi_sshort.c, + testsuite/libffi.call/cls_align_uint32.c, + testsuite/libffi.call/cls_align_sint16.c, + testsuite/libffi.call/cls_float.c, + testsuite/libffi.call/cls_20byte.c, + testsuite/libffi.call/cls_5_1_byte.c, + testsuite/libffi.call/nested_struct2.c, + testsuite/libffi.call/cls_24byte.c, + testsuite/libffi.call/nested_struct4.c, + testsuite/libffi.call/nested_struct6.c, + testsuite/libffi.call/cls_64byte.c, + testsuite/libffi.call/nested_struct8.c, + testsuite/libffi.call/cls_uint.c, + testsuite/libffi.call/cls_multi_ushortchar.c, + testsuite/libffi.call/cls_schar.c, + testsuite/libffi.call/cls_uchar.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/cls_align_longdouble.c, + testsuite/libffi.call/cls_1_1byte.c, + testsuite/libffi.call/cls_12byte.c, + testsuite/libffi.call/cls_3_1byte.c, + testsuite/libffi.call/cls_3byte1.c, + testsuite/libffi.call/cls_4_1byte.c, + testsuite/libffi.call/cls_6_1_byte.c, + testsuite/libffi.call/cls_16byte.c, + testsuite/libffi.call/cls_18byte.c, + testsuite/libffi.call/closure_fn0.c, + testsuite/libffi.call/cls_9byte2.c, + testsuite/libffi.call/closure_fn2.c, + testsuite/libffi.call/closure_fn4.c, + testsuite/libffi.call/cls_ushort.c, + testsuite/libffi.call/closure_fn6.c, + testsuite/libffi.call/cls_5byte.c, + testsuite/libffi.call/cls_align_pointer.c, + testsuite/libffi.call/cls_7byte.c, + testsuite/libffi.call/cls_align_sint32.c, + testsuite/libffi.special/unwindtest_ffi_call.cc, + testsuite/libffi.special/unwindtest.cc: Enable for ARM. + +2007-07-05 H.J. Lu <hongjiu.lu@intel.com> + + * aclocal.m4: Regenerated. + +2007-06-02 Paolo Bonzini <bonzini@gnu.org> + + * configure: Regenerate. + +2007-05-23 Steve Ellcey <sje@cup.hp.com> + + * Makefile.in: Regenerate. + * configure: Regenerate. + * aclocal.m4: Regenerate. + * include/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2007-05-10 Roman Zippel <zippel@linux-m68k.org> + + * src/m68k/ffi.c (ffi_prep_incoming_args_SYSV, + ffi_closure_SYSV_inner,ffi_prep_closure): New, add closure support. + * src/m68k/sysv.S(ffi_closure_SYSV,ffi_closure_struct_SYSV): Likewise. + * src/m68k/ffitarget.h (FFI_TRAMPOLINE_SIZE): Likewise. + (FFI_CLOSURES): Enable closure support. + +2007-05-10 Roman Zippel <zippel@linux-m68k.org> + + * configure.ac (HAVE_AS_CFI_PSEUDO_OP): New test. + * configure: Regenerate. + * fficonfig.h.in: Regenerate. + * src/m68k/sysv.S (CFI_STARTPROC,CFI_ENDPROC, + CFI_OFFSET,CFI_DEF_CFA): New macros. + (ffi_call_SYSV): Add callframe annotation. + +2007-05-10 Roman Zippel <zippel@linux-m68k.org> + + * src/m68k/ffi.c (ffi_prep_args,ffi_prep_cif_machdep): Fix + numerous test suite failures. + * src/m68k/sysv.S (ffi_call_SYSV): Likewise. + +2007-04-11 Paolo Bonzini <bonzini@gnu.org> + + * Makefile.am (EXTRA_DIST): Bring up to date. + * Makefile.in: Regenerate. + * src/frv/eabi.S: Remove RCS keyword. + +2007-04-06 Richard Henderson <rth@redhat.com> + + * configure.ac: Tidy target case. + (HAVE_LONG_DOUBLE): Allow the target to override. + * configure: Regenerate. + * include/ffi.h.in: Don't define ffi_type_foo if + LIBFFI_HIDE_BASIC_TYPES is defined. + (ffi_type_longdouble): If not HAVE_LONG_DOUBLE, define + to ffi_type_double. + * types.c (LIBFFI_HIDE_BASIC_TYPES): Define. + (FFI_TYPEDEF, ffi_type_void): Mark the data const. + (ffi_type_longdouble): Special case for Alpha. Don't define + if long double == double. + + * src/alpha/ffi.c (FFI_TYPE_LONGDOUBLE): Assert unique value. + (ffi_prep_cif_machdep): Handle it as the 128-bit type. + (ffi_call, ffi_closure_osf_inner): Likewise. + (ffi_closure_osf_inner): Likewise. Mark hidden. + (ffi_call_osf, ffi_closure_osf): Mark hidden. + * src/alpha/ffitarget.h (FFI_LAST_ABI): Tidy definition. + * src/alpha/osf.S (ffi_call_osf, ffi_closure_osf): Mark hidden. + (load_table): Handle 128-bit long double. + + * testsuite/libffi.call/float4.c: Add -mieee for alpha. + +2007-04-06 Tom Tromey <tromey@redhat.com> + + PR libffi/31491: + * README: Fixed bug in example. + +2007-04-03 Jakub Jelinek <jakub@redhat.com> + + * src/closures.c: Include sys/statfs.h. + (_GNU_SOURCE): Define on Linux. + (FFI_MMAP_EXEC_SELINUX): Define. + (selinux_enabled): New variable. + (selinux_enabled_check): New function. + (is_selinux_enabled): Define. + (dlmmap): Use it. + +2007-03-24 Uros Bizjak <ubizjak@gmail.com> + + * testsuite/libffi.call/return_fl2.c (return_fl): Mark as static. + Use 'volatile float sum' to create sum of floats to avoid false + negative due to excess precision on ix86 targets. + (main): Ditto. + +2007-03-08 Alexandre Oliva <aoliva@redhat.com> + + * src/powerpc/ffi.c (flush_icache): Fix left-over from previous + patch. + (ffi_prep_closure_loc): Remove unneeded casts. Add needed ones. + +2007-03-07 Alexandre Oliva <aoliva@redhat.com> + + * include/ffi.h.in (ffi_closure_alloc, ffi_closure_free): New. + (ffi_prep_closure_loc): New. + (ffi_prep_raw_closure_loc): New. + (ffi_prep_java_raw_closure_loc): New. + * src/closures.c: New file. + * src/dlmalloc.c [FFI_MMAP_EXEC_WRIT] (struct malloc_segment): + Replace sflags with exec_offset. + [FFI_MMAP_EXEC_WRIT] (mmap_exec_offset, add_segment_exec_offset, + sub_segment_exec_offset): New macros. + (get_segment_flags, set_segment_flags, check_segment_merge): New + macros. + (is_mmapped_segment, is_extern_segment): Use get_segment_flags. + (add_segment, sys_alloc, create_mspace, create_mspace_with_base, + destroy_mspace): Use new macros. + (sys_alloc): Silence warning. + * Makefile.am (libffi_la_SOURCES): Add src/closures.c. + * Makefile.in: Rebuilt. + * src/prep_cif [FFI_CLOSURES] (ffi_prep_closure): Implement in + terms of ffi_prep_closure_loc. + * src/raw_api.c (ffi_prep_raw_closure_loc): Renamed and adjusted + from... + (ffi_prep_raw_closure): ... this. Re-implement in terms of the + renamed version. + * src/java_raw_api (ffi_prep_java_raw_closure_loc): Renamed and + adjusted from... + (ffi_prep_java_raw_closure): ... this. Re-implement in terms of + the renamed version. + * src/alpha/ffi.c (ffi_prep_closure_loc): Renamed from + (ffi_prep_closure): ... this. + * src/pa/ffi.c: Likewise. + * src/cris/ffi.c: Likewise. Adjust. + * src/frv/ffi.c: Likewise. + * src/ia64/ffi.c: Likewise. + * src/mips/ffi.c: Likewise. + * src/powerpc/ffi_darwin.c: Likewise. + * src/s390/ffi.c: Likewise. + * src/sh/ffi.c: Likewise. + * src/sh64/ffi.c: Likewise. + * src/sparc/ffi.c: Likewise. + * src/x86/ffi64.c: Likewise. + * src/x86/ffi.c: Likewise. + (FFI_INIT_TRAMPOLINE): Adjust. + (ffi_prep_raw_closure_loc): Renamed and adjusted from... + (ffi_prep_raw_closure): ... this. + * src/powerpc/ffi.c (ffi_prep_closure_loc): Renamed from + (ffi_prep_closure): ... this. + (flush_icache): Adjust. + +2007-03-07 Alexandre Oliva <aoliva@redhat.com> + + * src/dlmalloc.c: New file, imported version 2.8.3 of Doug + Lea's malloc. + +2007-03-01 Brooks Moses <brooks.moses@codesourcery.com> + + * Makefile.am: Add dummy install-pdf target. + * Makefile.in: Regenerate + +2007-02-13 Andreas Krebbel <krebbel1@de.ibm.com> + + * src/s390/ffi.c (ffi_prep_args, ffi_prep_cif_machdep, + ffi_closure_helper_SYSV): Add long double handling. + +2007-02-02 Jakub Jelinek <jakub@redhat.com> + + * src/powerpc/linux64.S (ffi_call_LINUX64): Move restore of r2 + immediately after bctrl instruction. + +2007-01-18 Alexandre Oliva <aoliva@redhat.com> + + * Makefile.am (all-recursive, install-recursive, + mostlyclean-recursive, clean-recursive, distclean-recursive, + maintainer-clean-recursive): Add missing targets. + * Makefile.in: Rebuilt. + +2006-12-14 Andreas Tobler <a.tobler@schweiz.org> + + * configure.ac: Add TARGET for x86_64-*-darwin*. + * Makefile.am (nodist_libffi_la_SOURCES): Add rules for 64-bit sources + for X86_DARWIN. + * src/x86/ffitarget.h: Set trampoline size for x86_64-*-darwin*. + * src/x86/darwin64.S: New file for x86_64-*-darwin* support. + * configure: Regenerate. + * Makefile.in: Regenerate. + * include/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + * testsuite/libffi.special/unwindtest_ffi_call.cc: New test case for + ffi_call only. + +2006-12-13 Andreas Tobler <a.tobler@schweiz.org> + + * aclocal.m4: Regenerate with aclocal -I .. as written in the + Makefile.am. + +2006-10-31 Geoffrey Keating <geoffk@apple.com> + + * src/powerpc/ffi_darwin.c (darwin_adjust_aggregate_sizes): New. + (ffi_prep_cif_machdep): Call darwin_adjust_aggregate_sizes for + Darwin. + * testsuite/libffi.call/nested_struct4.c: Remove Darwin XFAIL. + * testsuite/libffi.call/nested_struct6.c: Remove Darwin XFAIL. + +2006-10-10 Paolo Bonzini <bonzini@gnu.org> + Sandro Tolaini <tolaini@libero.it> + + * configure.ac [i*86-*-darwin*]: Set X86_DARWIN symbol and + conditional. + * configure: Regenerated. + * Makefile.am (nodist_libffi_la_SOURCES) [X86_DARWIN]: New case. + (EXTRA_DIST): Add src/x86/darwin.S. + * Makefile.in: Regenerated. + * include/Makefile.in: Regenerated. + * testsuite/Makefile.in: Regenerated. + + * src/x86/ffi.c (ffi_prep_cif_machdep) [X86_DARWIN]: Treat like + X86_WIN32, and additionally align stack to 16 bytes. + * src/x86/darwin.S: New, based on sysv.S. + * src/prep_cif.c (ffi_prep_cif) [X86_DARWIN]: Align > 8-byte structs. + +2006-09-12 David Daney <ddaney@avtrex.com> + + PR libffi/23935 + * include/Makefile.am: Install both ffi.h and ffitarget.h in + $(libdir)/gcc/$(target_alias)/$(gcc_version)/include. + * aclocal.m4: Regenerated for automake 1.9.6. + * Makefile.in: Regenerated. + * include/Makefile.in: Regenerated. + * testsuite/Makefile.in: Regenerated. + +2006-08-17 Andreas Tobler <a.tobler@schweiz.ch> + + * include/ffi_common.h (struct): Revert accidental commit. + +2006-08-15 Andreas Tobler <a.tobler@schweiz.ch> + + * include/ffi_common.h: Remove lint directives. + * include/ffi.h.in: Likewise. + +2006-07-25 Torsten Schoenfeld <kaffeetisch@gmx.de> + + * include/ffi.h.in (ffi_type_ulong, ffi_type_slong): Define correctly + for 32-bit architectures. + * testsuite/libffi.call/return_ul.c: New test case. + +2006-07-19 David Daney <ddaney@avtrex.com> + + * testsuite/libffi.call/closure_fn6.c: Remove xfail for mips, + xfail remains for mips64. + +2006-05-23 Carlos O'Donell <carlos@codesourcery.com> + + * Makefile.am: Add install-html target. Add install-html to .PHONY + * Makefile.in: Regenerate. + * aclocal.m4: Regenerate. + * include/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2006-05-18 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> + + * pa/ffi.c (ffi_prep_args_pa32): Load floating point arguments from + stack slot. + +2006-04-22 Andreas Tobler <a.tobler@schweiz.ch> + + * README: Remove notice about 'Crazy Comments'. + * src/debug.c: Remove lint directives. Cleanup white spaces. + * src/java_raw_api.c: Likewise. + * src/prep_cif.c: Likewise. + * src/raw_api.c: Likewise. + * src/ffitest.c: Delete. No longer needed, all test cases migrated + to the testsuite. + * src/arm/ffi.c: Remove lint directives. + * src/m32r/ffi.c: Likewise. + * src/pa/ffi.c: Likewise. + * src/powerpc/ffi.c: Likewise. + * src/powerpc/ffi_darwin.c: Likewise. + * src/sh/ffi.c: Likewise. + * src/sh64/ffi.c: Likewise. + * src/x86/ffi.c: Likewise. + * testsuite/libffi.call/float2.c: Likewise. + * testsuite/libffi.call/promotion.c: Likewise. + * testsuite/libffi.call/struct1.c: Likewise. + +2006-04-13 Andreas Tobler <a.tobler@schweiz.ch> + + * src/pa/hpux32.S: Correct unwind offset calculation for + ffi_closure_pa32. + * src/pa/linux.S: Likewise. + +2006-04-12 James E Wilson <wilson@specifix.com> + + PR libgcj/26483 + * src/ia64/ffi.c (stf_spill, ldf_fill): Rewrite as macros. + (hfa_type_load): Call stf_spill. + (hfa_type_store): Call ldf_fill. + (ffi_call): Adjust calls to above routines. Add local temps for + macro result. + +2006-04-10 Matthias Klose <doko@debian.org> + + * testsuite/lib/libffi-dg.exp (libffi-init): Recognize multilib + directory names containing underscores. + +2006-04-07 James E Wilson <wilson@specifix.com> + + * testsuite/libffi.call/float4.c: New testcase. + +2006-04-05 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> + Andreas Tobler <a.tobler@schweiz.ch> + + * Makefile.am: Add PA_HPUX port. + * Makefile.in: Regenerate. + * include/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + * configure.ac: Add PA_HPUX rules. + * configure: Regenerate. + * src/pa/ffitarget.h: Rename linux target to PA_LINUX. + Add PA_HPUX and PA64_HPUX. + Rename FFI_LINUX ABI to FFI_PA32 ABI. + (FFI_TRAMPOLINE_SIZE): Define for 32-bit HP-UX targets. + (FFI_TYPE_SMALL_STRUCT2): Define. + (FFI_TYPE_SMALL_STRUCT4): Likewise. + (FFI_TYPE_SMALL_STRUCT8): Likewise. + (FFI_TYPE_SMALL_STRUCT3): Redefine. + (FFI_TYPE_SMALL_STRUCT5): Likewise. + (FFI_TYPE_SMALL_STRUCT6): Likewise. + (FFI_TYPE_SMALL_STRUCT7): Likewise. + * src/pa/ffi.c (ROUND_DOWN): Delete. + (fldw, fstw, fldd, fstd): Use '__asm__'. + (ffi_struct_type): Add support for FFI_TYPE_SMALL_STRUCT2, + FFI_TYPE_SMALL_STRUCT4 and FFI_TYPE_SMALL_STRUCT8. + (ffi_prep_args_LINUX): Rename to ffi_prep_args_pa32. Update comment. + Simplify incrementing of stack slot variable. Change type of local + 'n' to unsigned int. + (ffi_size_stack_LINUX): Rename to ffi_size_stack_pa32. Handle long + double on PA_HPUX. + (ffi_prep_cif_machdep): Likewise. + (ffi_call): Likewise. + (ffi_closure_inner_LINUX): Rename to ffi_closure_inner_pa32. Change + return type to ffi_status. Simplify incrementing of stack slot + variable. Only copy floating point argument registers when PA_LINUX + is true. Reformat debug statement. + Add support for FFI_TYPE_SMALL_STRUCT2, FFI_TYPE_SMALL_STRUCT4 and + FFI_TYPE_SMALL_STRUCT8. + (ffi_closure_LINUX): Rename to ffi_closure_pa32. Add 'extern' to + declaration. + (ffi_prep_closure): Make linux trampoline conditional on PA_LINUX. + Add nops to cache flush. Add trampoline for PA_HPUX. + * src/pa/hpux32.S: New file. + * src/pa/linux.S (ffi_call_LINUX): Rename to ffi_call_pa32. Rename + ffi_prep_args_LINUX to ffi_prep_args_pa32. + Localize labels. Add support for 2, 4 and 8-byte small structs. Handle + unaligned destinations in 3, 5, 6 and 7-byte small structs. Order + argument type checks so that common argument types appear first. + (ffi_closure_LINUX): Rename to ffi_closure_pa32. Rename + ffi_closure_inner_LINUX to ffi_closure_inner_pa32. + +2006-03-24 Alan Modra <amodra@bigpond.net.au> + + * src/powerpc/ffitarget.h (enum ffi_abi): Add FFI_LINUX. Default + for 32-bit using IBM extended double format. Fix FFI_LAST_ABI. + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Handle linux variant of + FFI_TYPE_LONGDOUBLE. + (ffi_prep_args64): Assert using IBM extended double. + (ffi_prep_cif_machdep): Don't munge FFI_TYPE_LONGDOUBLE type. + Handle FFI_LINUX FFI_TYPE_LONGDOUBLE return and args. + (ffi_call): Handle FFI_LINUX. + (ffi_closure_helper_SYSV): Non FFI_LINUX long double return needs + gpr3 return pointer as for struct return. Handle FFI_LINUX + FFI_TYPE_LONGDOUBLE return and args. Don't increment "nf" + unnecessarily. + * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Load both f1 and f2 + for FFI_TYPE_LONGDOUBLE. Move epilogue insns into case table. + Don't use r6 as pointer to results, instead use sp offset. Don't + make a special call to load lr with case table address, instead + use offset from previous call. + * src/powerpc/sysv.S (ffi_call_SYSV): Save long double return. + * src/powerpc/linux64.S (ffi_call_LINUX64): Simplify long double + return. + +2006-03-15 Kaz Kojima <kkojima@gcc.gnu.org> + + * src/sh64/ffi.c (ffi_prep_cif_machdep): Handle float arguments + passed with FP registers correctly. + (ffi_closure_helper_SYSV): Likewise. + * src/sh64/sysv.S: Likewise. + +2006-03-01 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.special/unwindtest.cc (closure_test_fn): Mark cif, + args and userdata unused. + (closure_test_fn1): Mark cif and userdata unused. + (main): Remove unused res. + +2006-02-28 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.call/call.exp: Adjust FSF address. Add test runs for + -O2, -O3, -Os and the warning flags -W -Wall. + * testsuite/libffi.special/special.exp: Likewise. + * testsuite/libffi.call/ffitest.h: Add an __UNUSED__ macro to mark + unused parameter unused for gcc or else do nothing. + * testsuite/libffi.special/ffitestcxx.h: Likewise. + * testsuite/libffi.call/cls_12byte.c (cls_struct_12byte_gn): Mark cif + and userdata unused. + * testsuite/libffi.call/cls_16byte.c (cls_struct_16byte_gn): Likewise. + * testsuite/libffi.call/cls_18byte.c (cls_struct_18byte_gn): Likewise. + * testsuite/libffi.call/cls_19byte.c (cls_struct_19byte_gn): Likewise. + * testsuite/libffi.call/cls_1_1byte.c (cls_struct_1_1byte_gn): Likewise. + * testsuite/libffi.call/cls_20byte.c (cls_struct_20byte_gn): Likewise. + * testsuite/libffi.call/cls_20byte1.c (cls_struct_20byte_gn): Likewise. + * testsuite/libffi.call/cls_24byte.c (cls_struct_24byte_gn): Likewise. + * testsuite/libffi.call/cls_2byte.c (cls_struct_2byte_gn): Likewise. + * testsuite/libffi.call/cls_3_1byte.c (cls_struct_3_1byte_gn): Likewise. + * testsuite/libffi.call/cls_3byte1.c (cls_struct_3byte_gn): Likewise. + * testsuite/libffi.call/cls_3byte2.c (cls_struct_3byte_gn1): Likewise. + * testsuite/libffi.call/cls_4_1byte.c (cls_struct_4_1byte_gn): Likewise. + * testsuite/libffi.call/cls_4byte.c (cls_struct_4byte_gn): Likewise. + * testsuite/libffi.call/cls_5_1_byte.c (cls_struct_5byte_gn): Likewise. + * testsuite/libffi.call/cls_5byte.c (cls_struct_5byte_gn): Likewise. + * testsuite/libffi.call/cls_64byte.c (cls_struct_64byte_gn): Likewise. + * testsuite/libffi.call/cls_6_1_byte.c (cls_struct_6byte_gn): Likewise. + * testsuite/libffi.call/cls_6byte.c (cls_struct_6byte_gn): Likewise. + * testsuite/libffi.call/cls_7_1_byte.c (cls_struct_7byte_gn): Likewise. + * testsuite/libffi.call/cls_7byte.c (cls_struct_7byte_gn): Likewise. + * testsuite/libffi.call/cls_8byte.c (cls_struct_8byte_gn): Likewise. + * testsuite/libffi.call/cls_9byte1.c (cls_struct_9byte_gn): Likewise. + * testsuite/libffi.call/cls_9byte2.c (cls_struct_9byte_gn): Likewise. + * testsuite/libffi.call/cls_align_double.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_float.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_longdouble.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_pointer.c (cls_struct_align_fn): Cast + void* to avoid compiler warning. + (main): Likewise. + (cls_struct_align_gn): Mark cif and userdata unused. + * testsuite/libffi.call/cls_align_sint16.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_sint32.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_sint64.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_uint16.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_uint32.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_double.c (cls_ret_double_fn): Likewise. + * testsuite/libffi.call/cls_float.c (cls_ret_float_fn): Likewise. + * testsuite/libffi.call/cls_multi_schar.c (test_func_gn): Mark cif and + data unused. + (main): Cast res_call to silence gcc. + * testsuite/libffi.call/cls_multi_sshort.c (test_func_gn): Mark cif and + data unused. + (main): Cast res_call to silence gcc. + * testsuite/libffi.call/cls_multi_sshortchar.c (test_func_gn): Mark cif + and data unused. + (main): Cast res_call to silence gcc. + * testsuite/libffi.call/cls_multi_uchar.c (test_func_gn): Mark cif and + data unused. + (main): Cast res_call to silence gcc. + * testsuite/libffi.call/cls_multi_ushort.c (test_func_gn): Mark cif and + data unused. + (main): Cast res_call to silence gcc. + * testsuite/libffi.call/cls_multi_ushortchar.c (test_func_gn): Mark cif + and data unused. + (main): Cast res_call to silence gcc. + * testsuite/libffi.call/cls_schar.c (cls_ret_schar_fn): Mark cif and + userdata unused. + (cls_ret_schar_fn): Cast printf parameter to silence gcc. + * testsuite/libffi.call/cls_sint.c (cls_ret_sint_fn): Mark cif and + userdata unused. + (cls_ret_sint_fn): Cast printf parameter to silence gcc. + * testsuite/libffi.call/cls_sshort.c (cls_ret_sshort_fn): Mark cif and + userdata unused. + (cls_ret_sshort_fn): Cast printf parameter to silence gcc. + * testsuite/libffi.call/cls_uchar.c (cls_ret_uchar_fn): Mark cif and + userdata unused. + (cls_ret_uchar_fn): Cast printf parameter to silence gcc. + * testsuite/libffi.call/cls_uint.c (cls_ret_uint_fn): Mark cif and + userdata unused. + (cls_ret_uint_fn): Cast printf parameter to silence gcc. + * testsuite/libffi.call/cls_ulonglong.c (cls_ret_ulonglong_fn): Mark cif + and userdata unused. + * testsuite/libffi.call/cls_ushort.c (cls_ret_ushort_fn): Mark cif and + userdata unused. + (cls_ret_ushort_fn): Cast printf parameter to silence gcc. + * testsuite/libffi.call/float.c (floating): Remove unused parameter e. + * testsuite/libffi.call/float1.c (main): Remove unused variable i. + Cleanup white spaces. + * testsuite/libffi.call/negint.c (checking): Remove unused variable i. + * testsuite/libffi.call/nested_struct.c (cls_struct_combined_gn): Mark + cif and userdata unused. + * testsuite/libffi.call/nested_struct1.c (cls_struct_combined_gn): + Likewise. + * testsuite/libffi.call/nested_struct10.c (B_gn): Likewise. + * testsuite/libffi.call/nested_struct2.c (B_fn): Adjust printf + formatters to silence gcc. + (B_gn): Mark cif and userdata unused. + * testsuite/libffi.call/nested_struct3.c (B_gn): Mark cif and userdata + unused. + * testsuite/libffi.call/nested_struct4.c: Mention related PR. + (B_gn): Mark cif and userdata unused. + * testsuite/libffi.call/nested_struct5.c (B_gn): Mark cif and userdata + unused. + * testsuite/libffi.call/nested_struct6.c: Mention related PR. + (B_gn): Mark cif and userdata unused. + * testsuite/libffi.call/nested_struct7.c (B_gn): Mark cif and userdata + unused. + * testsuite/libffi.call/nested_struct8.c (B_gn): Likewise. + * testsuite/libffi.call/nested_struct9.c (B_gn): Likewise. + * testsuite/libffi.call/problem1.c (stub): Likewise. + * testsuite/libffi.call/pyobjc-tc.c (main): Cast the result to silence + gcc. + * testsuite/libffi.call/return_fl2.c (return_fl): Add the note mentioned + in the last commit for this test case in the test case itself. + * testsuite/libffi.call/closure_fn0.c (closure_test_fn0): Mark cif as + unused. + * testsuite/libffi.call/closure_fn1.c (closure_test_fn1): Likewise. + * testsuite/libffi.call/closure_fn2.c (closure_test_fn2): Likewise. + * testsuite/libffi.call/closure_fn3.c (closure_test_fn3): Likewise. + * testsuite/libffi.call/closure_fn4.c (closure_test_fn0): Likewise. + * testsuite/libffi.call/closure_fn5.c (closure_test_fn5): Likewise. + * testsuite/libffi.call/closure_fn6.c (closure_test_fn0): Likewise. + +2006-02-22 Kaz Kojima <kkojima@gcc.gnu.org> + + * src/sh/sysv.S: Fix register numbers in the FDE for + ffi_closure_SYSV. + +2006-02-20 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.call/return_fl2.c (return_fl): Remove static + declaration to avoid a false negative on ix86. See PR323. + +2006-02-18 Kaz Kojima <kkojima@gcc.gnu.org> + + * src/sh/ffi.c (ffi_closure_helper_SYSV): Remove unused variable + and cast integer to void * if needed. Update the pointer to + the FP register saved area correctly. + +2006-02-17 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.call/nested_struct6.c: XFAIL this test until PR25630 + is fixed. + * testsuite/libffi.call/nested_struct4.c: Likewise. + +2006-02-16 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.call/return_dbl.c: New test case. + * testsuite/libffi.call/return_dbl1.c: Likewise. + * testsuite/libffi.call/return_dbl2.c: Likewise. + * testsuite/libffi.call/return_fl.c: Likewise. + * testsuite/libffi.call/return_fl1.c: Likewise. + * testsuite/libffi.call/return_fl2.c: Likewise. + * testsuite/libffi.call/return_fl3.c: Likewise. + * testsuite/libffi.call/closure_fn6.c: Likewise. + + * testsuite/libffi.call/nested_struct2.c: Remove ffi_type_mylong + definition. + * testsuite/libffi.call/ffitest.h: Add ffi_type_mylong definition + here to be used by other test cases too. + + * testsuite/libffi.call/nested_struct10.c: New test case. + * testsuite/libffi.call/nested_struct9.c: Likewise. + * testsuite/libffi.call/nested_struct8.c: Likewise. + * testsuite/libffi.call/nested_struct7.c: Likewise. + * testsuite/libffi.call/nested_struct6.c: Likewise. + * testsuite/libffi.call/nested_struct5.c: Likewise. + * testsuite/libffi.call/nested_struct4.c: Likewise. + +2006-01-21 Andreas Tobler <a.tobler@schweiz.ch> + + * configure.ac: Enable libffi for sparc64-*-freebsd*. + * configure: Rebuilt. + +2006-01-18 Jakub Jelinek <jakub@redhat.com> + + * src/powerpc/sysv.S (smst_two_register): Don't call __ashldi3, + instead do the shifting inline. + * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Don't compute %r5 + shift count unconditionally. Simplify load sequences for 1, 2, 3, 4 + and 8 byte structs, for the remaining struct sizes don't call + __lshrdi3, instead do the shifting inline. + +2005-12-07 Thiemo Seufer <ths@networkno.de> + + * src/mips/ffitarget.h: Remove obsolete sgidefs.h include. Add + missing parentheses. + * src/mips/o32.S (ffi_call_O32): Code formatting. Define + and use A3_OFF, FP_OFF, RA_OFF. Micro-optimizations. + (ffi_closure_O32): Likewise, but with newly defined A3_OFF2, + A2_OFF2, A1_OFF2, A0_OFF2, RA_OFF2, FP_OFF2, S0_OFF2, GP_OFF2, + V1_OFF2, V0_OFF2, FA_1_1_OFF2, FA_1_0_OFF2, FA_0_1_OFF2, + FA_0_0_OFF2. + * src/mips/ffi.c (ffi_prep_args): Code formatting. Fix + endianness bugs. + (ffi_prep_closure): Improve trampoline instruction scheduling. + (ffi_closure_mips_inner_O32): Fix endianness bugs. + +2005-12-03 Alan Modra <amodra@bigpond.net.au> + + * src/powerpc/ffi.c: Formatting. + (ffi_prep_args_SYSV): Avoid possible aliasing problems by using unions. + (ffi_prep_args64): Likewise. + +2005-09-30 Geoffrey Keating <geoffk@apple.com> + + * testsuite/lib/libffi-dg.exp (libffi_target_compile): For + darwin, use -shared-libgcc not -lgcc_s, and explain why. + +2005-09-26 Tom Tromey <tromey@redhat.com> + + * testsuite/libffi.call/float1.c (value_type): New typedef. + (CANARY): New define. + (main): Check for result buffer overflow. + * src/powerpc/linux64.S: Handle linux64 long double returns. + * src/powerpc/ffi.c (FLAG_RETURNS_128BITS): New constant. + (ffi_prep_cif_machdep): Handle linux64 long double returns. + +2005-08-25 Alan Modra <amodra@bigpond.net.au> + + PR target/23404 + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Correct placement of stack + homed fp args. + (ffi_status ffi_prep_cif_machdep): Correct stack sizing for same. + +2005-08-11 Jakub Jelinek <jakub@redhat.com> + + * configure.ac (HAVE_HIDDEN_VISIBILITY_ATTRIBUTE): New test. + (AH_BOTTOM): Add FFI_HIDDEN definition. + * configure: Rebuilt. + * fficonfig.h.in: Rebuilt. + * src/powerpc/ffi.c (hidden): Remove. + (ffi_closure_LINUX64, ffi_prep_args64, ffi_call_LINUX64, + ffi_closure_helper_LINUX64): Use FFI_HIDDEN instead of hidden. + * src/powerpc/linux64_closure.S (ffi_closure_LINUX64, + .ffi_closure_LINUX64): Use FFI_HIDDEN instead of .hidden. + * src/x86/ffi.c (ffi_closure_SYSV, ffi_closure_raw_SYSV): Remove, + add FFI_HIDDEN to its prototype. + (ffi_closure_SYSV_inner): New. + * src/x86/sysv.S (ffi_closure_SYSV, ffi_closure_raw_SYSV): New. + * src/x86/win32.S (ffi_closure_SYSV, ffi_closure_raw_SYSV): New. + +2005-08-10 Alfred M. Szmidt <ams@gnu.org> + + PR libffi/21819: + * configure: Rebuilt. + * configure.ac: Handle i*86-*-gnu*. + +2005-08-09 Jakub Jelinek <jakub@redhat.com> + + * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Use + DW_CFA_offset_extended_sf rather than + DW_CFA_GNU_negative_offset_extended. + * src/powerpc/sysv.S (ffi_call_SYSV): Likewise. + +2005-07-22 SUGIOKA Toshinobu <sugioka@itonet.co.jp> + + * src/sh/sysv.S (ffi_call_SYSV): Stop argument popping correctly + on sh3. + (ffi_closure_SYSV): Change the stack layout for sh3 struct argument. + * src/sh/ffi.c (ffi_prep_args): Fix sh3 argument copy, when it is + partially on register. + (ffi_closure_helper_SYSV): Likewise. + (ffi_prep_cif_machdep): Don't set too many cif->flags. + +2005-07-20 Kaz Kojima <kkojima@gcc.gnu.org> + + * src/sh/ffi.c (ffi_call): Handle small structures correctly. + Remove empty line. + * src/sh64/ffi.c (simple_type): Remove. + (return_type): Handle small structures correctly. + (ffi_prep_args): Likewise. + (ffi_call): Likewise. + (ffi_closure_helper_SYSV): Likewise. + * src/sh64/sysv.S (ffi_call_SYSV): Handle 1, 2 and 4-byte return. + Emit position independent code if PIC and remove wrong datalabel + prefixes from EH data. + +2005-07-19 Andreas Tobler <a.tobler@schweiz.ch> + + * Makefile.am (nodist_libffi_la_SOURCES): Add POWERPC_FREEBSD. + * Makefile.in: Regenerate. + * include/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + * configure.ac: Add POWERPC_FREEBSD rules. + * configure: Regenerate. + * src/powerpc/ffitarget.h: Add POWERPC_FREEBSD rules. + (FFI_SYSV_TYPE_SMALL_STRUCT): Define. + * src/powerpc/ffi.c: Add flags to handle small structure returns + in ffi_call_SYSV. + (ffi_prep_cif_machdep): Handle small structures for SYSV 4 ABI. + Aka FFI_SYSV. + (ffi_closure_helper_SYSV): Likewise. + * src/powerpc/ppc_closure.S: Add return types for small structures. + * src/powerpc/sysv.S: Add bits to handle small structures for + final SYSV 4 ABI. + +2005-07-10 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.call/cls_5_1_byte.c: New test file. + * testsuite/libffi.call/cls_6_1_byte.c: Likewise. + * testsuite/libffi.call/cls_7_1_byte.c: Likewise. + +2005-07-05 Randolph Chung <tausq@debian.org> + + * src/pa/ffi.c (ffi_struct_type): Rename FFI_TYPE_SMALL_STRUCT1 + as FFI_TYPE_SMALL_STRUCT3. Break out handling for 5-7 byte + structures. Kill compilation warnings. + (ffi_closure_inner_LINUX): Print return values as hex in debug + message. Rename FFI_TYPE_SMALL_STRUCT1 as FFI_TYPE_SMALL_STRUCT3. + Properly handle 5-7 byte structure returns. + * src/pa/ffitarget.h (FFI_TYPE_SMALL_STRUCT1) + (FFI_TYPE_SMALL_STRUCT2): Remove. + (FFI_TYPE_SMALL_STRUCT3, FFI_TYPE_SMALL_STRUCT5) + (FFI_TYPE_SMALL_STRUCT6, FFI_TYPE_SMALL_STRUCT7): Define. + * src/pa/linux.S: Mark source file as using PA1.1 assembly. + (checksmst1, checksmst2): Remove. + (checksmst3): Optimize handling of 3-byte struct returns. + (checksmst567): Properly handle 5-7 byte struct returns. + +2005-06-15 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + PR libgcj/21943 + * src/mips/n32.S: Enforce PIC code. + * src/mips/o32.S: Likewise. + +2005-06-15 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * configure.ac: Treat i*86-*-solaris2.10 and up as X86_64. + * configure: Regenerate. + +2005-06-01 Alan Modra <amodra@bigpond.net.au> + + * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Don't use JUMPTARGET + to call ffi_closure_helper_SYSV. Append @local instead. + * src/powerpc/sysv.S (ffi_call_SYSV): Likewise for ffi_prep_args_SYSV. + +2005-05-17 Kelley Cook <kcook@gcc.gnu.org> + + * configure.ac: Use AC_C_BIGENDIAN instead of AC_C_BIGENDIAN_CROSS. + Use AC_CHECK_SIZEOF instead of AC_COMPILE_CHECK_SIZEOF. + * Makefile.am (ACLOCAL_AMFLAGS): Remove -I ../config. + * aclocal.m4, configure, fficonfig.h.in, Makefile.in, + include/Makefile.in, testsuite/Makefile.in: Regenerate. + +2005-05-09 Mike Stump <mrs@apple.com> + + * configure: Regenerate. + +2005-05-08 Richard Henderson <rth@redhat.com> + + PR libffi/21285 + * src/alpha/osf.S: Update unwind into to match code. + +2005-05-04 Andreas Degert <ad@papyrus-gmbh.de> + Richard Henderson <rth@redhat.com> + + * src/x86/ffi64.c (ffi_prep_cif_machdep): Save sse-used flag in + bit 11 of flags. + (ffi_call): Mask return type field. Pass ssecount to ffi_call_unix64. + (ffi_prep_closure): Set carry bit if sse-used flag set. + * src/x86/unix64.S (ffi_call_unix64): Add ssecount argument. + Only load sse registers if ssecount non-zero. + (ffi_closure_unix64): Only save sse registers if carry set on entry. + +2005-04-29 Ralf Corsepius <ralf.corsepius@rtems.org> + + * configure.ac: Add i*86-*-rtems*, sparc*-*-rtems*, + powerpc-*rtems*, arm*-*-rtems*, sh-*-rtems*. + * configure: Regenerate. + +2005-04-20 Hans-Peter Nilsson <hp@axis.com> + + * testsuite/lib/libffi-dg.exp (libffi-dg-test-1): In regsub use, + have Tcl8.3-compatible intermediate variable. + +2005-04-18 Simon Posnjak <simon.posnjak@siol.net> + Hans-Peter Nilsson <hp@axis.com> + + * Makefile.am: Add CRIS support. + * configure.ac: Likewise. + * Makefile.in, configure, testsuite/Makefile.in, + include/Makefile.in: Regenerate. + * src/cris: New directory. + * src/cris/ffi.c, src/cris/sysv.S, src/cris/ffitarget.h: New files. + * src/prep_cif.c (ffi_prep_cif): Wrap in #ifndef __CRIS__. + + * testsuite/lib/libffi-dg.exp (libffi-dg-test-1): Replace \n with + \r?\n in output tests. + +2005-04-12 Mike Stump <mrs@apple.com> + + * configure: Regenerate. + +2005-03-30 Hans Boehm <Hans.Boehm@hp.com> + + * src/ia64/ffitarget.h (ffi_arg): Use long long instead of DI. + +2005-03-30 Steve Ellcey <sje@cup.hp.com> + + * src/ia64/ffitarget.h (ffi_arg) ADD DI attribute. + (ffi_sarg) Ditto. + * src/ia64/unix.S (ffi_closure_unix): Extend gp + to 64 bits in ILP32 mode. + Load 64 bits even for short data. + +2005-03-23 Mike Stump <mrs@apple.com> + + * src/powerpc/darwin.S: Update for -m64 multilib. + * src/powerpc/darwin_closure.S: Likewise. + +2005-03-21 Zack Weinberg <zack@codesourcery.com> + + * configure.ac: Do not invoke TL_AC_GCC_VERSION. + Do not set tool_include_dir. + * aclocal.m4, configure, Makefile.in, testsuite/Makefile.in: + Regenerate. + * include/Makefile.am: Set gcc_version and toollibffidir. + * include/Makefile.in: Regenerate. + +2005-02-22 Andrew Haley <aph@redhat.com> + + * src/powerpc/ffi.c (ffi_prep_cif_machdep): Bump alignment to + odd-numbered register pairs for 64-bit integer types. + +2005-02-23 Andreas Tobler <a.tobler@schweiz.ch> + + PR libffi/20104 + * testsuite/libffi.call/return_ll1.c: New test case. + +2005-02-11 Janis Johnson <janis187@us.ibm.com> + + * testsuite/libffi.call/cls_align_longdouble.c: Remove dg-options. + * testsuite/libffi.call/float.c: Ditto. + * testsuite/libffi.call/float2.c: Ditto. + * testsuite/libffi.call/float3.c: Ditto. + +2005-02-08 Andreas Tobler <a.tobler@schweiz.ch> + + * src/frv/ffitarget.h: Remove PPC stuff which does not belong to frv. + +2005-01-12 Eric Botcazou <ebotcazou@libertysurf.fr> + + * testsuite/libffi.special/special.exp (cxx_options): Add + -shared-libgcc. + +2004-12-31 Richard Henderson <rth@redhat.com> + + * src/types.c (FFI_AGGREGATE_TYPEDEF): Remove. + (FFI_TYPEDEF): Rename from FFI_INTEGRAL_TYPEDEF. Replace size and + offset parameters with a type parameter; deduce size and structure + alignment. Update all users. + +2004-12-31 Richard Henderson <rth@redhat.com> + + * src/types.c (FFI_TYPE_POINTER): Define with sizeof. + (FFI_TYPE_LONGDOUBLE): Fix for ia64. + * src/ia64/ffitarget.h (struct ffi_ia64_trampoline_struct): Move + into ffi_prep_closure. + * src/ia64/ia64_flags.h, src/ia64/ffi.c, src/ia64/unix.S: Rewrite + from scratch. + +2004-12-27 Richard Henderson <rth@redhat.com> + + * src/x86/unix64.S: Fix typo in unwind info. + +2004-12-25 Richard Henderson <rth@redhat.com> + + * src/x86/ffi64.c (struct register_args): Rename from stackLayout. + (enum x86_64_reg_class): Add X86_64_COMPLEX_X87_CLASS. + (merge_classes): Check for it. + (SSE_CLASS_P): New. + (classify_argument): Pass byte_offset by value; perform all updates + inside struct case. + (examine_argument): Add classes argument; handle + X86_64_COMPLEX_X87_CLASS. + (ffi_prep_args): Merge into ... + (ffi_call): ... here. Share stack frame with ffi_call_unix64. + (ffi_prep_cif_machdep): Setup cif->flags for proper structure return. + (ffi_fill_return_value): Remove. + (ffi_prep_closure): Remove dead assert. + (ffi_closure_unix64_inner): Rename from ffi_closure_UNIX64_inner. + Rewrite to use struct register_args instead of va_list. Create + flags for handling structure returns. + * src/x86/unix64.S: Remove dead strings. + (ffi_call_unix64): Rename from ffi_call_UNIX64. Rewrite to share + stack frame with ffi_call. Handle structure returns properly. + (float2sse, floatfloat2sse, double2sse): Remove. + (sse2float, sse2double, sse2floatfloat): Remove. + (ffi_closure_unix64): Rename from ffi_closure_UNIX64. Rewrite + to handle structure returns properly. + +2004-12-08 David Edelsohn <edelsohn@gnu.org> + + * Makefile.am (AM_MAKEFLAGS): Remove duplicate LIBCFLAGS and + PICFLAG. + * Makefile.in: Regenerated. + +2004-12-02 Richard Sandiford <rsandifo@redhat.com> + + * configure.ac: Use TL_AC_GCC_VERSION to set gcc_version. + * configure, aclocal.m4, Makefile.in: Regenerate. + * include/Makefile.in, testsuite/Makefile.in: Regenerate. + +2004-11-29 Kelley Cook <kcook@gcc.gnu.org> + + * configure: Regenerate for libtool change. + +2004-11-25 Kelley Cook <kcook@gcc.gnu.org> + + * configure: Regenerate for libtool reversion. + +2004-11-24 Kelley Cook <kcook@gcc.gnu.org> + + * configure: Regenerate for libtool change. + +2004-11-23 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> + + * testsuite/lib/libffi-dg.exp: Use new procs in target-libpath.exp. + +2004-11-23 Richard Sandiford <rsandifo@redhat.com> + + * src/mips/o32.S (ffi_call_O32, ffi_closure_O32): Use jalr instead + of jal. Use an absolute encoding for the frame information. + +2004-11-23 Kelley Cook <kcook@gcc.gnu.org> + + * Makefile.am: Remove no-dependencies. Add ACLOCAL_AMFLAGS. + * acinclude.m4: Delete logic for sincludes. + * aclocal.m4, Makefile.in, configure: Regenerate. + * include/Makefile: Likewise. + * testsuite/Makefile: Likewise. + +2004-11-22 Eric Botcazou <ebotcazou@libertysurf.fr> + + * src/sparc/ffi.c (ffi_prep_closure): Align doubles and 64-bit integers + on a 8-byte boundary. + * src/sparc/v8.S (ffi_closure_v8): Reserve frame space for arguments. + +2004-10-27 Richard Earnshaw <rearnsha@arm.com> + + * src/arm/ffi.c (ffi_prep_cif_machdep): Handle functions that return + long long values. Round stack allocation to a multiple of 8 bytes + for ATPCS compatibility. + * src/arm/sysv.S (ffi_call_SYSV): Rework to avoid use of APCS register + names. Handle returning long long types. Add Thumb and interworking + support. Improve soft-float code. + +2004-10-27 Richard Earnshaw <rearnsha@arm.com> + + * testsuite/lib/libffi-db.exp (load_gcc_lib): New function. + (libffi_exit): New function. + (libffi_init): Build the testglue wrapper if needed. + +2004-10-25 Eric Botcazou <ebotcazou@libertysurf.fr> + + PR other/18138 + * testsuite/lib/libffi-dg.exp: Accept more than one multilib libgcc. + +2004-10-25 Kazuhiro Inaoka <inaoka.kazuhiro@renesas.com> + + * src/m32r/libffitarget.h (FFI_CLOSURES): Set to 0. + +2004-10-20 Kaz Kojima <kkojima@gcc.gnu.org> + + * src/sh/sysv.S (ffi_call_SYSV): Don't align for double data. + * testsuite/libffi.call/float3.c: New test case. + +2004-10-18 Kaz Kojima <kkojima@gcc.gnu.org> + + * src/sh/ffi.c (ffi_prep_closure): Set T bit in trampoline for + the function returning a structure pointed with R2. + * src/sh/sysv.S (ffi_closure_SYSV): Use R2 as the pointer to + the structure return value if T bit set. Emit position + independent code and EH data if PIC. + +2004-10-13 Kazuhiro Inaoka <inaoka.kazuhiro@renesas.com> + + * Makefile.am: Add m32r support. + * configure.ac: Likewise. + * Makefile.in: Regenerate. + * confiugre: Regenerate. + * src/types.c: Add m32r port to FFI_INTERNAL_TYPEDEF + (uint64, sint64, double, longdouble) + * src/m32r: New directory. + * src/m32r/ffi.c: New file. + * src/m32r/sysv.S: Likewise. + * src/m32r/ffitarget.h: Likewise. + +2004-10-02 Kaz Kojima <kkojima@gcc.gnu.org> + + * testsuite/libffi.call/negint.c: New test case. + +2004-09-14 H.J. Lu <hongjiu.lu@intel.com> + + PR libgcj/17465 + * testsuite/lib/libffi-dg.exp: Don't use global ld_library_path. + Set up LD_LIBRARY_PATH, SHLIB_PATH, LD_LIBRARYN32_PATH, + LD_LIBRARY64_PATH, LD_LIBRARY_PATH_32, LD_LIBRARY_PATH_64 and + DYLD_LIBRARY_PATH. + +2004-09-05 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.call/many_win32.c: Remove whitespaces. + * testsuite/libffi.call/promotion.c: Likewise. + * testsuite/libffi.call/return_ll.c: Remove unused var. Cleanup + whitespaces. + * testsuite/libffi.call/return_sc.c: Likewise. + * testsuite/libffi.call/return_uc.c: Likewise. + +2004-09-05 Andreas Tobler <a.tobler@schweiz.ch> + + * src/powerpc/darwin.S: Fix comments and identation. + * src/powerpc/darwin_closure.S: Likewise. + +2004-09-02 Andreas Tobler <a.tobler@schweiz.ch> + + * src/powerpc/ffi_darwin.c: Add flag for longdouble return values. + (ffi_prep_args): Handle longdouble arguments. + (ffi_prep_cif_machdep): Set flags for longdouble. Calculate space for + longdouble. + (ffi_closure_helper_DARWIN): Add closure handling for longdouble. + * src/powerpc/darwin.S (_ffi_call_DARWIN): Add handling of longdouble + values. + * src/powerpc/darwin_closure.S (_ffi_closure_ASM): Likewise. + * src/types.c: Defined longdouble size and alignment for darwin. + +2004-09-02 Andreas Tobler <a.tobler@schweiz.ch> + + * src/powerpc/aix.S: Remove whitespaces. + * src/powerpc/aix_closure.S: Likewise. + * src/powerpc/asm.h: Likewise. + * src/powerpc/ffi.c: Likewise. + * src/powerpc/ffitarget.h: Likewise. + * src/powerpc/linux64.S: Likewise. + * src/powerpc/linux64_closure.S: Likewise. + * src/powerpc/ppc_closure.S: Likewise. + * src/powerpc/sysv.S: Likewise. + +2004-08-30 Anthony Green <green@redhat.com> + + * Makefile.am: Add frv support. + * Makefile.in, testsuite/Makefile.in: Rebuilt. + * configure.ac: Read configure.host. + * configure.in: Read configure.host. + * configure.host: New file. frv-elf needs libgloss. + * include/ffi.h.in: Force ffi_closure to have a nice big (8) + alignment. This is needed to frv and shouldn't harm the others. + * include/ffi_common.h (ALIGN_DOWN): New macro. + * src/frv/ffi.c, src/frv/ffitarget.h, src/frv/eabi.S: New files. + +2004-08-24 David Daney <daney@avtrex.com> + + * testsuite/libffi.call/closure_fn0.c: Xfail mips64* instead of mips*. + * testsuite/libffi.call/closure_fn1.c: Likewise. + * testsuite/libffi.call/closure_fn2.c Likewise. + * testsuite/libffi.call/closure_fn3.c: Likewise. + * testsuite/libffi.call/closure_fn4.c: Likewise. + * testsuite/libffi.call/closure_fn5.c: Likewise. + * testsuite/libffi.call/cls_18byte.c: Likewise. + * testsuite/libffi.call/cls_19byte.c: Likewise. + * testsuite/libffi.call/cls_1_1byte.c: Likewise. + * testsuite/libffi.call/cls_20byte.c: Likewise. + * testsuite/libffi.call/cls_20byte1.c: Likewise. + * testsuite/libffi.call/cls_24byte.c: Likewise. + * testsuite/libffi.call/cls_2byte.c: Likewise. + * testsuite/libffi.call/cls_3_1byte.c: Likewise. + * testsuite/libffi.call/cls_3byte1.c: Likewise. + * testsuite/libffi.call/cls_3byte2.c: Likewise. + * testsuite/libffi.call/cls_4_1byte.c: Likewise. + * testsuite/libffi.call/cls_4byte.c: Likewise. + * testsuite/libffi.call/cls_64byte.c: Likewise. + * testsuite/libffi.call/cls_6byte.c: Likewise. + * testsuite/libffi.call/cls_7byte.c: Likewise. + * testsuite/libffi.call/cls_8byte.c: Likewise. + * testsuite/libffi.call/cls_9byte1.c: Likewise. + * testsuite/libffi.call/cls_9byte2.c: Likewise. + * testsuite/libffi.call/cls_align_double.c: Likewise. + * testsuite/libffi.call/cls_align_float.c: Likewise. + * testsuite/libffi.call/cls_align_longdouble.c: Likewise. + * testsuite/libffi.call/cls_align_pointer.c: Likewise. + * testsuite/libffi.call/cls_align_sint16.c: Likewise. + * testsuite/libffi.call/cls_align_sint32.c: Likewise. + * testsuite/libffi.call/cls_align_sint64.c: Likewise. + * testsuite/libffi.call/cls_align_uint16.c: Likewise. + * testsuite/libffi.call/cls_align_uint32.c: Likewise. + * testsuite/libffi.call/cls_align_uint64.c: Likewise. + * testsuite/libffi.call/cls_double.c: Likewise. + * testsuite/libffi.call/cls_float.c: Likewise. + * testsuite/libffi.call/cls_multi_schar.c: Likewise. + * testsuite/libffi.call/cls_multi_sshort.c: Likewise. + * testsuite/libffi.call/cls_multi_sshortchar.c: Likewise. + * testsuite/libffi.call/cls_multi_uchar.c: Likewise. + * testsuite/libffi.call/cls_multi_ushort.c: Likewise. + * testsuite/libffi.call/cls_multi_ushortchar.c: Likewise. + * testsuite/libffi.call/cls_schar.c: Likewise. + * testsuite/libffi.call/cls_sint.c: Likewise. + * testsuite/libffi.call/cls_sshort.c: Likewise. + * testsuite/libffi.call/cls_uchar.c: Likewise. + * testsuite/libffi.call/cls_uint.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/cls_ushort.c: Likewise. + * testsuite/libffi.call/nested_struct.c: Likewise. + * testsuite/libffi.call/nested_struct1.c: Likewise. + * testsuite/libffi.call/nested_struct2.c: Likewise. + * testsuite/libffi.call/nested_struct3.c: Likewise. + * testsuite/libffi.call/problem1.c: Likewise. + * testsuite/libffi.special/unwindtest.cc: Likewise. + * testsuite/libffi.call/cls_12byte.c: Likewise and set return value + to zero. + * testsuite/libffi.call/cls_16byte.c: Likewise. + * testsuite/libffi.call/cls_5byte.c: Likewise. + +2004-08-23 David Daney <daney@avtrex.com> + + PR libgcj/13141 + * src/mips/ffitarget.h (FFI_O32_SOFT_FLOAT): New ABI. + * src/mips/ffi.c (ffi_prep_args): Fix alignment calculation. + (ffi_prep_cif_machdep): Handle FFI_O32_SOFT_FLOAT floating point + parameters and return types. + (ffi_call): Handle FFI_O32_SOFT_FLOAT ABI. + (ffi_prep_closure): Ditto. + (ffi_closure_mips_inner_O32): Handle FFI_O32_SOFT_FLOAT ABI, fix + alignment calculations. + * src/mips/o32.S (ffi_closure_O32): Don't use floating point + instructions if FFI_O32_SOFT_FLOAT, make stack frame ABI compliant. + +2004-08-14 Casey Marshall <csm@gnu.org> + + * src/mips/ffi.c (ffi_pref_cif_machdep): set `cif->flags' to + contain `FFI_TYPE_UINT64' as return type for any 64-bit + integer (O32 ABI only). + (ffi_prep_closure): new function. + (ffi_closure_mips_inner_O32): new function. + * src/mips/ffitarget.h: Define `FFI_CLOSURES' and + `FFI_TRAMPOLINE_SIZE' appropriately if the ABI is o32. + * src/mips/o32.S (ffi_call_O32): add labels for .eh_frame. Return + 64 bit integers correctly. + (ffi_closure_O32): new function. + Added DWARF-2 unwind info for both functions. + +2004-08-10 Andrew Haley <aph@redhat.com> + + * src/x86/ffi64.c (ffi_prep_args ): 8-align all stack arguments. + +2004-08-01 Robert Millan <robertmh@gnu.org> + + * configure.ac: Detect knetbsd-gnu and kfreebsd-gnu. + * configure: Regenerate. + +2004-07-30 Maciej W. Rozycki <macro@linux-mips.org> + + * acinclude.m4 (AC_FUNC_MMAP_BLACKLIST): Check for <sys/mman.h> + and mmap() explicitly instead of relying on preset autoconf cache + variables. + * aclocal.m4: Regenerate. + * configure: Regenerate. + +2004-07-11 Ulrich Weigand <uweigand@de.ibm.com> + + * src/s390/ffi.c (ffi_prep_args): Fix C aliasing violation. + (ffi_check_float_struct): Remove unused prototype. + +2004-06-30 Geoffrey Keating <geoffk@apple.com> + + * src/powerpc/ffi_darwin.c (flush_icache): ';' is a comment + character on Darwin, use '\n\t' instead. + +2004-06-26 Matthias Klose <doko@debian.org> + + * libtool-version: Fix typo in revision/age. + +2004-06-17 Matthias Klose <doko@debian.org> + + * libtool-version: New. + * Makefile.am (libffi_la_LDFLAGS): Use -version-info for soname. + * Makefile.in: Regenerate. + +2004-06-15 Paolo Bonzini <bonzini@gnu.org> + + * Makefile.am: Remove useless multilib rules. + * Makefile.in: Regenerate. + * aclocal.m4: Regenerate with automake 1.8.5. + * configure.ac: Remove useless multilib configury. + * configure: Regenerate. + +2004-06-15 Paolo Bonzini <bonzini@gnu.org> + + * .cvsignore: New file. + +2004-06-10 Jakub Jelinek <jakub@redhat.com> + + * src/ia64/unix.S (ffi_call_unix): Insert group barrier break + fp_done. + (ffi_closure_UNIX): Fix f14/f15 adjustment if FLOAT_SZ is ever + changed from 8. + +2004-06-06 Sean McNeil <sean@mcneil.com> + + * configure.ac: Add x86_64-*-freebsd* support. + * configure: Regenerate. + +2004-04-26 Joe Buck <jbuck@welsh-buck.org> + + Bug 15093 + * configure.ac: Test for existence of mmap and sys/mman.h before + checking blacklist. Fix suggested by Jim Wilson. + * configure: Regenerate. + +2004-04-26 Matt Austern <austern@apple.com> + + * src/powerpc/darwin.S: Go through a non-lazy pointer for initial + FDE location. + * src/powerpc/darwin_closure.S: Likewise. + +2004-04-24 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.call/cls_multi_schar.c (main): Fix initialization + error. Reported by Thomas Heller <theller@python.net>. + * testsuite/libffi.call/cls_multi_sshort.c (main): Likewise. + * testsuite/libffi.call/cls_multi_ushort.c (main): Likewise. + +2004-03-20 Matthias Klose <doko@debian.org> + + * src/pa/linux.S: Fix typo. + +2004-03-19 Matthias Klose <doko@debian.org> + + * Makefile.am: Update. + * Makefile.in: Regenerate. + * src/pa/ffi.h.in: Remove. + * src/pa/ffitarget.h: New file. + +2004-02-10 Randolph Chung <tausq@debian.org> + + * Makefile.am: Add PA support. + * Makefile.in: Regenerate. + * include/Makefile.in: Regenerate. + * configure.ac: Add PA target. + * configure: Regenerate. + * src/pa/ffi.c: New file. + * src/pa/ffi.h.in: Add PA support. + * src/pa/linux.S: New file. + * prep_cif.c: Add PA support. + +2004-03-16 Hosaka Yuji <hos@tamanegi.org> + + * src/types.c: Fix alignment size of X86_WIN32 case int64 and + double. + * src/x86/ffi.c (ffi_prep_args): Replace ecif->cif->rtype->type + with ecif->cif->flags. + (ffi_call, ffi_prep_incoming_args_SYSV): Replace cif->rtype->type + with cif->flags. + (ffi_prep_cif_machdep): Add X86_WIN32 struct case. + (ffi_closure_SYSV): Add 1 or 2-bytes struct case for X86_WIN32. + * src/x86/win32.S (retstruct1b, retstruct2b, sc_retstruct1b, + sc_retstruct2b): Add for 1 or 2-bytes struct case. + +2004-03-15 Kelley Cook <kcook@gcc.gnu.org> + + * configure.in: Rename file to ... + * configure.ac: ... this. + * fficonfig.h.in: Regenerate. + * Makefile.in: Regenerate. + * include/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2004-03-12 Matt Austern <austern@apple.com> + + * src/powerpc/darwin.S: Fix EH information so it corresponds to + changes in EH format resulting from addition of linkonce support. + * src/powerpc/darwin_closure.S: Likewise. + +2004-03-11 Andreas Tobler <a.tobler@schweiz.ch> + Paolo Bonzini <bonzini@gnu.org> + + * Makefile.am (AUTOMAKE_OPTIONS): Set them. + Remove VPATH. Remove rules for object files. Remove multilib support. + (AM_CCASFLAGS): Add. + * configure.in (AC_CONFIG_HEADERS): Relace AM_CONFIG_HEADER. + (AC_PREREQ): Bump version to 2.59. + (AC_INIT): Fill with version info and bug address. + (ORIGINAL_LD_FOR_MULTILIBS): Remove. + (AM_ENABLE_MULTILIB): Use this instead of AC_ARG_ENABLE. + De-precious CC so that the right flags are passed down to multilibs. + (AC_MSG_ERROR): Replace obsolete macro AC_ERROR. + (AC_CONFIG_FILES): Replace obsolete macro AC_LINK_FILES. + (AC_OUTPUT): Reorganize the output with AC_CONFIG_COMMANDS. + * configure: Rebuilt. + * aclocal.m4: Likewise. + * Makefile.in, include/Makefile.in, testsuite/Makefile.in: Likewise. + * fficonfig.h.in: Likewise. + +2004-03-11 Andreas Schwab <schwab@suse.de> + + * src/ia64/ffi.c (ffi_prep_incoming_args_UNIX): Get floating point + arguments from fp registers only for the first 8 parameter slots. + Don't convert a float parameter when passed in memory. + +2004-03-09 Hans-Peter Nilsson <hp@axis.com> + + * configure: Regenerate for config/accross.m4 correction. + +2004-02-25 Matt Kraai <kraai@alumni.cmu.edu> + + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Change + ecif->cif->bytes to bytes. + (ffi_prep_cif_machdep): Add braces around nested if statement. + +2004-02-09 Alan Modra <amodra@bigpond.net.au> + + * src/types.c (pointer): POWERPC64 has 8 byte pointers. + + * src/powerpc/ffi.c (ffi_prep_args64): Correct long double handling. + (ffi_closure_helper_LINUX64): Fix typo. + * testsuite/libffi.call/cls_align_longdouble.c: Pass -mlong-double-128 + for powerpc64-*-*. + * testsuite/libffi.call/float.c: Likewise. + * testsuite/libffi.call/float2.c: Likewise. + +2004-02-08 Alan Modra <amodra@bigpond.net.au> + + * src/powerpc/ffi.c (ffi_prep_cif_machdep <FFI_LINUX64>): Correct + long double function return and long double arg handling. + (ffi_closure_helper_LINUX64): Formatting. Delete unused "ng" var. + Use "end_pfr" instead of "nf". Correct long double handling. + Localise "temp". + * src/powerpc/linux64.S (ffi_call_LINUX64): Save f2 long double + return value. + * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Allocate + space for long double return value. Adjust stack frame and offsets. + Load f2 long double return. + +2004-02-07 Alan Modra <amodra@bigpond.net.au> + + * src/types.c: Use 16 byte long double for POWERPC64. + +2004-01-25 Eric Botcazou <ebotcazou@libertysurf.fr> + + * src/sparc/ffi.c (ffi_prep_args_v9): Shift the parameter array + when the structure return address is passed in %o0. + (ffi_V9_return_struct): Rename into ffi_v9_layout_struct. + (ffi_v9_layout_struct): Align the field following a nested structure + on a word boundary. Use memmove instead of memcpy. + (ffi_call): Update call to ffi_V9_return_struct. + (ffi_prep_closure): Define 'ctx' only for V8. + (ffi_closure_sparc_inner): Clone into ffi_closure_sparc_inner_v8 + and ffi_closure_sparc_inner_v9. + (ffi_closure_sparc_inner_v8): Return long doubles by reference. + Always skip the structure return address. For structures and long + doubles, copy the argument directly. + (ffi_closure_sparc_inner_v9): Skip the structure return address only + if required. Shift the maximum floating-point slot accordingly. For + big structures, copy the argument directly; otherwise, left-justify the + argument and call ffi_v9_layout_struct to lay out the structure on + the stack. + * src/sparc/v8.S: Undef STACKFRAME before defining it. + (ffi_closure_v8): Pass the structure return address. Update call to + ffi_closure_sparc_inner_v8. Short-circuit FFI_TYPE_INT handling. + Skip the 'unimp' insn when returning long doubles and structures. + * src/sparc/v9.S: Undef STACKFRAME before defining it. + (ffi_closure_v9): Increase the frame size by 2 words. Short-circuit + FFI_TYPE_INT handling. Load structures both in integers and + floating-point registers on return. + * README: Update status of the SPARC port. + +2004-01-24 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.call/pyobjc-tc.c (main): Treat result value + as of type ffi_arg. + * testsuite/libffi.call/struct3.c (main): Fix CHECK. + +2004-01-22 Ulrich Weigand <uweigand@de.ibm.com> + + * testsuite/libffi.call/cls_uint.c (cls_ret_uint_fn): Treat result + value as of type ffi_arg, not unsigned int. + +2004-01-21 Michael Ritzert <ritzert@t-online.de> + + * ffi64.c (ffi_prep_args): Cast the RHS of an assignment instead + of the LHS. + +2004-01-12 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/lib/libffi-dg.exp: Set LD_LIBRARY_PATH_32 for + Solaris. + +2004-01-08 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * testsuite/libffi.call/ffitest.h (allocate_mmap): Cast MAP_FAILED + to void *. + +2003-12-10 Richard Henderson <rth@redhat.com> + + * testsuite/libffi.call/cls_align_pointer.c: Cast pointers to + size_t instead of int. + +2003-12-04 Hosaka Yuji <hos@tamanegi.org> + + * testsuite/libffi.call/many_win32.c: Include <float.h>. + * testsuite/libffi.call/many_win32.c (main): Replace variable + int i with unsigned long ul. + + * testsuite/libffi.call/cls_align_uint64.c: New test case. + * testsuite/libffi.call/cls_align_sint64.c: Likewise. + * testsuite/libffi.call/cls_align_uint32.c: Likewise. + * testsuite/libffi.call/cls_align_sint32.c: Likewise. + * testsuite/libffi.call/cls_align_uint16.c: Likewise. + * testsuite/libffi.call/cls_align_sint16.c: Likewise. + * testsuite/libffi.call/cls_align_float.c: Likewise. + * testsuite/libffi.call/cls_align_double.c: Likewise. + * testsuite/libffi.call/cls_align_longdouble.c: Likewise. + * testsuite/libffi.call/cls_align_pointer.c: Likewise. + +2003-12-02 Hosaka Yuji <hos@tamanegi.org> + + PR other/13221 + * src/x86/ffi.c (ffi_prep_args, ffi_prep_incoming_args_SYSV): + Align arguments to 32 bits. + +2003-12-01 Andreas Tobler <a.tobler@schweiz.ch> + + PR other/13221 + * testsuite/libffi.call/cls_multi_sshort.c: New test case. + * testsuite/libffi.call/cls_multi_sshortchar.c: Likewise. + * testsuite/libffi.call/cls_multi_uchar.c: Likewise. + * testsuite/libffi.call/cls_multi_schar.c: Likewise. + * testsuite/libffi.call/cls_multi_ushortchar.c: Likewise. + * testsuite/libffi.call/cls_multi_ushort.c: Likewise. + + * testsuite/libffi.special/unwindtest.cc: Cosmetics. + +2003-11-26 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * testsuite/libffi.call/ffitest.h: Include <fcntl.h>. + * testsuite/libffi.special/ffitestcxx.h: Likewise. + +2003-11-22 Andreas Tobler <a.tobler@schweiz.ch> + + * Makefile.in: Rebuilt. + * configure: Likewise. + * testsuite/libffi.special/unwindtest.cc: Convert the mmap to + the right type. + +2003-11-21 Andreas Jaeger <aj@suse.de> + Andreas Tobler <a.tobler@schweiz.ch> + + * acinclude.m4: Add AC_FUNC_MMAP_BLACKLIST. + * configure.in: Call AC_FUNC_MMAP_BLACKLIST. + * Makefile.in: Rebuilt. + * aclocal.m4: Likewise. + * configure: Likewise. + * fficonfig.h.in: Likewise. + * testsuite/lib/libffi-dg.exp: Add include dir. + * testsuite/libffi.call/ffitest.h: Add MMAP definitions. + * testsuite/libffi.special/ffitestcxx.h: Likewise. + * testsuite/libffi.call/closure_fn0.c: Use MMAP functionality + for ffi_closure if available. + * testsuite/libffi.call/closure_fn1.c: Likewise. + * testsuite/libffi.call/closure_fn2.c: Likewise. + * testsuite/libffi.call/closure_fn3.c: Likewise. + * testsuite/libffi.call/closure_fn4.c: Likewise. + * testsuite/libffi.call/closure_fn5.c: Likewise. + * testsuite/libffi.call/cls_12byte.c: Likewise. + * testsuite/libffi.call/cls_16byte.c: Likewise. + * testsuite/libffi.call/cls_18byte.c: Likewise. + * testsuite/libffi.call/cls_19byte.c: Likewise. + * testsuite/libffi.call/cls_1_1byte.c: Likewise. + * testsuite/libffi.call/cls_20byte.c: Likewise. + * testsuite/libffi.call/cls_20byte1.c: Likewise. + * testsuite/libffi.call/cls_24byte.c: Likewise. + * testsuite/libffi.call/cls_2byte.c: Likewise. + * testsuite/libffi.call/cls_3_1byte.c: Likewise. + * testsuite/libffi.call/cls_3byte1.c: Likewise. + * testsuite/libffi.call/cls_3byte2.c: Likewise. + * testsuite/libffi.call/cls_4_1byte.c: Likewise. + * testsuite/libffi.call/cls_4byte.c: Likewise. + * testsuite/libffi.call/cls_5byte.c: Likewise. + * testsuite/libffi.call/cls_64byte.c: Likewise. + * testsuite/libffi.call/cls_6byte.c: Likewise. + * testsuite/libffi.call/cls_7byte.c: Likewise. + * testsuite/libffi.call/cls_8byte.c: Likewise. + * testsuite/libffi.call/cls_9byte1.c: Likewise. + * testsuite/libffi.call/cls_9byte2.c: Likewise. + * testsuite/libffi.call/cls_double.c: Likewise. + * testsuite/libffi.call/cls_float.c: Likewise. + * testsuite/libffi.call/cls_schar.c: Likewise. + * testsuite/libffi.call/cls_sint.c: Likewise. + * testsuite/libffi.call/cls_sshort.c: Likewise. + * testsuite/libffi.call/cls_uchar.c: Likewise. + * testsuite/libffi.call/cls_uint.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/cls_ushort.c: Likewise. + * testsuite/libffi.call/nested_struct.c: Likewise. + * testsuite/libffi.call/nested_struct1.c: Likewise. + * testsuite/libffi.call/nested_struct2.c: Likewise. + * testsuite/libffi.call/nested_struct3.c: Likewise. + * testsuite/libffi.call/problem1.c: Likewise. + * testsuite/libffi.special/unwindtest.cc: Likewise. + +2003-11-20 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/lib/libffi-dg.exp: Make the -lgcc_s conditional. + +2003-11-19 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/lib/libffi-dg.exp: Add DYLD_LIBRARY_PATH for darwin. + Add -lgcc_s to additional flags. + +2003-11-12 Andreas Tobler <a.tobler@schweiz.ch> + + * configure.in, include/Makefile.am: PR libgcj/11147, install + the ffitarget.h header file in a gcc versioned and target + dependent place. + * configure: Regenerated. + * Makefile.in, include/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + +2003-11-09 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.call/closure_fn0.c: Print result and check + with dg-output to make debugging easier. + * testsuite/libffi.call/closure_fn1.c: Likewise. + * testsuite/libffi.call/closure_fn2.c: Likewise. + * testsuite/libffi.call/closure_fn3.c: Likewise. + * testsuite/libffi.call/closure_fn4.c: Likewise. + * testsuite/libffi.call/closure_fn5.c: Likewise. + * testsuite/libffi.call/cls_12byte.c: Likewise. + * testsuite/libffi.call/cls_16byte.c: Likewise. + * testsuite/libffi.call/cls_18byte.c: Likewise. + * testsuite/libffi.call/cls_19byte.c: Likewise. + * testsuite/libffi.call/cls_1_1byte.c: Likewise. + * testsuite/libffi.call/cls_20byte.c: Likewise. + * testsuite/libffi.call/cls_20byte1.c: Likewise. + * testsuite/libffi.call/cls_24byte.c: Likewise. + * testsuite/libffi.call/cls_2byte.c: Likewise. + * testsuite/libffi.call/cls_3_1byte.c: Likewise. + * testsuite/libffi.call/cls_3byte1.c: Likewise. + * testsuite/libffi.call/cls_3byte2.c: Likewise. + * testsuite/libffi.call/cls_4_1byte.c: Likewise. + * testsuite/libffi.call/cls_4byte.c: Likewise. + * testsuite/libffi.call/cls_5byte.c: Likewise. + * testsuite/libffi.call/cls_64byte.c: Likewise. + * testsuite/libffi.call/cls_6byte.c: Likewise. + * testsuite/libffi.call/cls_7byte.c: Likewise. + * testsuite/libffi.call/cls_8byte.c: Likewise. + * testsuite/libffi.call/cls_9byte1.c: Likewise. + * testsuite/libffi.call/cls_9byte2.c: Likewise. + * testsuite/libffi.call/cls_double.c: Likewise. + * testsuite/libffi.call/cls_float.c: Likewise. + * testsuite/libffi.call/cls_schar.c: Likewise. + * testsuite/libffi.call/cls_sint.c: Likewise. + * testsuite/libffi.call/cls_sshort.c: Likewise. + * testsuite/libffi.call/cls_uchar.c: Likewise. + * testsuite/libffi.call/cls_uint.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/cls_ushort.c: Likewise. + * testsuite/libffi.call/problem1.c: Likewise. + + * testsuite/libffi.special/unwindtest.cc: Make ffi_closure + static. + +2003-11-08 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.call/cls_9byte2.c: New test case. + * testsuite/libffi.call/cls_9byte1.c: Likewise. + * testsuite/libffi.call/cls_64byte.c: Likewise. + * testsuite/libffi.call/cls_20byte1.c: Likewise. + * testsuite/libffi.call/cls_19byte.c: Likewise. + * testsuite/libffi.call/cls_18byte.c: Likewise. + * testsuite/libffi.call/closure_fn4.c: Likewise. + * testsuite/libffi.call/closure_fn5.c: Likewise. + * testsuite/libffi.call/cls_schar.c: Likewise. + * testsuite/libffi.call/cls_sint.c: Likewise. + * testsuite/libffi.call/cls_sshort.c: Likewise. + * testsuite/libffi.call/nested_struct2.c: Likewise. + * testsuite/libffi.call/nested_struct3.c: Likewise. + +2003-11-08 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.call/cls_double.c: Do a check on the result. + * testsuite/libffi.call/cls_uchar.c: Likewise. + * testsuite/libffi.call/cls_uint.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/cls_ushort.c: Likewise. + * testsuite/libffi.call/return_sc.c: Cleanup whitespaces. + +2003-11-06 Andreas Tobler <a.tobler@schweiz.ch> + + * src/prep_cif.c (ffi_prep_cif): Move the validity check after + the initialization. + +2003-10-23 Andreas Tobler <a.tobler@schweiz.ch> + + * src/java_raw_api.c (ffi_java_ptrarray_to_raw): Replace + FFI_ASSERT(FALSE) with FFI_ASSERT(0). + +2003-10-22 David Daney <ddaney@avtrex.com> + + * src/mips/ffitarget.h: Replace undefined UINT32 and friends with + __attribute__((__mode__(__SI__))) and friends. + +2003-10-22 Andreas Schwab <schwab@suse.de> + + * src/ia64/ffi.c: Replace FALSE/TRUE with false/true. + +2003-10-21 Andreas Tobler <a.tobler@schweiz.ch> + + * configure.in: AC_LINK_FILES(ffitarget.h). + * configure: Regenerate. + * Makefile.in: Likewise. + * include/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + * fficonfig.h.in: Likewise. + +2003-10-21 Paolo Bonzini <bonzini@gnu.org> + Richard Henderson <rth@redhat.com> + + Avoid that ffi.h includes fficonfig.h. + + * Makefile.am (EXTRA_DIST): Include ffitarget.h files + (TARGET_SRC_MIPS_GCC): Renamed to TARGET_SRC_MIPS_IRIX. + (TARGET_SRC_MIPS_SGI): Removed. + (MIPS_GCC): Renamed to TARGET_SRC_MIPS_IRIX. + (MIPS_SGI): Removed. + (CLEANFILES): Removed. + (mostlyclean-am, clean-am, mostlyclean-sub, clean-sub): New + targets. + * acconfig.h: Removed. + * configure.in: Compute sizeofs only for double and long double. + Use them to define and subst HAVE_LONG_DOUBLE. Include comments + into AC_DEFINE instead of using acconfig.h. Create + include/ffitarget.h instead of include/fficonfig.h. Rename + MIPS_GCC to MIPS_IRIX, drop MIPS_SGI since we are in gcc's tree. + AC_DEFINE EH_FRAME_FLAGS. + * include/Makefile.am (DISTCLEANFILES): New automake macro. + (hack_DATA): Add ffitarget.h. + * include/ffi.h.in: Remove all system specific definitions. + Declare raw API even if it is not installed, why bother? + Use limits.h instead of SIZEOF_* to define ffi_type_*. Do + not define EH_FRAME_FLAGS, it is in fficonfig.h now. Include + ffitarget.h instead of fficonfig.h. Remove ALIGN macro. + (UINT_ARG, INT_ARG): Removed, use ffi_arg and ffi_sarg instead. + * include/ffi_common.h (bool): Do not define. + (ffi_assert): Accept failed assertion. + (ffi_type_test): Return void and accept file/line. + (FFI_ASSERT): Pass stringized failed assertion. + (FFI_ASSERT_AT): New macro. + (FFI_ASSERT_VALID_TYPE): New macro. + (UINT8, SINT8, UINT16, SINT16, UINT32, SINT32, + UINT64, SINT64): Define here with gcc's __attribute__ macro + instead of in ffi.h + (FLOAT32, ALIGN): Define here instead of in ffi.h + * include/ffi-mips.h: Removed. Its content moved to + src/mips/ffitarget.h after separating assembly and C sections. + * src/alpha/ffi.c, src/alpha/ffi.c, src/java_raw_api.c + src/prep_cif.c, src/raw_api.c, src/ia64/ffi.c, + src/mips/ffi.c, src/mips/n32.S, src/mips/o32.S, + src/mips/ffitarget.h, src/sparc/ffi.c, src/x86/ffi64.c: + SIZEOF_ARG -> FFI_SIZEOF_ARG. + * src/ia64/ffi.c: Include stdbool.h (provided by GCC 2.95+). + * src/debug.c (ffi_assert): Accept stringized failed assertion. + (ffi_type_test): Rewritten. + * src/prep-cif.c (initialize_aggregate, ffi_prep_cif): Call + FFI_ASSERT_VALID_TYPE. + * src/alpha/ffitarget.h, src/arm/ffitarget.h, + src/ia64/ffitarget.h, src/m68k/ffitarget.h, + src/mips/ffitarget.h, src/powerpc/ffitarget.h, + src/s390/ffitarget.h, src/sh/ffitarget.h, + src/sh64/ffitarget.h, src/sparc/ffitarget.h, + src/x86/ffitarget.h: New files. + * src/alpha/osf.S, src/arm/sysv.S, src/ia64/unix.S, + src/m68k/sysv.S, src/mips/n32.S, src/mips/o32.S, + src/powerpc/aix.S, src/powerpc/darwin.S, + src/powerpc/ffi_darwin.c, src/powerpc/linux64.S, + src/powerpc/linux64_closure.S, src/powerpc/ppc_closure.S, + src/powerpc/sysv.S, src/s390/sysv.S, src/sh/sysv.S, + src/sh64/sysv.S, src/sparc/v8.S, src/sparc/v9.S, + src/x86/sysv.S, src/x86/unix64.S, src/x86/win32.S: + include fficonfig.h + +2003-10-20 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * src/mips/ffi.c: Use _ABIN32, _ABIO32 instead of external + _MIPS_SIM_NABI32, _MIPS_SIM_ABI32. + +2003-10-19 Andreas Tobler <a.tobler@schweiz.ch> + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Declare bytes again. + Used when FFI_DEBUG = 1. + +2003-10-14 Alan Modra <amodra@bigpond.net.au> + + * src/types.c (double, longdouble): Default POWERPC64 to 8 byte size + and align. + +2003-10-06 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * include/ffi_mips.h: Define FFI_MIPS_N32 for N32/N64 ABIs, + FFI_MIPS_O32 for O32 ABI. + +2003-10-01 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/lib/libffi-dg.exp: Set LD_LIBRARY_PATH_64 for + SPARC64. Cleanup whitespaces. + +2003-09-19 Andreas Tobler <a.tobler@schweiz.ch> + + * testsuite/libffi.call/closure_fn0.c: Xfail mips, arm, + strongarm, xscale. Cleanup whitespaces. + * testsuite/libffi.call/closure_fn1.c: Likewise. + * testsuite/libffi.call/closure_fn2.c: Likewise. + * testsuite/libffi.call/closure_fn3.c: Likewise. + * testsuite/libffi.call/cls_12byte.c: Likewise. + * testsuite/libffi.call/cls_16byte.c: Likewise. + * testsuite/libffi.call/cls_1_1byte.c: Likewise. + * testsuite/libffi.call/cls_20byte.c: Likewise. + * testsuite/libffi.call/cls_24byte.c: Likewise. + * testsuite/libffi.call/cls_2byte.c: Likewise. + * testsuite/libffi.call/cls_3_1byte.c: Likewise. + * testsuite/libffi.call/cls_3byte1.c: Likewise. + * testsuite/libffi.call/cls_3byte2.c: Likewise. + * testsuite/libffi.call/cls_4_1byte.c: Likewise. + * testsuite/libffi.call/cls_4byte.c: Likewise. + * testsuite/libffi.call/cls_5byte.c: Likewise. + * testsuite/libffi.call/cls_6byte.c: Likewise. + * testsuite/libffi.call/cls_7byte.c: Likewise. + * testsuite/libffi.call/cls_8byte.c: Likewise. + * testsuite/libffi.call/cls_double.c: Likewise. + * testsuite/libffi.call/cls_float.c: Likewise. + * testsuite/libffi.call/cls_uchar.c: Likewise. + * testsuite/libffi.call/cls_uint.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/cls_ushort.c: Likewise. + * testsuite/libffi.call/nested_struct.c: Likewise. + * testsuite/libffi.call/nested_struct1.c: Likewise. + * testsuite/libffi.call/problem1.c: Likewise. + * testsuite/libffi.special/unwindtest.cc: Likewise. + * testsuite/libffi.call/pyobjc-tc.c: Cleanup whitespaces. + +2003-09-18 David Edelsohn <edelsohn@gnu.org> + + * src/powerpc/aix.S: Cleanup whitespaces. + * src/powerpc/aix_closure.S: Likewise. + +2003-09-18 Andreas Tobler <a.tobler@schweiz.ch> + + * src/powerpc/darwin.S: Cleanup whitespaces, comment formatting. + * src/powerpc/darwin_closure.S: Likewise. + * src/powerpc/ffi_darwin.c: Likewise. + +2003-09-18 Andreas Tobler <a.tobler@schweiz.ch> + David Edelsohn <edelsohn@gnu.org> + + * src/types.c (double): Add AIX and Darwin to the right TYPEDEF. + * src/powerpc/aix_closure.S: Remove the pointer to the outgoing + parameter stack. + * src/powerpc/darwin_closure.S: Likewise. + * src/powerpc/ffi_darwin.c (ffi_prep_args): Handle structures + according to the Darwin/AIX ABI. + (ffi_prep_cif_machdep): Likewise. + (ffi_closure_helper_DARWIN): Likewise. + Remove the outgoing parameter stack logic. Simplify the evaluation + of the different CASE types. + (ffi_prep_clousure): Avoid the casts on lvalues. Change the branch + statement in the trampoline code. + +2003-09-18 Kaz Kojima <kkojima@gcc.gnu.org> + + * src/sh/ffi.c (ffi_prep_args): Take account into the alignement + for the register size. + (ffi_closure_helper_SYSV): Handle the structure return value + address correctly. + (ffi_closure_helper_SYSV): Return the appropriate type when + the registers are used for the structure return value. + * src/sh/sysv.S (ffi_closure_SYSV): Fix the stack layout for + the 64-bit return value. Update copyright years. + +2003-09-17 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * testsuite/lib/libffi-dg.exp (libffi_target_compile): Search in + srcdir for ffi_mips.h. + +2003-09-12 Alan Modra <amodra@bigpond.net.au> + + * src/prep_cif.c (initialize_aggregate): Include tail padding in + structure size. + * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Correct + placement of float result. + * testsuite/libffi.special/unwindtest.cc (closure_test_fn1): Correct + cast of "resp" for big-endian 64 bit machines. + +2003-09-11 Alan Modra <amodra@bigpond.net.au> + + * src/types.c (double, longdouble): Merge identical SH and ARM + typedefs, and add POWERPC64. + * src/powerpc/ffi.c (ffi_prep_args64): Correct next_arg calc for + struct split over gpr and rest. + (ffi_prep_cif_machdep): Correct intarg_count for structures. + * src/powerpc/linux64.S (ffi_call_LINUX64): Fix gpr offsets. + +2003-09-09 Andreas Tobler <a.tobler@schweiz.ch> + + * src/powerpc/ffi.c (ffi_closure_helper_SYSV) Handle struct + passing correctly. + +2003-09-09 Alan Modra <amodra@bigpond.net.au> + + * configure: Regenerate. + +2003-09-04 Andreas Tobler <a.tobler@schweiz.ch> + + * Makefile.am: Remove build rules for ffitest. + * Makefile.in: Rebuilt. + +2003-09-04 Andreas Tobler <a.tobler@schweiz.ch> + + * src/java_raw_api.c: Include <stdlib.h> to fix compiler warning + about implicit declaration of abort(). + +2003-09-04 Andreas Tobler <a.tobler@schweiz.ch> + + * Makefile.am: Add dejagnu test framework. Fixes PR other/11411. + * Makefile.in: Rebuilt. + * configure.in: Add dejagnu test framework. + * configure: Rebuilt. + + * testsuite/Makefile.am: New file. + * testsuite/Makefile.in: Built + * testsuite/lib/libffi-dg.exp: New file. + * testsuite/config/default.exp: Likewise. + * testsuite/libffi.call/call.exp: Likewise. + * testsuite/libffi.call/ffitest.h: Likewise. + * testsuite/libffi.call/closure_fn0.c: Likewise. + * testsuite/libffi.call/closure_fn1.c: Likewise. + * testsuite/libffi.call/closure_fn2.c: Likewise. + * testsuite/libffi.call/closure_fn3.c: Likewise. + * testsuite/libffi.call/cls_1_1byte.c: Likewise. + * testsuite/libffi.call/cls_3_1byte.c: Likewise. + * testsuite/libffi.call/cls_4_1byte.c: Likewise. + * testsuite/libffi.call/cls_2byte.c: Likewise. + * testsuite/libffi.call/cls_3byte1.c: Likewise. + * testsuite/libffi.call/cls_3byte2.c: Likewise. + * testsuite/libffi.call/cls_4byte.c: Likewise. + * testsuite/libffi.call/cls_5byte.c: Likewise. + * testsuite/libffi.call/cls_6byte.c: Likewise. + * testsuite/libffi.call/cls_7byte.c: Likewise. + * testsuite/libffi.call/cls_8byte.c: Likewise. + * testsuite/libffi.call/cls_12byte.c: Likewise. + * testsuite/libffi.call/cls_16byte.c: Likewise. + * testsuite/libffi.call/cls_20byte.c: Likewise. + * testsuite/libffi.call/cls_24byte.c: Likewise. + * testsuite/libffi.call/cls_double.c: Likewise. + * testsuite/libffi.call/cls_float.c: Likewise. + * testsuite/libffi.call/cls_uchar.c: Likewise. + * testsuite/libffi.call/cls_uint.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/cls_ushort.c: Likewise. + * testsuite/libffi.call/float.c: Likewise. + * testsuite/libffi.call/float1.c: Likewise. + * testsuite/libffi.call/float2.c: Likewise. + * testsuite/libffi.call/many.c: Likewise. + * testsuite/libffi.call/many_win32.c: Likewise. + * testsuite/libffi.call/nested_struct.c: Likewise. + * testsuite/libffi.call/nested_struct1.c: Likewise. + * testsuite/libffi.call/pyobjc-tc.c: Likewise. + * testsuite/libffi.call/problem1.c: Likewise. + * testsuite/libffi.call/promotion.c: Likewise. + * testsuite/libffi.call/return_ll.c: Likewise. + * testsuite/libffi.call/return_sc.c: Likewise. + * testsuite/libffi.call/return_uc.c: Likewise. + * testsuite/libffi.call/strlen.c: Likewise. + * testsuite/libffi.call/strlen_win32.c: Likewise. + * testsuite/libffi.call/struct1.c: Likewise. + * testsuite/libffi.call/struct2.c: Likewise. + * testsuite/libffi.call/struct3.c: Likewise. + * testsuite/libffi.call/struct4.c: Likewise. + * testsuite/libffi.call/struct5.c: Likewise. + * testsuite/libffi.call/struct6.c: Likewise. + * testsuite/libffi.call/struct7.c: Likewise. + * testsuite/libffi.call/struct8.c: Likewise. + * testsuite/libffi.call/struct9.c: Likewise. + * testsuite/libffi.special/special.exp: New file. + * testsuite/libffi.special/ffitestcxx.h: Likewise. + * testsuite/libffi.special/unwindtest.cc: Likewise. + + +2003-08-13 Kaz Kojima <kkojima@gcc.gnu.org> + + * src/sh/ffi.c (OFS_INT16): Set 0 for little endian case. Update + copyright years. + +2003-08-02 Alan Modra <amodra@bigpond.net.au> + + * src/powerpc/ffi.c (ffi_prep_args64): Modify for changed gcc + structure passing. + (ffi_closure_helper_LINUX64): Likewise. + * src/powerpc/linux64.S: Remove code writing to parm save area. + * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Use return + address in lr from ffi_closure_helper_LINUX64 call to calculate + table address. Optimize function tail. + +2003-07-28 Andreas Tobler <a.tobler@schweiz.ch> + + * src/sparc/ffi.c: Handle all floating point registers. + * src/sparc/v9.S: Likewise. Fixes second part of PR target/11410. + +2003-07-11 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at> + + * README: Note that libffi is not part of GCC. Update the project + URL and status. + +2003-06-19 Franz Sirl <Franz.Sirl-kernel@lauterbach.com> + + * src/powerpc/ppc_closure.S: Include ffi.h. + +2003-06-13 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * src/x86/sysv.S: Avoid gas-only .uleb128/.sleb128 directives. + Use C style comments. + +2003-06-13 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * Makefile.am: Add SHmedia support. Fix a typo of SH support. + * Makefile.in: Regenerate. + * configure.in (sh64-*-linux*, sh5*-*-linux*): Add target. + * configure: Regenerate. + * include/ffi.h.in: Add SHmedia support. + * src/sh64/ffi.c: New file. + * src/sh64/sysv.S: New file. + +2003-05-16 Jakub Jelinek <jakub@redhat.com> + + * configure.in (HAVE_RO_EH_FRAME): Check whether .eh_frame section + should be read-only. + * configure: Rebuilt. + * fficonfig.h.in: Rebuilt. + * include/ffi.h.in (EH_FRAME_FLAGS): Define. + * src/alpha/osf.S: Use EH_FRAME_FLAGS. + * src/powerpc/linux64.S: Likewise. + * src/powerpc/linux64_closure.S: Likewise. Include ffi.h. + * src/powerpc/sysv.S: Use EH_FRAME_FLAGS. Use pcrel encoding + if -fpic/-fPIC/-mrelocatable. + * src/powerpc/powerpc_closure.S: Likewise. + * src/sparc/v8.S: If HAVE_RO_EH_FRAME is defined, don't include + #write in .eh_frame flags. + * src/sparc/v9.S: Likewise. + * src/x86/unix64.S: Use EH_FRAME_FLAGS. + * src/x86/sysv.S: Likewise. Use pcrel encoding if -fpic/-fPIC. + * src/s390/sysv.S: Use EH_FRAME_FLAGS. Include ffi.h. + +2003-05-07 Jeff Sturm <jsturm@one-point.com> + + Fixes PR bootstrap/10656 + * configure.in (HAVE_AS_REGISTER_PSEUDO_OP): Test assembler + support for .register pseudo-op. + * src/sparc/v8.S: Use it. + * fficonfig.h.in: Rebuilt. + * configure: Rebuilt. + +2003-04-18 Jakub Jelinek <jakub@redhat.com> + + * include/ffi.h.in (POWERPC64): Define if 64-bit. + (enum ffi_abi): Add FFI_LINUX64 on POWERPC. + Make it the default on POWERPC64. + (FFI_TRAMPOLINE_SIZE): Define to 24 on POWERPC64. + * configure.in: Change powerpc-*-linux* into powerpc*-*-linux*. + * configure: Rebuilt. + * src/powerpc/ffi.c (hidden): Define. + (ffi_prep_args_SYSV): Renamed from + ffi_prep_args. Cast pointers to unsigned long to shut up warnings. + (NUM_GPR_ARG_REGISTERS64, NUM_FPR_ARG_REGISTERS64, + ASM_NEEDS_REGISTERS64): New. + (ffi_prep_args64): New function. + (ffi_prep_cif_machdep): Handle FFI_LINUX64 ABI. + (ffi_call): Likewise. + (ffi_prep_closure): Likewise. + (flush_icache): Surround by #ifndef POWERPC64. + (ffi_dblfl): New union type. + (ffi_closure_helper_SYSV): Use it to avoid aliasing problems. + (ffi_closure_helper_LINUX64): New function. + * src/powerpc/ppc_closure.S: Surround whole file by #ifndef + __powerpc64__. + * src/powerpc/sysv.S: Likewise. + (ffi_call_SYSV): Rename ffi_prep_args to ffi_prep_args_SYSV. + * src/powerpc/linux64.S: New file. + * src/powerpc/linux64_closure.S: New file. + * Makefile.am (EXTRA_DIST): Add src/powerpc/linux64.S and + src/powerpc/linux64_closure.S. + (TARGET_SRC_POWERPC): Likewise. + + * src/ffitest.c (closure_test_fn, closure_test_fn1, closure_test_fn2, + closure_test_fn3): Fix result printing on big-endian 64-bit + machines. + (main): Print tst2_arg instead of uninitialized tst2_result. + + * src/ffitest.c (main): Hide what closure pointer really points to + from the compiler. + +2003-04-16 Richard Earnshaw <rearnsha@arm.com> + + * configure.in (arm-*-netbsdelf*): Add configuration. + (configure): Regenerated. + +2003-04-04 Loren J. Rittle <ljrittle@acm.org> + + * include/Makefile.in: Regenerate. + +2003-03-21 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz> + + * libffi/include/ffi.h.in: Define X86 instead of X86_64 in 32 + bit mode. + * libffi/src/x86/ffi.c (ffi_closure_SYSV, ffi_closure_raw_SYSV): + Receive closure pointer through parameter, read args using + __builtin_dwarf_cfa. + (FFI_INIT_TRAMPOLINE): Send closure reference through eax. + +2003-03-12 Andreas Schwab <schwab@suse.de> + + * configure.in: Avoid trailing /. in toolexeclibdir. + * configure: Rebuilt. + +2003-03-03 Andreas Tobler <a.tobler@schweiz.ch> + + * src/powerpc/darwin_closure.S: Recode to fit dynamic libraries. + +2003-02-06 Andreas Tobler <a.tobler@schweiz.ch> + + * libffi/src/powerpc/darwin_closure.S: + Fix alignement bug, allocate 8 bytes for the result. + * libffi/src/powerpc/aix_closure.S: + Likewise. + * libffi/src/powerpc/ffi_darwin.c: + Update stackframe description for aix/darwin_closure.S. + +2003-02-06 Jakub Jelinek <jakub@redhat.com> + + * src/s390/ffi.c (ffi_closure_helper_SYSV): Add hidden visibility + attribute. + +2003-01-31 Christian Cornelssen <ccorn@cs.tu-berlin.de>, + Andreas Schwab <schwab@suse.de> + + * configure.in: Adjust command to source config-ml.in to account + for changes to the libffi_basedir definition. + (libffi_basedir): Remove ${srcdir} from value and include trailing + slash if nonempty. + + * configure: Regenerate. + +2003-01-29 Franz Sirl <Franz.Sirl-kernel@lauterbach.com> + + * src/powerpc/ppc_closure.S: Recode to fit shared libs. + +2003-01-28 Andrew Haley <aph@redhat.com> + + * include/ffi.h.in: Enable FFI_CLOSURES for x86_64. + * src/x86/ffi64.c (ffi_prep_closure): New. + (ffi_closure_UNIX64_inner): New. + * src/x86/unix64.S (ffi_closure_UNIX64): New. + +2003-01-27 Alexandre Oliva <aoliva@redhat.com> + + * configure.in (toolexecdir, toolexeclibdir): Set and AC_SUBST. + Remove USE_LIBDIR conditional. + * Makefile.am (toolexecdir, toolexeclibdir): Don't override. + * Makefile.in, configure: Rebuilt. + +2003-01027 David Edelsohn <edelsohn@gnu.org> + + * Makefile.am (TARGET_SRC_POWERPC_AIX): Fix typo. + * Makefile.in: Regenerate. + +2003-01-22 Andrew Haley <aph@redhat.com> + + * src/powerpc/darwin.S (_ffi_call_AIX): Add Augmentation size to + unwind info. + +2003-01-21 Andreas Tobler <a.tobler@schweiz.ch> + + * src/powerpc/darwin.S: Add unwind info. + * src/powerpc/darwin_closure.S: Likewise. + +2003-01-14 Andrew Haley <aph@redhat.com> + + * src/x86/ffi64.c (ffi_prep_args): Check for void retval. + (ffi_prep_cif_machdep): Likewise. + * src/x86/unix64.S: Add unwind info. + +2003-01-14 Andreas Jaeger <aj@suse.de> + + * src/ffitest.c (main): Only use ffi_closures if those are + supported. + +2003-01-13 Andreas Tobler <a.tobler@schweiz.ch> + + * libffi/src/ffitest.c + add closure testcases + +2003-01-13 Kevin B. Hendricks <khendricks@ivey.uwo.ca> + + * libffi/src/powerpc/ffi.c + fix alignment bug for float (4 byte aligned iso 8 byte) + +2003-01-09 Geoffrey Keating <geoffk@apple.com> + + * src/powerpc/ffi_darwin.c: Remove RCS version string. + * src/powerpc/darwin.S: Remove RCS version string. + +2003-01-03 Jeff Sturm <jsturm@one-point.com> + + * include/ffi.h.in: Add closure defines for SPARC, SPARC64. + * src/ffitest.c (main): Use static storage for closure. + * src/sparc/ffi.c (ffi_prep_closure, ffi_closure_sparc_inner): New. + * src/sparc/v8.S (ffi_closure_v8): New. + * src/sparc/v9.S (ffi_closure_v9): New. + +2002-11-10 Ranjit Mathew <rmathew@hotmail.com> + + * include/ffi.h.in: Added FFI_STDCALL ffi_type + enumeration for X86_WIN32. + * src/x86/win32.S: Added ffi_call_STDCALL function + definition. + * src/x86/ffi.c (ffi_call/ffi_raw_call): Added + switch cases for recognising FFI_STDCALL and + calling ffi_call_STDCALL if target is X86_WIN32. + * src/ffitest.c (my_stdcall_strlen/stdcall_many): + stdcall versions of the "my_strlen" and "many" + test functions (for X86_WIN32). + Added test cases to test stdcall invocation using + these functions. + +2002-12-02 Kaz Kojima <kkojima@gcc.gnu.org> + + * src/sh/sysv.S: Add DWARF2 unwind info. + +2002-11-27 Ulrich Weigand <uweigand@de.ibm.com> + + * src/s390/sysv.S (.eh_frame section): Make section read-only. + +2002-11-26 Jim Wilson <wilson@redhat.com> + + * src/types.c (FFI_TYPE_POINTER): Has size 8 on IA64. + +2002-11-23 H.J. Lu <hjl@gnu.org> + + * acinclude.m4: Add dummy AM_PROG_LIBTOOL. + Include ../config/accross.m4. + * aclocal.m4; Rebuild. + * configure: Likewise. + +2002-11-15 Ulrich Weigand <uweigand@de.ibm.com> + + * src/s390/sysv.S (.eh_frame section): Adapt to pcrel FDE encoding. + +2002-11-11 DJ Delorie <dj@redhat.com> + + * configure.in: Look for common files in the right place. + +2002-10-08 Ulrich Weigand <uweigand@de.ibm.com> + + * src/java_raw_api.c (ffi_java_raw_to_ptrarray): Interpret + raw data as _Jv_word values, not ffi_raw. + (ffi_java_ptrarray_to_raw): Likewise. + (ffi_java_rvalue_to_raw): New function. + (ffi_java_raw_call): Call it. + (ffi_java_raw_to_rvalue): New function. + (ffi_java_translate_args): Call it. + * src/ffitest.c (closure_test_fn): Interpret return value + as ffi_arg, not int. + * src/s390/ffi.c (ffi_prep_cif_machdep): Add missing + FFI_TYPE_POINTER case. + (ffi_closure_helper_SYSV): Likewise. Also, assume return + values extended to word size. + +2002-10-02 Andreas Jaeger <aj@suse.de> + + * src/x86/ffi64.c (ffi_prep_cif_machdep): Remove debug output. + +2002-10-01 Bo Thorsen <bo@smetana.suse.de> + + * include/ffi.h.in: Fix i386 win32 compilation. + +2002-09-30 Ulrich Weigand <uweigand@de.ibm.com> + + * configure.in: Add s390x-*-linux-* target. + * configure: Regenerate. + * include/ffi.h.in: Define S390X for s390x targets. + (FFI_CLOSURES): Define for s390/s390x. + (FFI_TRAMPOLINE_SIZE): Likewise. + (FFI_NATIVE_RAW_API): Likewise. + * src/prep_cif.c (ffi_prep_cif): Do not compute stack space for s390. + * src/types.c (FFI_TYPE_POINTER): Use 8-byte pointers on s390x. + * src/s390/ffi.c: Major rework of existing code. Add support for + s390x targets. Add closure support. + * src/s390/sysv.S: Likewise. + +2002-09-29 Richard Earnshaw <rearnsha@arm.com> + + * src/arm/sysv.S: Fix typo. + +2002-09-28 Richard Earnshaw <rearnsha@arm.com> + + * src/arm/sysv.S: If we don't have machine/asm.h and the pre-processor + has defined __USER_LABEL_PREFIX__, then use it in CNAME. + (ffi_call_SYSV): Handle soft-float. + +2002-09-27 Bo Thorsen <bo@suse.de> + + * include/ffi.h.in: Fix multilib x86-64 support. + +2002-09-22 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * Makefile.am (all-multi): Fix multilib parallel build. + +2002-07-19 Kaz Kojima <kkojima@gcc.gnu.org> + + * configure.in (sh[34]*-*-linux*): Add brackets. + * configure: Regenerate. + +2002-07-18 Kaz Kojima <kkojima@gcc.gnu.org> + + * Makefile.am: Add SH support. + * Makefile.in: Regenerate. + * configure.in (sh-*-linux*, sh[34]*-*-linux*): Add target. + * configure: Regenerate. + * include/ffi.h.in: Add SH support. + * src/sh/ffi.c: New file. + * src/sh/sysv.S: New file. + * src/types.c: Add SH support. + +2002-07-16 Bo Thorsen <bo@suse.de> + + * src/x86/ffi64.c: New file that adds x86-64 support. + * src/x86/unix64.S: New file that handles argument setup for + x86-64. + * src/x86/sysv.S: Don't use this on x86-64. + * src/x86/ffi.c: Don't use this on x86-64. + Remove unused vars. + * src/prep_cif.c (ffi_prep_cif): Don't do stack size calculation + for x86-64. + * src/ffitest.c (struct6): New test that tests a special case in + the x86-64 ABI. + (struct7): Likewise. + (struct8): Likewise. + (struct9): Likewise. + (closure_test_fn): Silence warning about this when it's not used. + (main): Add the new tests. + (main): Fix a couple of wrong casts and silence some compiler warnings. + * include/ffi.h.in: Add x86-64 ABI definition. + * fficonfig.h.in: Regenerate. + * Makefile.am: Add x86-64 support. + * configure.in: Likewise. + * Makefile.in: Regenerate. + * configure: Likewise. + +2002-06-24 Bo Thorsen <bo@suse.de> + + * src/types.c: Merge settings for similar architectures. + Add x86-64 sizes and alignments. + +2002-06-23 Bo Thorsen <bo@suse.de> + + * src/arm/ffi.c (ffi_prep_args): Remove unused vars. + * src/sparc/ffi.c (ffi_prep_args_v8): Likewise. + * src/mips/ffi.c (ffi_prep_args): Likewise. + * src/m68k/ffi.c (ffi_prep_args): Likewise. + +2002-07-18 H.J. Lu (hjl@gnu.org) + + * Makefile.am (TARGET_SRC_MIPS_LINUX): New. + (libffi_la_SOURCES): Support MIPS_LINUX. + (libffi_convenience_la_SOURCES): Likewise. + * Makefile.in: Regenerated. + + * configure.in (mips64*-*): Skip. + (mips*-*-linux*): New. + * configure: Regenerated. + + * src/mips/ffi.c: Include <sgidefs.h>. + +2002-06-06 Ulrich Weigand <uweigand@de.ibm.com> + + * src/s390/sysv.S: Save/restore %r6. Add DWARF-2 unwind info. + +2002-05-27 Roger Sayle <roger@eyesopen.com> + + * src/x86/ffi.c (ffi_prep_args): Remove reference to avn. + +2002-05-27 Bo Thorsen <bo@suse.de> + + * src/x86/ffi.c (ffi_prep_args): Remove unused variable and + fix formatting. + +2002-05-13 Andreas Tobler <a.tobler@schweiz.ch> + + * src/powerpc/ffi_darwin.c (ffi_prep_closure): Declare fd at + beginning of function (for older apple cc). + +2002-05-08 Alexandre Oliva <aoliva@redhat.com> + + * configure.in (ORIGINAL_LD_FOR_MULTILIBS): Preserve LD at + script entry, and set LD to it when configuring multilibs. + * configure: Rebuilt. + +2002-05-05 Jason Thorpe <thorpej@wasabisystems.com> + + * configure.in (sparc64-*-netbsd*): Add target. + (sparc-*-netbsdelf*): Likewise. + * configure: Regenerate. + +2002-04-28 David S. Miller <davem@redhat.com> + + * configure.in, configure: Fix SPARC test in previous change. + +2002-04-29 Gerhard Tonn <GerhardTonn@swol.de> + + * Makefile.am: Add Linux for S/390 support. + * Makefile.in: Regenerate. + * configure.in: Add Linux for S/390 support. + * configure: Regenerate. + * include/ffi.h.in: Add Linux for S/390 support. + * src/s390/ffi.c: New file from libffi CVS tree. + * src/s390/sysv.S: New file from libffi CVS tree. + +2002-04-28 Jakub Jelinek <jakub@redhat.com> + + * configure.in (HAVE_AS_SPARC_UA_PCREL): Check for working + %r_disp32(). + * src/sparc/v8.S: Use it. + * src/sparc/v9.S: Likewise. + * fficonfig.h.in: Rebuilt. + * configure: Rebuilt. + +2002-04-08 Hans Boehm <Hans_Boehm@hp.com> + + * src/java_raw_api.c (ffi_java_raw_size): Handle FFI_TYPE_DOUBLE + correctly. + * src/ia64/unix.S: Add unwind information. Fix comments. + Save sp in a way that's compatible with unwind info. + (ffi_call_unix): Correctly restore sp in all cases. + * src/ia64/ffi.c: Add, fix comments. + +2002-04-08 Jakub Jelinek <jakub@redhat.com> + + * src/sparc/v8.S: Make .eh_frame dependent on target word size. + +2002-04-06 Jason Thorpe <thorpej@wasabisystems.com> + + * configure.in (alpha*-*-netbsd*): Add target. + * configure: Regenerate. + +2002-04-04 Jeff Sturm <jsturm@one-point.com> + + * src/sparc/v8.S: Add unwind info. + * src/sparc/v9.S: Likewise. + +2002-03-30 Krister Walfridsson <cato@df.lth.se> + + * configure.in: Enable i*86-*-netbsdelf*. + * configure: Rebuilt. + +2002-03-29 David Billinghurst <David.Billinghurst@riotinto.com> + + PR other/2620 + * src/mips/n32.s: Delete + * src/mips/o32.s: Delete + +2002-03-21 Loren J. Rittle <ljrittle@acm.org> + + * configure.in: Enable alpha*-*-freebsd*. + * configure: Rebuilt. + +2002-03-17 Bryce McKinlay <bryce@waitaki.otago.ac.nz> + + * Makefile.am: libfficonvenience -> libffi_convenience. + * Makefile.in: Rebuilt. + + * Makefile.am: Define ffitest_OBJECTS. + * Makefile.in: Rebuilt. + +2002-03-07 Andreas Tobler <toa@pop.agri.ch> + David Edelsohn <edelsohn@gnu.org> + + * Makefile.am (EXTRA_DIST): Add Darwin and AIX closure files. + (TARGET_SRC_POWERPC_AIX): Add aix_closure.S. + (TARGET_SRC_POWERPC_DARWIN): Add darwin_closure.S. + * Makefile.in: Regenerate. + * include/ffi.h.in: Add AIX and Darwin closure definitions. + * src/powerpc/ffi_darwin.c (ffi_prep_closure): New function. + (flush_icache, flush_range): New functions. + (ffi_closure_helper_DARWIN): New function. + * src/powerpc/aix_closure.S: New file. + * src/powerpc/darwin_closure.S: New file. + +2002-02-24 Jeff Sturm <jsturm@one-point.com> + + * include/ffi.h.in: Add typedef for ffi_arg. + * src/ffitest.c (main): Declare rint with ffi_arg. + +2002-02-21 Andreas Tobler <toa@pop.agri.ch> + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Skip appropriate + number of GPRs for floating-point arguments. + +2002-01-31 Anthony Green <green@redhat.com> + + * configure: Rebuilt. + * configure.in: Replace CHECK_SIZEOF and endian tests with + cross-compiler friendly macros. + * aclocal.m4 (AC_COMPILE_CHECK_SIZEOF, AC_C_BIGENDIAN_CROSS): New + macros. + +2002-01-18 David Edelsohn <edelsohn@gnu.org> + + * src/powerpc/darwin.S (_ffi_call_AIX): New. + * src/powerpc/aix.S (ffi_call_DARWIN): New. + +2002-01-17 David Edelsohn <edelsohn@gnu.org> + + * Makefile.am (EXTRA_DIST): Add Darwin and AIX files. + (TARGET_SRC_POWERPC_AIX): New. + (POWERPC_AIX): New stanza. + * Makefile.in: Regenerate. + * configure.in: Add AIX case. + * configure: Regenerate. + * include/ffi.h.in (ffi_abi): Add FFI_AIX. + * src/powerpc/ffi_darwin.c (ffi_status): Use "long" to scale frame + size. Fix "long double" support. + (ffi_call): Add FFI_AIX case. + * src/powerpc/aix.S: New. + +2001-10-09 John Hornkvist <john@toastedmarshmallow.com> + + Implement Darwin PowerPC ABI. + * configure.in: Handle powerpc-*-darwin*. + * Makefile.am: Set source files for POWERPC_DARWIN. + * configure: Rebuilt. + * Makefile.in: Rebuilt. + * include/ffi.h.in: Define FFI_DARWIN and FFI_DEFAULT_ABI for + POWERPC_DARWIN. + * src/powerpc/darwin.S: New file. + * src/powerpc/ffi_darwin.c: New file. + +2001-10-07 Joseph S. Myers <jsm28@cam.ac.uk> + + * src/x86/ffi.c: Fix spelling error of "separate" as "seperate". + +2001-07-16 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * src/x86/sysv.S: Avoid gas-only .balign directive. + Use C style comments. + +2001-07-16 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * src/alpha/ffi.c (ffi_prep_closure): Avoid gas-only mnemonic. + Fixes PR bootstrap/3563. + +2001-06-26 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * src/alpha/osf.S (ffi_closure_osf): Use .rdata for ECOFF. + +2001-06-25 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * configure.in: Recognize sparc*-sun-* host. + * configure: Regenerate. + +2001-06-06 Andrew Haley <aph@redhat.com> + + * src/alpha/osf.S (__FRAME_BEGIN__): Conditionalize for ELF. + +2001-06-03 Andrew Haley <aph@redhat.com> + + * src/alpha/osf.S: Add unwind info. + * src/powerpc/sysv.S: Add unwind info. + * src/powerpc/ppc_closure.S: Likewise. + +2000-05-31 Jeff Sturm <jsturm@one-point.com> + + * configure.in: Fix AC_ARG_ENABLE usage. + * configure: Rebuilt. + +2001-05-06 Bryce McKinlay <bryce@waitaki.otago.ac.nz> + + * configure.in: Remove warning about beta code. + * configure: Rebuilt. + +2001-04-25 Hans Boehm <Hans_Boehm@hp.com> + + * src/ia64/unix.S: Restore stack pointer when returning from + ffi_closure_UNIX. + * src/ia64/ffi.c: Fix typo in comment. + +2001-04-18 Jim Wilson <wilson@redhat.com> + + * src/ia64/unix.S: Delete unnecessary increment and decrement of loc2 + to eliminate RAW DV. + +2001-04-12 Bryce McKinlay <bryce@albatross.co.nz> + + * Makefile.am: Make a libtool convenience library. + * Makefile.in: Rebuilt. + +2001-03-29 Bryce McKinlay <bryce@albatross.co.nz> + + * configure.in: Use different syntax for subdirectory creation. + * configure: Rebuilt. + +2001-03-27 Jon Beniston <jon@beniston.com> + + * configure.in: Added X86_WIN32 target (Win32, CygWin, MingW). + * configure: Rebuilt. + * Makefile.am: Added X86_WIN32 target support. + * Makefile.in: Rebuilt. + + * include/ffi.h.in: Added X86_WIN32 target support. + + * src/ffitest.c: Doesn't run structure tests for X86_WIN32 targets. + * src/types.c: Added X86_WIN32 target support. + + * src/x86/win32.S: New file. Based on sysv.S, but with EH + stuff removed and made to work with CygWin's gas. + +2001-03-26 Bryce McKinlay <bryce@albatross.co.nz> + + * configure.in: Make target subdirectory in build dir. + * Makefile.am: Override suffix based rules to specify correct output + subdirectory. + * Makefile.in: Rebuilt. + * configure: Rebuilt. + +2001-03-23 Kevin B Hendricks <khendricks@ivey.uwo.ca> + + * src/powerpc/ppc_closure.S: New file. + * src/powerpc/ffi.c (ffi_prep_args): Fixed ABI compatibility bug + involving long long and register pairs. + (ffi_prep_closure): New function. + (flush_icache): Likewise. + (ffi_closure_helper_SYSV): Likewise. + * include/ffi.h.in (FFI_CLOSURES): Define on PPC. + (FFI_TRAMPOLINE_SIZE): Likewise. + (FFI_NATIVE_RAW_API): Likewise. + * Makefile.in: Rebuilt. + * Makefile.am (EXTRA_DIST): Added src/powerpc/ppc_closure.S. + (TARGET_SRC_POWERPC): Likewise. + +2001-03-19 Tom Tromey <tromey@redhat.com> + + * Makefile.in: Rebuilt. + * Makefile.am (ffitest_LDFLAGS): New macro. + +2001-03-02 Nick Clifton <nickc@redhat.com> + + * include/ffi.h.in: Remove RCS ident string. + * include/ffi_mips.h: Remove RCS ident string. + * src/debug.c: Remove RCS ident string. + * src/ffitest.c: Remove RCS ident string. + * src/prep_cif.c: Remove RCS ident string. + * src/types.c: Remove RCS ident string. + * src/alpha/ffi.c: Remove RCS ident string. + * src/alpha/osf.S: Remove RCS ident string. + * src/arm/ffi.c: Remove RCS ident string. + * src/arm/sysv.S: Remove RCS ident string. + * src/mips/ffi.c: Remove RCS ident string. + * src/mips/n32.S: Remove RCS ident string. + * src/mips/o32.S: Remove RCS ident string. + * src/sparc/ffi.c: Remove RCS ident string. + * src/sparc/v8.S: Remove RCS ident string. + * src/sparc/v9.S: Remove RCS ident string. + * src/x86/ffi.c: Remove RCS ident string. + * src/x86/sysv.S: Remove RCS ident string. + +2001-02-08 Joseph S. Myers <jsm28@cam.ac.uk> + + * include/ffi.h.in: Change sourceware.cygnus.com references to + gcc.gnu.org. + +2000-12-09 Richard Henderson <rth@redhat.com> + + * src/alpha/ffi.c (ffi_call): Simplify struct return test. + (ffi_closure_osf_inner): Index rather than increment avalue + and arg_types. Give ffi_closure_osf the raw return value type. + * src/alpha/osf.S (ffi_closure_osf): Handle return value type + promotion. + +2000-12-07 Richard Henderson <rth@redhat.com> + + * src/raw_api.c (ffi_translate_args): Fix typo. + (ffi_prep_closure): Likewise. + + * include/ffi.h.in [ALPHA]: Define FFI_CLOSURES and + FFI_TRAMPOLINE_SIZE. + * src/alpha/ffi.c (ffi_prep_cif_machdep): Adjust minimal + cif->bytes for new ffi_call_osf implementation. + (ffi_prep_args): Absorb into ... + (ffi_call): ... here. Do all stack allocation here and + avoid a callback function. + (ffi_prep_closure, ffi_closure_osf_inner): New. + * src/alpha/osf.S (ffi_call_osf): Reimplement with no callback. + (ffi_closure_osf): New. + +2000-09-10 Alexandre Oliva <aoliva@redhat.com> + + * config.guess, config.sub, install-sh: Removed. + * ltconfig, ltmain.sh, missing, mkinstalldirs: Likewise. + * Makefile.in: Rebuilt. + + * acinclude.m4: Include libtool macros from the top level. + * aclocal.m4, configure: Rebuilt. + +2000-08-22 Alexandre Oliva <aoliva@redhat.com> + + * configure.in [i*86-*-freebsd*] (TARGET, TARGETDIR): Set. + * configure: Rebuilt. + +2000-05-11 Scott Bambrough <scottb@netwinder.org> + + * libffi/src/arm/sysv.S (ffi_call_SYSV): Doubles are not saved to + memory correctly. Use conditional instructions, not branches where + possible. + +2000-05-04 Tom Tromey <tromey@cygnus.com> + + * configure: Rebuilt. + * configure.in: Match `arm*-*-linux-*'. + From Chris Dornan <cdornan@arm.com>. + +2000-04-28 Jakub Jelinek <jakub@redhat.com> + + * Makefile.am (SUBDIRS): Define. + (AM_MAKEFLAGS): Likewise. + (Multilib support.): Add section. + * Makefile.in: Rebuilt. + * ltconfig (extra_compiler_flags, extra_compiler_flags_value): + New variables. Set for gcc using -print-multi-lib. Export them + to libtool. + (sparc64-*-linux-gnu*): Use libsuff 64 for search paths. + * ltmain.sh (B|b|V): Don't throw away gcc's -B, -b and -V options + for -shared links. + (extra_compiler_flags_value, extra_compiler_flags): Check these + for extra compiler options which need to be passed down in + compiler_flags. + +2000-04-16 Anthony Green <green@redhat.com> + + * configure: Rebuilt. + * configure.in: Change i*86-pc-linux* to i*86-*-linux*. + +2000-04-14 Jakub Jelinek <jakub@redhat.com> + + * include/ffi.h.in (SPARC64): Define for 64bit SPARC builds. + Set SPARC FFI_DEFAULT_ABI based on SPARC64 define. + * src/sparc/ffi.c (ffi_prep_args_v8): Renamed from ffi_prep_args. + Replace all void * sizeofs with sizeof(int). + Only compare type with FFI_TYPE_LONGDOUBLE if LONGDOUBLE is + different than DOUBLE. + Remove FFI_TYPE_SINT32 and FFI_TYPE_UINT32 cases (handled elsewhere). + (ffi_prep_args_v9): New function. + (ffi_prep_cif_machdep): Handle V9 ABI and long long on V8. + (ffi_V9_return_struct): New function. + (ffi_call): Handle FFI_V9 ABI from 64bit code and FFI_V8 ABI from + 32bit code (not yet cross-arch calls). + * src/sparc/v8.S: Add struct return delay nop. + Handle long long. + * src/sparc/v9.S: New file. + * src/prep_cif.c (ffi_prep_cif): Return structure pointer + is used on sparc64 only for structures larger than 32 bytes. + Pass by reference for structures is done for structure arguments + larger than 16 bytes. + * src/ffitest.c (main): Use 64bit rint on sparc64. + Run long long tests on sparc. + * src/types.c (FFI_TYPE_POINTER): Pointer is 64bit on alpha and + sparc64. + (FFI_TYPE_LONGDOUBLE): long double is 128 bit aligned to 128 bits + on sparc64. + * configure.in (sparc-*-linux*): New supported target. + (sparc64-*-linux*): Likewise. + * configure: Rebuilt. + * Makefile.am: Add v9.S to SPARC files. + * Makefile.in: Likewise. + (LINK): Surround $(CCLD) into double quotes, so that multilib + compiles work correctly. + +2000-04-04 Alexandre Petit-Bianco <apbianco@cygnus.com> + + * configure: Rebuilt. + * configure.in: (i*86-*-solaris*): New libffi target. Patch + proposed by Bryce McKinlay. + +2000-03-20 Tom Tromey <tromey@cygnus.com> + + * Makefile.in: Hand edit for java_raw_api.lo. + +2000-03-08 Bryce McKinlay <bryce@albatross.co.nz> + + * config.guess, config.sub: Update from the gcc tree. + Fix for PR libgcj/168. + +2000-03-03 Tom Tromey <tromey@cygnus.com> + + * Makefile.in: Fixed ia64 by hand. + + * configure: Rebuilt. + * configure.in (--enable-multilib): New option. + (libffi_basedir): New subst. + (AC_OUTPUT): Added multilib code. + +2000-03-02 Tom Tromey <tromey@cygnus.com> + + * Makefile.in: Rebuilt. + * Makefile.am (TARGET_SRC_IA64): Use `ia64', not `alpha', as + directory name. + +2000-02-25 Hans Boehm <boehm@acm.org> + + * src/ia64/ffi.c, src/ia64/ia64_flags.h, src/ia64/unix.S: New + files. + * src/raw_api.c (ffi_translate_args): Fixed typo in argument + list. + (ffi_prep_raw_closure): Use ffi_translate_args, not + ffi_closure_translate. + * src/java_raw_api.c: New file. + * src/ffitest.c (closure_test_fn): New function. + (main): Define `rint' as long long on IA64. Added new test when + FFI_CLOSURES is defined. + * include/ffi.h.in (ALIGN): Use size_t, not unsigned. + (ffi_abi): Recognize IA64. + (ffi_raw): Added `flt' field. + Added "Java raw API" code. + * configure.in: Recognize ia64. + * Makefile.am (TARGET_SRC_IA64): New macro. + (libffi_la_common_SOURCES): Added java_raw_api.c. + (libffi_la_SOURCES): Define in IA64 case. + +2000-01-04 Tom Tromey <tromey@cygnus.com> + + * Makefile.in: Rebuilt with newer automake. + +1999-12-31 Tom Tromey <tromey@cygnus.com> + + * Makefile.am (INCLUDES): Added -I$(top_srcdir)/src. + +1999-09-01 Tom Tromey <tromey@cygnus.com> + + * include/ffi.h.in: Removed PACKAGE and VERSION defines and + undefs. + * fficonfig.h.in: Rebuilt. + * configure: Rebuilt. + * configure.in: Pass 3rd argument to AM_INIT_AUTOMAKE. + Use AM_PROG_LIBTOOL (automake 1.4 compatibility). + * acconfig.h: Don't #undef PACKAGE or VERSION. + +1999-08-09 Anthony Green <green@cygnus.com> + + * include/ffi.h.in: Try to work around messy header problem + with PACKAGE and VERSION. + + * configure: Rebuilt. + * configure.in: Change version to 2.00-beta. + + * fficonfig.h.in: Rebuilt. + * acconfig.h (FFI_NO_STRUCTS, FFI_NO_RAW_API): Define. + + * src/x86/ffi.c (ffi_raw_call): Rename. + +1999-08-02 Kresten Krab Thorup <krab@dominiq.is.s.u-tokyo.ac.jp> + + * src/x86/ffi.c (ffi_closure_SYSV): New function. + (ffi_prep_incoming_args_SYSV): Ditto. + (ffi_prep_closure): Ditto. + (ffi_closure_raw_SYSV): Ditto. + (ffi_prep_raw_closure): More ditto. + (ffi_call_raw): Final ditto. + + * include/ffi.h.in: Add definitions for closure and raw API. + + * src/x86/ffi.c (ffi_prep_cif_machdep): Added case for + FFI_TYPE_UINT64. + + * Makefile.am (libffi_la_common_SOURCES): Added raw_api.c + + * src/raw_api.c: New file. + + * include/ffi.h.in (ffi_raw): New type. + (UINT_ARG, SINT_ARG): New defines. + (ffi_closure, ffi_raw_closure): New types. + (ffi_prep_closure, ffi_prep_raw_closure): New declarations. + + * configure.in: Add check for endianness and sizeof void*. + + * src/x86/sysv.S (ffi_call_SYSV): Call fixup routine via argument, + instead of directly. + + * configure: Rebuilt. + +Thu Jul 8 14:28:42 1999 Anthony Green <green@cygnus.com> + + * configure.in: Add x86 and powerpc BeOS configurations. + From Makoto Kato <m_kato@ga2.so-net.ne.jp>. + +1999-05-09 Anthony Green <green@cygnus.com> + + * configure.in: Add warning about this being beta code. + Remove src/Makefile.am from the picture. + * configure: Rebuilt. + + * Makefile.am: Move logic from src/Makefile.am. Add changes + to support libffi as a target library. + * Makefile.in: Rebuilt. + + * aclocal.m4, config.guess, config.sub, ltconfig, ltmain.sh: + Upgraded to new autoconf, automake, libtool. + + * README: Tweaks. + + * LICENSE: Update copyright date. + + * src/Makefile.am, src/Makefile.in: Removed. + +1998-11-29 Anthony Green <green@cygnus.com> + + * include/ChangeLog: Removed. + * src/ChangeLog: Removed. + * src/mips/ChangeLog: Removed. + * src/sparc/ChangeLog: Remboved. + * src/x86/ChangeLog: Removed. + + * ChangeLog.v1: Created. + +============================================================================= +From the old ChangeLog.libffi file.... + 2011-02-08 Andreas Tobler <andreast@fgznet.ch> * testsuite/lib/libffi.exp: Tweak for stand-alone mode. @@ -574,11 +6586,822 @@ * Makefile.am, include/Makefile.am: Move headers to libffi_la_SOURCES for new automake. * Makefile.in, include/Makefile.in: Rebuilt. - - * testsuite/lib/wrapper.exp: Copied from gcc tree to allow for + + * testsuite/lib/wrapper.exp: Copied from gcc tree to allow for execution outside of gcc tree. * testsuite/lib/target-libpath.exp: Ditto. * testsuite/lib/libffi-dg.exp: Many changes to allow for execution outside of gcc tree. + +============================================================================= +From the old ChangeLog.libgcj file.... + +2004-01-14 Kelley Cook <kcook@gcc.gnu.org> + + * configure.in: Add in AC_PREREQ(2.13) + +2003-02-20 Alexandre Oliva <aoliva@redhat.com> + + * configure.in: Propagate ORIGINAL_LD_FOR_MULTILIBS to + config.status. + * configure: Rebuilt. + +2002-01-27 Alexandre Oliva <aoliva@redhat.com> + + * configure.in (toolexecdir, toolexeclibdir): Set and AC_SUBST. + Remove USE_LIBDIR conditional. + * Makefile.am (toolexecdir, toolexeclibdir): Don't override. + * Makefile.in, configure: Rebuilt. + +Mon Aug 9 18:33:38 1999 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> + + * include/Makefile.in: Rebuilt. + * Makefile.in: Rebuilt + * Makefile.am (toolexeclibdir): Add $(MULTISUBDIR) even for native + builds. + Use USE_LIBDIR. + + * configure: Rebuilt. + * configure.in (USE_LIBDIR): Define for native builds. + Use lowercase in configure --help explanations. + +1999-08-08 Anthony Green <green@cygnus.com> + + * include/ffi.h.in (FFI_FN): Remove `...'. + +1999-08-08 Anthony Green <green@cygnus.com> + + * Makefile.in: Rebuilt. + * Makefile.am (AM_CFLAGS): Compile with -fexceptions. + + * src/x86/sysv.S: Add exception handling metadata. + + +============================================================================= + +The libffi version 1 ChangeLog archive. + +Version 1 of libffi had per-directory ChangeLogs. Current and future +versions have a single ChangeLog file in the root directory. The +version 1 ChangeLogs have all been concatenated into this file for +future reference only. + +--- libffi ---------------------------------------------------------------- + +Mon Oct 5 02:17:50 1998 Anthony Green <green@cygnus.com> + + * configure.in: Boosted rev. + * configure, Makefile.in, aclocal.m4: Rebuilt. + * README: Boosted rev and updated release notes. + +Mon Oct 5 01:03:03 1998 Anthony Green <green@cygnus.com> + + * configure.in: Boosted rev. + * configure, Makefile.in, aclocal.m4: Rebuilt. + * README: Boosted rev and updated release notes. + +1998-07-25 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * m68k/ffi.c (ffi_prep_cif_machdep): Use bitmask for cif->flags. + Correctly handle small structures. + (ffi_prep_args): Also handle small structures. + (ffi_call): Pass size of return type to ffi_call_SYSV. + * m68k/sysv.S: Adjust for above changes. Correctly align small + structures in the return value. + + * types.c (uint64, sint64) [M68K]: Change alignment to 4. + +Fri Apr 17 17:26:58 1998 Anthony Green <green@hoser.cygnus.com> + + * configure.in: Boosted rev. + * configure,Makefile.in,aclocal.m4: Rebuilt. + * README: Boosted rev and added release notes. + +Sun Feb 22 00:50:41 1998 Geoff Keating <geoffk@ozemail.com.au> + + * configure.in: Add PowerPC config bits. + +1998-02-14 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * configure.in: Add m68k config bits. Change AC_CANONICAL_SYSTEM + to AC_CANONICAL_HOST, this is not a compiler. Use $host instead + of $target. Remove AC_CHECK_SIZEOF(char), we already know the + result. Fix argument of AC_ARG_ENABLE. + * configure, fficonfig.h.in: Rebuilt. + +Tue Feb 10 20:53:40 1998 Richard Henderson <rth@cygnus.com> + + * configure.in: Add Alpha config bits. + +Tue May 13 13:39:20 1997 Anthony Green <green@hoser.cygnus.com> + + * README: Updated dates and reworded Irix comments. + + * configure.in: Removed AC_PROG_RANLIB. + + * Makefile.in, aclocal.m4, config.guess, config.sub, configure, + ltmain.sh, */Makefile.in: libtoolized again and rebuilt with + automake and autoconf. + +Sat May 10 18:44:50 1997 Tom Tromey <tromey@cygnus.com> + + * configure, aclocal.m4: Rebuilt. + * configure.in: Don't compute EXTRADIST; now handled in + src/Makefile.in. Removed macros implied by AM_INIT_AUTOMAKE. + Don't run AM_MAINTAINER_MODE. + +Thu May 8 14:34:05 1997 Anthony Green <green@hoser.cygnus.com> + + * missing, ltmain.sh, ltconfig.sh: Created. These are new files + required by automake and libtool. + + * README: Boosted rev to 1.14. Added notes. + + * acconfig.h: Moved PACKAGE and VERSION for new automake. + + * configure.in: Changes for libtool. + + * Makefile.am (check): make test now make check. Uses libtool now. + + * Makefile.in, configure.in, aclocal.h, fficonfig.h.in: Rebuilt. + +Thu May 1 16:27:07 1997 Anthony Green <green@hoser.cygnus.com> + + * missing: Added file required by new automake. + +Tue Nov 26 14:10:42 1996 Anthony Green <green@csk3.cygnus.com> + + * acconfig.h: Added USING_PURIFY flag. This is defined when + --enable-purify-safety was used at configure time. + + * configure.in (allsources): Added --enable-purify-safety switch. + (VERSION): Boosted rev to 1.13. + * configure: Rebuilt. + +Fri Nov 22 06:46:12 1996 Anthony Green <green@rtl.cygnus.com> + + * configure.in (VERSION): Boosted rev to 1.12. + Removed special CFLAGS hack for gcc. + * configure: Rebuilt. + + * README: Boosted rev to 1.12. Added notes. + + * Many files: Cygnus Support changed to Cygnus Solutions. + +Wed Oct 30 11:15:25 1996 Anthony Green <green@rtl.cygnus.com> + + * configure.in (VERSION): Boosted rev to 1.11. + * configure: Rebuilt. + + * README: Boosted rev to 1.11. Added notes about GNU make. + +Tue Oct 29 12:25:12 1996 Anthony Green <green@rtl.cygnus.com> + + * configure.in: Fixed -Wall trick. + (VERSION): Boosted rev. + * configure: Rebuilt + + * acconfig.h: Needed for --enable-debug configure switch. + + * README: Boosted rev to 1.09. Added more notes on building + libffi, and LCLint. + + * configure.in: Added --enable-debug switch. Boosted rev to + 1.09. + * configure: Rebuilt + +Tue Oct 15 13:11:28 1996 Anthony Green <green@hoser.cygnus.com> + + * configure.in (VERSION): Boosted rev to 1.08 + * configure: Rebuilt. + + * README: Added n32 bug fix notes. + + * Makefile.am: Added "make lint" production. + * Makefile.in: Rebuilt. + +Mon Oct 14 10:54:46 1996 Anthony Green <green@rtl.cygnus.com> + + * README: Added web page reference. + + * configure.in, README: Boosted rev to 1.05 + * configure: Rebuilt. + + * README: Fixed n32 sample code. + +Fri Oct 11 17:09:28 1996 Anthony Green <green@rtl.cygnus.com> + + * README: Added sparc notes. + + * configure.in, README: Boosted rev to 1.04. + * configure: Rebuilt. + +Thu Oct 10 10:31:03 1996 Anthony Green <green@rtl.cygnus.com> + + * configure.in, README: Boosted rev to 1.03. + * configure: Rebuilt. + + * README: Added struct notes. + + * Makefile.am (EXTRA_DIST): Added LICENSE to distribution. + * Makefile.in: Rebuilt. + + * README: Removed Linux section. No special notes now + because aggregates arg/return types work. + +Wed Oct 9 16:16:42 1996 Anthony Green <green@rtl.cygnus.com> + + * README, configure.in (VERSION): Boosted rev to 1.02 + * configure: Rebuilt. + +Tue Oct 8 11:56:33 1996 Anthony Green <green@rtl.cygnus.com> + + * README (NOTE): Added n32 notes. + + * Makefile.am: Added test production. + * Makefile: Rebuilt + + * README: spell checked! + + * configure.in (VERSION): Boosted rev to 1.01 + * configure: Rebuilt. + +Mon Oct 7 15:50:22 1996 Anthony Green <green@rtl.cygnus.com> + + * configure.in: Added nasty bit to support SGI tools. + * configure: Rebuilt. + + * README: Added SGI notes. Added note about automake bug. + +Mon Oct 7 11:00:28 1996 Anthony Green <green@hoser.cygnus.com> + + * README: Rewrote intro, and fixed examples. + +Fri Oct 4 10:19:55 1996 Anthony Green <green@hoser.cygnus.com> + + * configure.in: -D$TARGET is no longer used as a compiler switch. + It is now inserted into ffi.h at configure time. + * configure: Rebuilt. + + * FFI_ABI and FFI_STATUS are now ffi_abi and ffi_status. + +Thu Oct 3 13:47:34 1996 Anthony Green <green@hoser.cygnus.com> + + * README, LICENSE: Created. Wrote some docs. + + * configure.in: Don't barf on i586-unknown-linuxaout. + Added EXTRADIST code for "make dist". + * configure: Rebuilt. + + * */Makefile.in: Rebuilt with patched automake. + +Tue Oct 1 17:12:25 1996 Anthony Green <green@rtl.cygnus.com> + + * Makefile.am, aclocal.m4, config.guess, config.sub, + configure.in, fficonfig.h.in, install-sh, mkinstalldirs, + stamp-h.in: Created + * Makefile.in, configure: Generated + +--- libffi/include -------------------------------------------------------- + +Tue Feb 24 13:09:36 1998 Anthony Green <green@gerbil.cygnus.com> + + * ffi_mips.h: Updated FFI_TYPE_STRUCT_* values based on + ffi.h.in changes. This is a work-around for SGI's "simple" + assembler. + +Sun Feb 22 00:51:55 1998 Geoff Keating <geoffk@ozemail.com.au> + + * ffi.h.in: PowerPC support. + +1998-02-14 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * ffi.h.in: Add m68k support. + (FFI_TYPE_LONGDOUBLE): Make it a separate value. + +Tue Feb 10 20:55:16 1998 Richard Henderson <rth@cygnus.com> + + * ffi.h.in (SIZEOF_ARG): Use a pointer type by default. + + * ffi.h.in: Alpha support. + +Fri Nov 22 06:48:45 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.h.in, ffi_common.h: Cygnus Support -> Cygnus Solutions. + +Wed Nov 20 22:31:01 1996 Anthony Green <green@hoser.cygnus.com> + + * ffi.h.in: Added ffi_type_void definition. + +Tue Oct 29 12:22:40 1996 Anthony Green <green@rtl.cygnus.com> + + * Makefile.am (hack_DATA): Always install ffi_mips.h. + + * ffi.h.in: Removed FFI_DEBUG. It's now in the correct + place (acconfig.h). + Added #include <stddef.h> for size_t definition. + +Tue Oct 15 17:23:35 1996 Anthony Green <green@hoser.cygnus.com> + + * ffi.h.in, ffi_common.h, ffi_mips.h: More clean up. + Commented out #define of FFI_DEBUG. + +Tue Oct 15 13:01:06 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi_common.h: Added bool definition. + + * ffi.h.in, ffi_common.h: Clean up based on LCLint output. + Added funny /*@...@*/ comments to annotate source. + +Mon Oct 14 12:29:23 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.h.in: Interface changes based on feedback from Jim + Blandy. + +Fri Oct 11 16:49:35 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.h.in: Small change for sparc support. + +Thu Oct 10 14:53:37 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi_mips.h: Added FFI_TYPE_STRUCT_* definitions for + special structure return types. + +Wed Oct 9 13:55:57 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.h.in: Added SIZEOF_ARG definition for X86 + +Tue Oct 8 11:40:36 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.h.in (FFI_FN): Added macro for eliminating compiler warnings. + Use it to case your function pointers to the proper type. + + * ffi_mips.h (SIZEOF_ARG): Added magic to fix type promotion bug. + + * Makefile.am (EXTRA_DIST): Added ffi_mips.h to EXTRA_DIST. + * Makefile: Rebuilt. + + * ffi_mips.h: Created. Moved all common mips definitions here. + +Mon Oct 7 10:58:12 1996 Anthony Green <green@hoser.cygnus.com> + + * ffi.h.in: The SGI assember is very picky about parens. Redefined + some macros to avoid problems. + + * ffi.h.in: Added FFI_DEFAULT_ABI definitions. Also added + externs for pointer, and 64bit integral ffi_types. + +Fri Oct 4 09:51:37 1996 Anthony Green <green@hoser.cygnus.com> + + * ffi.h.in: Added FFI_ABI member to ffi_cif and changed + function prototypes accordingly. + Added #define @TARGET@. Now programs including ffi.h don't + have to specify this themselves. + +Thu Oct 3 15:36:44 1996 Anthony Green <green@hoser.cygnus.com> + + * ffi.h.in: Changed ffi_prep_cif's values from void* to void** + + * Makefile.am (EXTRA_DIST): Added EXTRA_DIST for "make dist" + to work. + * Makefile.in: Regenerated. + +Wed Oct 2 10:16:59 1996 Anthony Green <green@hoser.cygnus.com> + + * Makefile.am: Created + * Makefile.in: Generated + + * ffi_common.h: Added rcsid comment + +Tue Oct 1 17:13:51 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.h.in, ffi_common.h: Created + +--- libffi/src ------------------------------------------------------------ + +Mon Oct 5 02:17:50 1998 Anthony Green <green@cygnus.com> + + * arm/ffi.c, arm/sysv.S: Created. + + * Makefile.am: Added arm files. + * Makefile.in: Rebuilt. + +Mon Oct 5 01:41:38 1998 Anthony Green <green@rtl.cygnus.com> + + * Makefile.am (libffi_la_LDFLAGS): Incremented revision. + +Sun Oct 4 16:27:17 1998 Anthony Green <green@cygnus.com> + + * alpha/osf.S (ffi_call_osf): Patch for DU assembler. + + * ffitest.c (main): long long and long double return values work + for x86. + +Fri Apr 17 11:50:58 1998 Anthony Green <green@hoser.cygnus.com> + + * Makefile.in: Rebuilt. + + * ffitest.c (main): Floating point tests not executed for systems + with broken lond double (SunOS 4 w/ GCC). + + * types.c: Fixed x86 alignment info for long long types. + +Thu Apr 16 07:15:28 1998 Anthony Green <green@ada.cygnus.com> + + * ffitest.c: Added more notes about GCC bugs under Irix 6. + +Wed Apr 15 08:42:22 1998 Anthony Green <green@hoser.cygnus.com> + + * ffitest.c (struct5): New test function. + (main): New test with struct5. + +Thu Mar 5 10:48:11 1998 Anthony Green <green@tootie.to.cygnus.com> + + * prep_cif.c (initialize_aggregate): Fix assertion for + nested structures. + +Tue Feb 24 16:33:41 1998 Anthony Green <green@hoser.cygnus.com> + + * prep_cif.c (ffi_prep_cif): Added long double support for sparc. + +Sun Feb 22 00:52:18 1998 Geoff Keating <geoffk@ozemail.com.au> + + * powerpc/asm.h: New file. + * powerpc/ffi.c: New file. + * powerpc/sysv.S: New file. + * Makefile.am: PowerPC port. + * ffitest.c (main): Allow all tests to run even in presence of gcc + bug on PowerPC. + +1998-02-17 Anthony Green <green@hoser.cygnus.com> + + * mips/ffi.c: Fixed comment typo. + + * x86/ffi.c (ffi_prep_cif_machdep), x86/sysv.S (retfloat): + Fixed x86 long double return handling. + + * types.c: Fixed x86 long double alignment info. + +1998-02-14 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * types.c: Add m68k support. + + * ffitest.c (floating): Add long double parameter. + (return_ll, ldblit): New functions to test long long and long + double return value. + (main): Fix type error in assignment of ts[1-4]_type.elements. + Add tests for long long and long double arguments and return + values. + + * prep_cif.c (ffi_prep_cif) [M68K]: Don't allocate argument for + struct value pointer. + + * m68k/ffi.c, m68k/sysv.S: New files. + * Makefile.am: Add bits for m68k port. Add kludge to work around + automake deficiency. + (test): Don't require "." in $PATH. + * Makefile.in: Rebuilt. + +Wed Feb 11 07:36:50 1998 Anthony Green <green@hoser.cygnus.com> + + * Makefile.in: Rebuilt. + +Tue Feb 10 20:56:00 1998 Richard Henderson <rth@cygnus.com> + + * alpha/ffi.c, alpha/osf.S: New files. + * Makefile.am: Alpha port. + +Tue Nov 18 14:12:07 1997 Anthony Green <green@hoser.cygnus.com> + + * mips/ffi.c (ffi_prep_cif_machdep): Initialize rstruct_flag + for n32. + +Tue Jun 3 17:18:20 1997 Anthony Green <green@hoser.cygnus.com> + + * ffitest.c (main): Added hack to get structure tests working + correctly. + +Sat May 10 19:06:42 1997 Tom Tromey <tromey@cygnus.com> + + * Makefile.in: Rebuilt. + * Makefile.am (EXTRA_DIST): Explicitly list all distributable + files in subdirs. + (VERSION, CC): Removed. + +Thu May 8 17:19:01 1997 Anthony Green <green@hoser.cygnus.com> + + * Makefile.am: Many changes for new automake and libtool. + * Makefile.in: Rebuilt. + +Fri Nov 22 06:57:56 1996 Anthony Green <green@rtl.cygnus.com> + + * ffitest.c (main): Fixed test case for non mips machines. + +Wed Nov 20 22:31:59 1996 Anthony Green <green@hoser.cygnus.com> + + * types.c: Added ffi_type_void declaration. + +Tue Oct 29 13:07:19 1996 Anthony Green <green@rtl.cygnus.com> + + * ffitest.c (main): Fixed character constants. + (main): Emit warning for structure test 3 failure on Sun. + + * Makefile.am (VPATH): Fixed VPATH def'n so automake won't + strip it out. + Moved distdir hack from libffi to automake. + (ffitest): Added missing -c for $(COMPILE) (change in automake). + * Makefile.in: Rebuilt. + +Tue Oct 15 13:08:20 1996 Anthony Green <green@hoser.cygnus.com> + + * Makefile.am: Added "make lint" production. + * Makefile.in: Rebuilt. + + * prep_cif.c (STACK_ARG_SIZE): Improved STACK_ARG_SIZE macro. + Clean up based on LCLint output. Added funny /*@...@*/ comments to + annotate source. + + * ffitest.c, debug.c: Cleaned up code. + +Mon Oct 14 12:26:56 1996 Anthony Green <green@rtl.cygnus.com> + + * ffitest.c: Changes based on interface changes. + + * prep_cif.c (ffi_prep_cif): Cleaned up interface based on + feedback from Jim Blandy. + +Fri Oct 11 15:53:18 1996 Anthony Green <green@rtl.cygnus.com> + + * ffitest.c: Reordered tests while porting to sparc. + Made changes to handle lame structure passing for sparc. + Removed calls to fflush(). + + * prep_cif.c (ffi_prep_cif): Added special case for sparc + aggregate type arguments. + +Thu Oct 10 09:56:51 1996 Anthony Green <green@rtl.cygnus.com> + + * ffitest.c (main): Added structure passing/returning tests. + + * prep_cif.c (ffi_prep_cif): Perform proper initialization + of structure return types if needed. + (initialize_aggregate): Bug fix + +Wed Oct 9 16:04:20 1996 Anthony Green <green@rtl.cygnus.com> + + * types.c: Added special definitions for x86 (double doesn't + need double word alignment). + + * ffitest.c: Added many tests + +Tue Oct 8 09:19:22 1996 Anthony Green <green@rtl.cygnus.com> + + * prep_cif.c (ffi_prep_cif): Fixed assertion. + + * debug.c (ffi_assert): Must return a non void now. + + * Makefile.am: Added test production. + * Makefile: Rebuilt. + + * ffitest.c (main): Created. + + * types.c: Created. Stripped common code out of */ffi.c. + + * prep_cif.c: Added missing stdlib.h include. + + * debug.c (ffi_type_test): Used "a" to eliminate compiler + warnings in non-debug builds. Included ffi_common.h. + +Mon Oct 7 15:36:42 1996 Anthony Green <green@rtl.cygnus.com> + + * Makefile.am: Added a rule for .s -> .o + This is required by the SGI compiler. + * Makefile: Rebuilt. + +Fri Oct 4 09:51:08 1996 Anthony Green <green@hoser.cygnus.com> + + * prep_cif.c (initialize_aggregate): Moved abi specification + to ffi_prep_cif(). + +Thu Oct 3 15:37:37 1996 Anthony Green <green@hoser.cygnus.com> + + * prep_cif.c (ffi_prep_cif): Changed values from void* to void**. + (initialize_aggregate): Fixed aggregate type initialization. + + * Makefile.am (EXTRA_DIST): Added support code for "make dist". + * Makefile.in: Regenerated. + +Wed Oct 2 11:41:57 1996 Anthony Green <green@hoser.cygnus.com> + + * debug.c, prep_cif: Created. + + * Makefile.am: Added debug.o and prep_cif.o to OBJ. + * Makefile.in: Regenerated. + + * Makefile.am (INCLUDES): Added missing -I../include + * Makefile.in: Regenerated. + +Tue Oct 1 17:11:51 1996 Anthony Green <green@rtl.cygnus.com> + + * error.c, Makefile.am: Created. + * Makefile.in: Generated. + +--- libffi/src/x86 -------------------------------------------------------- + +Sun Oct 4 16:27:17 1998 Anthony Green <green@cygnus.com> + + * sysv.S (retlongdouble): Fixed long long return value support. + * ffi.c (ffi_prep_cif_machdep): Ditto. + +Wed May 13 04:30:33 1998 Anthony Green <green@raft.ppp.tsoft.net> + + * ffi.c (ffi_prep_cif_machdep): Fixed long double return value + support. + +Wed Apr 15 08:43:20 1998 Anthony Green <green@hoser.cygnus.com> + + * ffi.c (ffi_prep_args): small struct support was missing. + +Thu May 8 16:53:58 1997 Anthony Green <green@hoser.cygnus.com> + + * objects.mak: Removed. + +Mon Dec 2 15:12:58 1996 Tom Tromey <tromey@cygnus.com> + + * sysv.S: Use .balign, for a.out Linux boxes. + +Tue Oct 15 13:06:50 1996 Anthony Green <green@hoser.cygnus.com> + + * ffi.c: Clean up based on LCLint output. + Added funny /*@...@*/ comments to annotate source. + +Fri Oct 11 16:43:38 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.c (ffi_call): Added assertion for bad ABIs. + +Wed Oct 9 13:57:27 1996 Anthony Green <green@rtl.cygnus.com> + + * sysv.S (retdouble): Fixed double return problems. + + * ffi.c (ffi_call): Corrected fn arg definition. + (ffi_prep_cif_machdep): Fixed double return problems + +Tue Oct 8 12:12:49 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.c: Moved ffi_type definitions to types.c. + (ffi_prep_args): Fixed type promotion bug. + +Mon Oct 7 15:53:06 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.c (FFI_*_TYPEDEF): Removed redundant ';' + +Fri Oct 4 09:54:53 1996 Anthony Green <green@hoser.cygnus.com> + + * ffi.c (ffi_call): Removed FFI_ABI arg, and swapped + remaining args. + +Wed Oct 2 10:07:05 1996 Anthony Green <green@hoser.cygnus.com> + + * ffi.c, sysv.S, objects.mak: Created. + (ffi_prep_cif): cif->rvalue no longer initialized to NULL. + (ffi_prep_cif_machdep): Moved machine independent cif processing + to src/prep_cif.c. Introduced ffi_prep_cif_machdep(). + +--- libffi/src/mips ------------------------------------------------------- + +Tue Feb 17 17:18:07 1998 Anthony Green <green@hoser.cygnus.com> + + * o32.S: Fixed typo in comment. + + * ffi.c (ffi_prep_cif_machdep): Fixed argument processing. + +Thu May 8 16:53:58 1997 Anthony Green <green@hoser.cygnus.com> + + * o32.s, n32.s: Wrappers for SGI tool support. + + * objects.mak: Removed. + +Tue Oct 29 14:37:45 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.c (ffi_prep_args): Changed int z to size_t z. + +Tue Oct 15 13:17:25 1996 Anthony Green <green@hoser.cygnus.com> + + * n32.S: Fixed bad stack munging. + + * ffi.c: Moved prototypes for ffi_call_?32() to here from + ffi_mips.h because extended_cif is not defined in ffi_mips.h. + +Mon Oct 14 12:42:02 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.c: Interface changes based on feedback from Jim Blandy. + +Thu Oct 10 11:22:16 1996 Anthony Green <green@rtl.cygnus.com> + + * n32.S, ffi.c: Lots of changes to support passing and + returning structures with the n32 calling convention. + + * n32.S: Fixed fn pointer bug. + + * ffi.c (ffi_prep_cif_machdep): Fix for o32 structure + return values. + (ffi_prep_args): Fixed n32 structure passing when structures + partially fit in registers. + +Wed Oct 9 13:49:25 1996 Anthony Green <green@rtl.cygnus.com> + + * objects.mak: Added n32.o. + + * n32.S: Created. + + * ffi.c (ffi_prep_args): Added magic to support proper + n32 processing. + +Tue Oct 8 10:37:35 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.c: Moved ffi_type definitions to types.c. + (ffi_prep_args): Fixed type promotion bug. + + * o32.S: This code is only built for o32 compiles. + A lot of the #define cruft has moved to ffi_mips.h. + + * ffi.c (ffi_prep_cif_machdep): Fixed arg flags. Second arg + is only processed if the first is either a float or double. + +Mon Oct 7 15:33:59 1996 Anthony Green <green@rtl.cygnus.com> + + * o32.S: Modified to compile under each of o32, n32 and n64. + + * ffi.c (FFI_*_TYPEDEF): Removed redundant ';' + +Fri Oct 4 09:53:25 1996 Anthony Green <green@hoser.cygnus.com> + + * ffi.c (ffi_call): Removed FFI_ABI arg, and swapped + remaining args. + +Wed Oct 2 17:41:22 1996 Anthony Green <green@rtl.cygnus.com> + + * o32.S: Removed crufty definitions. + +Wed Oct 2 12:53:42 1996 Anthony Green <green@hoser.cygnus.com> + + * ffi.c (ffi_prep_cif): cif->rvalue no longer initialized to NULL. + (ffi_prep_cif_machdep): Moved all machine independent cif processing + to src/prep_cif.c. Introduced ffi_prep_cif_machdep. Return types + of FFI_TYPE_STRUCT are no different than FFI_TYPE_INT. + +Tue Oct 1 17:11:02 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.c, o32.S, object.mak: Created + +--- libffi/src/sparc ------------------------------------------------------ + +Tue Feb 24 16:33:18 1998 Anthony Green <green@hoser.cygnus.com> + + * ffi.c (ffi_prep_args): Added long double support. + +Thu May 8 16:53:58 1997 Anthony Green <green@hoser.cygnus.com> + + * objects.mak: Removed. + +Thu May 1 16:07:56 1997 Anthony Green <green@hoser.cygnus.com> + + * v8.S: Fixed minor portability problem reported by + Russ McManus <mcmanr@eq.gs.com>. + +Tue Nov 26 14:12:43 1996 Anthony Green <green@csk3.cygnus.com> + + * v8.S: Used STACKFRAME define elsewhere. + + * ffi.c (ffi_prep_args): Zero out space when USING_PURIFY + is set. + (ffi_prep_cif_machdep): Allocate the correct stack frame + space for functions with < 6 args. + +Tue Oct 29 15:08:55 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.c (ffi_prep_args): int z is now size_t z. + +Mon Oct 14 13:31:24 1996 Anthony Green <green@rtl.cygnus.com> + + * v8.S (ffi_call_V8): Gordon rewrites this again. It looks + great now. + + * ffi.c (ffi_call): The comment about hijacked registers + is no longer valid after gordoni hacked v8.S. + + * v8.S (ffi_call_V8): Rewrote with gordoni. Much simpler. + + * v8.S, ffi.c: ffi_call() had changed to accept more than + two args, so v8.S had to change (because it hijacks incoming + arg registers). + + * ffi.c: Interface changes based on feedback from Jim Blandy. + +Thu Oct 10 17:48:16 1996 Anthony Green <green@rtl.cygnus.com> + + * ffi.c, v8.S, objects.mak: Created. + + diff --git a/libffi/HOWTO_MERGE b/libffi/HOWTO_MERGE new file mode 100644 index 0000000..5b92b10 --- /dev/null +++ b/libffi/HOWTO_MERGE @@ -0,0 +1,13 @@ +In general, merging process should not be very difficult, but we need to +track GCC-specific patches carefully. Here is a general list of actions +required to perform the merge: + +* Checkout recent GCC tree. +* Run merge.sh script from the libffi directory. +* Add new files and remove old files if needed. +* Apply all needed GCC-specific patches to libffi (note that some of + them might be already included to upstream). The list of these patches + is stored into LOCAL_PATCHES file. May need to re-run autogen.sh to + regenerate configure and Makefile.in files. +* Send your patches for review to GCC Patches Mailing List (gcc-patches@gcc.gnu.org). +* Update LOCAL_PATCHES file when you've committed the whole patch set with new revisions numbers. diff --git a/libffi/LICENSE b/libffi/LICENSE index a66fab4..e4034b0 100644 --- a/libffi/LICENSE +++ b/libffi/LICENSE @@ -1,4 +1,4 @@ -libffi - Copyright (c) 1996-2014 Anthony Green, Red Hat, Inc and others. +libffi - Copyright (c) 1996-2021 Anthony Green, Red Hat, Inc and others. See source files for details. Permission is hereby granted, free of charge, to any person obtaining diff --git a/libffi/LICENSE-BUILDTOOLS b/libffi/LICENSE-BUILDTOOLS new file mode 100644 index 0000000..d1d626e --- /dev/null +++ b/libffi/LICENSE-BUILDTOOLS @@ -0,0 +1,353 @@ +The libffi source distribution contains certain code that is not part +of libffi, and is only used as tooling to assist with the building and +testing of libffi. This includes the msvcc.sh script used to wrap the +Microsoft compiler with GNU compatible command-line options, +make_sunver.pl, and the libffi test code distributed in the +testsuite/libffi.bhaible directory. This code is distributed with +libffi for the purpose of convenience only, and libffi is in no way +derived from this code. + +msvcc.sh an testsuite/libffi.bhaible are both distributed under the +terms of the GNU GPL version 2, as below. + + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/libffi/LOCAL_PATCHES b/libffi/LOCAL_PATCHES new file mode 100644 index 0000000..a377c28 --- /dev/null +++ b/libffi/LOCAL_PATCHES @@ -0,0 +1,2 @@ +5be7b66998127286fada45e4f23bd8a2056d553e +4824ed41ba7cd63e60fd9f8769a58b79935a90d1 diff --git a/libffi/MERGE b/libffi/MERGE new file mode 100644 index 0000000..fd0076e --- /dev/null +++ b/libffi/MERGE @@ -0,0 +1,4 @@ +f9ea41683444ebe11cfa45b05223899764df28fb + +The first line of this file holds the git revision number of the +last merge done from the master library sources. diff --git a/libffi/Makefile.am b/libffi/Makefile.am index 203b7d1..02e3617 100644 --- a/libffi/Makefile.am +++ b/libffi/Makefile.am @@ -6,14 +6,14 @@ ACLOCAL_AMFLAGS = -I .. -I ../config SUBDIRS = include testsuite man -EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj \ - ChangeLog.libffi ChangeLog.libffi-3.1 \ +EXTRA_DIST = LICENSE ChangeLog.old \ m4/libtool.m4 m4/lt~obsolete.m4 \ m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 \ m4/ltversion.m4 src/debug.c msvcc.sh \ generate-darwin-source-and-headers.py \ libffi.xcodeproj/project.pbxproj \ - libtool-ldflags + libtool-ldflags libtool-version configure.host README.md \ + libffi.map.in LICENSE-BUILDTOOLS msvc_build make_sunver.pl # local.exp is generated by configure DISTCLEANFILES = local.exp @@ -37,7 +37,7 @@ STAMP_GENINSRC = endif # AM_CONDITIONAL on configure check ACX_CHECK_PROG_VER([MAKEINFO]) -if BUILD_INFO +if BUILD_DOCS STAMP_BUILD_INFO = stamp-build-info else STAMP_BUILD_INFO = @@ -114,82 +114,62 @@ toolexeclib_LTLIBRARIES = libffi.la noinst_LTLIBRARIES = libffi_convenience.la libffi_la_SOURCES = src/prep_cif.c src/types.c \ - src/raw_api.c src/java_raw_api.c src/closures.c + src/raw_api.c src/java_raw_api.c src/closures.c \ + src/tramp.c if FFI_DEBUG libffi_la_SOURCES += src/debug.c endif -noinst_HEADERS = \ - src/aarch64/ffitarget.h src/aarch64/internal.h \ +noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h \ src/alpha/ffitarget.h src/alpha/internal.h \ - src/arc/ffitarget.h \ - src/arm/ffitarget.h src/arm/internal.h \ - src/avr32/ffitarget.h \ - src/bfin/ffitarget.h \ - src/cris/ffitarget.h \ - src/frv/ffitarget.h \ + src/arc/ffitarget.h src/arm/ffitarget.h src/arm/internal.h \ + src/avr32/ffitarget.h src/bfin/ffitarget.h \ + src/cris/ffitarget.h src/csky/ffitarget.h src/frv/ffitarget.h \ src/ia64/ffitarget.h src/ia64/ia64_flags.h \ - src/m32r/ffitarget.h \ - src/m68k/ffitarget.h \ - src/m88k/ffitarget.h \ - src/metag/ffitarget.h \ - src/microblaze/ffitarget.h \ - src/mips/ffitarget.h \ - src/moxie/ffitarget.h \ - src/nios2/ffitarget.h \ - src/or1k/ffitarget.h \ - src/pa/ffitarget.h \ - src/powerpc/ffitarget.h src/powerpc/asm.h src/powerpc/ffi_powerpc.h \ - src/riscv/ffitarget.h \ - src/s390/ffitarget.h \ - src/sh/ffitarget.h \ - src/sh64/ffitarget.h \ - src/sparc/ffitarget.h src/sparc/internal.h \ - src/tile/ffitarget.h \ - src/vax/ffitarget.h \ + src/m32r/ffitarget.h src/m68k/ffitarget.h \ + src/m88k/ffitarget.h src/metag/ffitarget.h \ + src/microblaze/ffitarget.h src/mips/ffitarget.h \ + src/moxie/ffitarget.h src/nios2/ffitarget.h \ + src/or1k/ffitarget.h src/pa/ffitarget.h \ + src/powerpc/ffitarget.h src/powerpc/asm.h \ + src/powerpc/ffi_powerpc.h src/riscv/ffitarget.h \ + src/s390/ffitarget.h src/s390/internal.h src/sh/ffitarget.h \ + src/sh64/ffitarget.h src/sparc/ffitarget.h \ + src/sparc/internal.h src/tile/ffitarget.h src/vax/ffitarget.h \ src/x86/ffitarget.h src/x86/internal.h src/x86/internal64.h \ - src/xtensa/ffitarget.h \ - src/dlmalloc.c - -EXTRA_libffi_la_SOURCES = \ - src/aarch64/ffi.c src/aarch64/sysv.S \ - src/alpha/ffi.c src/alpha/osf.S \ - src/arc/ffi.c src/arc/arcompact.S \ - src/arm/ffi.c src/arm/sysv.S \ - src/avr32/ffi.c src/avr32/sysv.S \ - src/bfin/ffi.c src/bfin/sysv.S \ - src/cris/ffi.c src/cris/sysv.S \ - src/frv/ffi.c src/frv/eabi.S \ - src/ia64/ffi.c src/ia64/unix.S \ - src/m32r/ffi.c src/m32r/sysv.S \ - src/m68k/ffi.c src/m68k/sysv.S \ - src/m88k/ffi.c src/m88k/obsd.S \ - src/metag/ffi.c src/metag/sysv.S \ - src/microblaze/ffi.c src/microblaze/sysv.S \ - src/mips/ffi.c src/mips/o32.S src/mips/n32.S \ - src/moxie/ffi.c src/moxie/eabi.S \ - src/nios2/ffi.c src/nios2/sysv.S \ - src/or1k/ffi.c src/or1k/sysv.S \ - src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S \ - src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c \ - src/powerpc/sysv.S src/powerpc/linux64.S \ - src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S \ - src/powerpc/aix.S src/powerpc/darwin.S src/powerpc/aix_closure.S \ - src/powerpc/darwin_closure.S src/powerpc/ffi_darwin.c \ - src/riscv/ffi.c src/riscv/sysv.S \ - src/s390/ffi.c src/s390/sysv.S \ - src/sh/ffi.c src/sh/sysv.S \ - src/sh64/ffi.c src/sh64/sysv.S \ - src/sparc/ffi.c src/sparc/ffi64.c src/sparc/v8.S src/sparc/v9.S \ - src/tile/ffi.c src/tile/tile.S \ - src/vax/ffi.c src/vax/elfbsd.S \ - src/x86/ffi.c src/x86/sysv.S \ - src/x86/ffiw64.c src/x86/win64.S \ - src/x86/ffi64.c src/x86/unix64.S \ - src/x86/darwin64.S src/x86/darwin.S \ - src/x86/darwin64_c.c src/x86/darwin_c.c \ - src/xtensa/ffi.c src/xtensa/sysv.S + src/x86/asmnames.h src/xtensa/ffitarget.h src/dlmalloc.c \ + src/kvx/ffitarget.h + +EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S \ + src/aarch64/win64_armasm.S src/alpha/ffi.c src/alpha/osf.S \ + src/arc/ffi.c src/arc/arcompact.S src/arm/ffi.c \ + src/arm/sysv.S src/arm/ffi.c src/arm/sysv_msvc_arm32.S \ + src/avr32/ffi.c src/avr32/sysv.S src/bfin/ffi.c \ + src/bfin/sysv.S src/cris/ffi.c src/cris/sysv.S src/frv/ffi.c \ + src/csky/ffi.c src/csky/sysv.S src/frv/eabi.S src/ia64/ffi.c \ + src/ia64/unix.S src/m32r/ffi.c src/m32r/sysv.S src/m68k/ffi.c \ + src/m68k/sysv.S src/m88k/ffi.c src/m88k/obsd.S \ + src/metag/ffi.c src/metag/sysv.S src/microblaze/ffi.c \ + src/microblaze/sysv.S src/mips/ffi.c src/mips/o32.S \ + src/mips/n32.S src/moxie/ffi.c src/moxie/eabi.S \ + src/nios2/ffi.c src/nios2/sysv.S src/or1k/ffi.c \ + src/or1k/sysv.S src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S \ + src/powerpc/ffi.c src/powerpc/ffi_sysv.c \ + src/powerpc/ffi_linux64.c src/powerpc/sysv.S \ + src/powerpc/linux64.S src/powerpc/linux64_closure.S \ + src/powerpc/ppc_closure.S src/powerpc/aix.S \ + src/powerpc/darwin.S src/powerpc/aix_closure.S \ + src/powerpc/darwin_closure.S src/powerpc/ffi_darwin.c \ + src/riscv/ffi.c src/riscv/sysv.S src/s390/ffi.c \ + src/s390/sysv.S src/sh/ffi.c src/sh/sysv.S src/sh64/ffi.c \ + src/sh64/sysv.S src/sparc/ffi.c src/sparc/ffi64.c \ + src/sparc/v8.S src/sparc/v9.S src/tile/ffi.c src/tile/tile.S \ + src/vax/ffi.c src/vax/elfbsd.S src/x86/ffi.c src/x86/sysv.S \ + src/x86/ffiw64.c src/x86/win64.S src/x86/ffi64.c \ + src/x86/unix64.S src/x86/sysv_intel.S src/x86/win64_intel.S \ + src/xtensa/ffi.c src/xtensa/sysv.S src/kvx/ffi.c \ + src/kvx/sysv.S TARGET_OBJ = @TARGET_OBJ@ libffi_la_LIBADD = $(TARGET_OBJ) @@ -209,16 +189,16 @@ if FFI_DEBUG AM_CFLAGS += -DFFI_DEBUG endif -if LIBAT_BUILD_VERSIONED_SHLIB -if LIBAT_BUILD_VERSIONED_SHLIB_GNU +if LIBFFI_BUILD_VERSIONED_SHLIB +if LIBFFI_BUILD_VERSIONED_SHLIB_GNU libffi_version_script = -Wl,--version-script,libffi.map libffi_version_dep = libffi.map endif -if LIBAT_BUILD_VERSIONED_SHLIB_SUN +if LIBFFI_BUILD_VERSIONED_SHLIB_SUN libffi_version_script = -Wl,-M,libffi.map-sun libffi_version_dep = libffi.map-sun libffi.map-sun : libffi.map $(top_srcdir)/../contrib/make_sunver.pl \ - $(libffi_la_OBJECTS) $(libffi_la_LIBADD) + $(libffi_la_OBJECTS) $(libffi_la_LIBADD) perl $(top_srcdir)/../contrib/make_sunver.pl libffi.map \ `echo $(libffi_la_OBJECTS) $(libffi_la_LIBADD) | \ sed 's,\([^/ ]*\)\.l\([ao]\),.libs/\1.\2,g'` \ @@ -231,7 +211,8 @@ endif libffi_version_info = -version-info `grep -v '^\#' $(srcdir)/libtool-version` libffi.map: $(top_srcdir)/libffi.map.in - $(COMPILE) -D$(TARGET) -E -x assembler-with-cpp -o $@ $< + $(COMPILE) -D$(TARGET) -DGENERATE_LIBFFI_MAP \ + -E -x assembler-with-cpp -o $@ $(top_srcdir)/libffi.map.in libffi_la_LDFLAGS = -no-undefined $(libffi_version_info) $(libffi_version_script) $(LTLDFLAGS) $(AM_LTLDFLAGS) libffi_la_DEPENDENCIES = $(libffi_la_LIBADD) $(libffi_version_dep) diff --git a/libffi/Makefile.in b/libffi/Makefile.in index 745bdd8..6ff0c67 100644 --- a/libffi/Makefile.in +++ b/libffi/Makefile.in @@ -153,7 +153,8 @@ am__DEPENDENCIES_1 = am__dirstamp = $(am__leading_dot)dirstamp @FFI_DEBUG_TRUE@am__objects_1 = src/debug.lo am_libffi_la_OBJECTS = src/prep_cif.lo src/types.lo src/raw_api.lo \ - src/java_raw_api.lo src/closures.lo $(am__objects_1) + src/java_raw_api.lo src/closures.lo src/tramp.lo \ + $(am__objects_1) libffi_la_OBJECTS = $(am_libffi_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -164,7 +165,8 @@ libffi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(libffi_la_LDFLAGS) $(LDFLAGS) -o $@ am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) am__objects_2 = src/prep_cif.lo src/types.lo src/raw_api.lo \ - src/java_raw_api.lo src/closures.lo $(am__objects_1) + src/java_raw_api.lo src/closures.lo src/tramp.lo \ + $(am__objects_1) am_libffi_convenience_la_OBJECTS = $(am__objects_2) nodist_libffi_convenience_la_OBJECTS = libffi_convenience_la_OBJECTS = $(am_libffi_convenience_la_OBJECTS) \ @@ -372,6 +374,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ +READELF = @READELF@ SECTION_LDFLAGS = @SECTION_LDFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -444,14 +447,14 @@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign subdir-objects info-in-builddir ACLOCAL_AMFLAGS = -I .. -I ../config SUBDIRS = include testsuite man -EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj \ - ChangeLog.libffi ChangeLog.libffi-3.1 \ +EXTRA_DIST = LICENSE ChangeLog.old \ m4/libtool.m4 m4/lt~obsolete.m4 \ m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 \ m4/ltversion.m4 src/debug.c msvcc.sh \ generate-darwin-source-and-headers.py \ libffi.xcodeproj/project.pbxproj \ - libtool-ldflags + libtool-ldflags libtool-version configure.host README.md \ + libffi.map.in LICENSE-BUILDTOOLS msvc_build make_sunver.pl # local.exp is generated by configure @@ -471,10 +474,10 @@ info_TEXINFOS = doc/libffi.texi # AM_CONDITIONAL on configure option --generated-files-in-srcdir @GENINSRC_TRUE@STAMP_GENINSRC = stamp-geninsrc -@BUILD_INFO_FALSE@STAMP_BUILD_INFO = +@BUILD_DOCS_FALSE@STAMP_BUILD_INFO = # AM_CONDITIONAL on configure check ACX_CHECK_PROG_VER([MAKEINFO]) -@BUILD_INFO_TRUE@STAMP_BUILD_INFO = stamp-build-info +@BUILD_DOCS_TRUE@STAMP_BUILD_INFO = stamp-build-info CLEANFILES = $(STAMP_GENINSRC) $(STAMP_BUILD_INFO) MAINTAINERCLEANFILES = $(srcdir)/doc/libffi.info @@ -525,77 +528,56 @@ pkgconfig_DATA = libffi.pc toolexeclib_LTLIBRARIES = libffi.la noinst_LTLIBRARIES = libffi_convenience.la libffi_la_SOURCES = src/prep_cif.c src/types.c src/raw_api.c \ - src/java_raw_api.c src/closures.c $(am__append_1) -noinst_HEADERS = \ - src/aarch64/ffitarget.h src/aarch64/internal.h \ + src/java_raw_api.c src/closures.c src/tramp.c $(am__append_1) +noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h \ src/alpha/ffitarget.h src/alpha/internal.h \ - src/arc/ffitarget.h \ - src/arm/ffitarget.h src/arm/internal.h \ - src/avr32/ffitarget.h \ - src/bfin/ffitarget.h \ - src/cris/ffitarget.h \ - src/frv/ffitarget.h \ + src/arc/ffitarget.h src/arm/ffitarget.h src/arm/internal.h \ + src/avr32/ffitarget.h src/bfin/ffitarget.h \ + src/cris/ffitarget.h src/csky/ffitarget.h src/frv/ffitarget.h \ src/ia64/ffitarget.h src/ia64/ia64_flags.h \ - src/m32r/ffitarget.h \ - src/m68k/ffitarget.h \ - src/m88k/ffitarget.h \ - src/metag/ffitarget.h \ - src/microblaze/ffitarget.h \ - src/mips/ffitarget.h \ - src/moxie/ffitarget.h \ - src/nios2/ffitarget.h \ - src/or1k/ffitarget.h \ - src/pa/ffitarget.h \ - src/powerpc/ffitarget.h src/powerpc/asm.h src/powerpc/ffi_powerpc.h \ - src/riscv/ffitarget.h \ - src/s390/ffitarget.h \ - src/sh/ffitarget.h \ - src/sh64/ffitarget.h \ - src/sparc/ffitarget.h src/sparc/internal.h \ - src/tile/ffitarget.h \ - src/vax/ffitarget.h \ + src/m32r/ffitarget.h src/m68k/ffitarget.h \ + src/m88k/ffitarget.h src/metag/ffitarget.h \ + src/microblaze/ffitarget.h src/mips/ffitarget.h \ + src/moxie/ffitarget.h src/nios2/ffitarget.h \ + src/or1k/ffitarget.h src/pa/ffitarget.h \ + src/powerpc/ffitarget.h src/powerpc/asm.h \ + src/powerpc/ffi_powerpc.h src/riscv/ffitarget.h \ + src/s390/ffitarget.h src/s390/internal.h src/sh/ffitarget.h \ + src/sh64/ffitarget.h src/sparc/ffitarget.h \ + src/sparc/internal.h src/tile/ffitarget.h src/vax/ffitarget.h \ src/x86/ffitarget.h src/x86/internal.h src/x86/internal64.h \ - src/xtensa/ffitarget.h \ - src/dlmalloc.c - -EXTRA_libffi_la_SOURCES = \ - src/aarch64/ffi.c src/aarch64/sysv.S \ - src/alpha/ffi.c src/alpha/osf.S \ - src/arc/ffi.c src/arc/arcompact.S \ - src/arm/ffi.c src/arm/sysv.S \ - src/avr32/ffi.c src/avr32/sysv.S \ - src/bfin/ffi.c src/bfin/sysv.S \ - src/cris/ffi.c src/cris/sysv.S \ - src/frv/ffi.c src/frv/eabi.S \ - src/ia64/ffi.c src/ia64/unix.S \ - src/m32r/ffi.c src/m32r/sysv.S \ - src/m68k/ffi.c src/m68k/sysv.S \ - src/m88k/ffi.c src/m88k/obsd.S \ - src/metag/ffi.c src/metag/sysv.S \ - src/microblaze/ffi.c src/microblaze/sysv.S \ - src/mips/ffi.c src/mips/o32.S src/mips/n32.S \ - src/moxie/ffi.c src/moxie/eabi.S \ - src/nios2/ffi.c src/nios2/sysv.S \ - src/or1k/ffi.c src/or1k/sysv.S \ - src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S \ - src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c \ - src/powerpc/sysv.S src/powerpc/linux64.S \ - src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S \ - src/powerpc/aix.S src/powerpc/darwin.S src/powerpc/aix_closure.S \ - src/powerpc/darwin_closure.S src/powerpc/ffi_darwin.c \ - src/riscv/ffi.c src/riscv/sysv.S \ - src/s390/ffi.c src/s390/sysv.S \ - src/sh/ffi.c src/sh/sysv.S \ - src/sh64/ffi.c src/sh64/sysv.S \ - src/sparc/ffi.c src/sparc/ffi64.c src/sparc/v8.S src/sparc/v9.S \ - src/tile/ffi.c src/tile/tile.S \ - src/vax/ffi.c src/vax/elfbsd.S \ - src/x86/ffi.c src/x86/sysv.S \ - src/x86/ffiw64.c src/x86/win64.S \ - src/x86/ffi64.c src/x86/unix64.S \ - src/x86/darwin64.S src/x86/darwin.S \ - src/x86/darwin64_c.c src/x86/darwin_c.c \ - src/xtensa/ffi.c src/xtensa/sysv.S + src/x86/asmnames.h src/xtensa/ffitarget.h src/dlmalloc.c \ + src/kvx/ffitarget.h + +EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S \ + src/aarch64/win64_armasm.S src/alpha/ffi.c src/alpha/osf.S \ + src/arc/ffi.c src/arc/arcompact.S src/arm/ffi.c \ + src/arm/sysv.S src/arm/ffi.c src/arm/sysv_msvc_arm32.S \ + src/avr32/ffi.c src/avr32/sysv.S src/bfin/ffi.c \ + src/bfin/sysv.S src/cris/ffi.c src/cris/sysv.S src/frv/ffi.c \ + src/csky/ffi.c src/csky/sysv.S src/frv/eabi.S src/ia64/ffi.c \ + src/ia64/unix.S src/m32r/ffi.c src/m32r/sysv.S src/m68k/ffi.c \ + src/m68k/sysv.S src/m88k/ffi.c src/m88k/obsd.S \ + src/metag/ffi.c src/metag/sysv.S src/microblaze/ffi.c \ + src/microblaze/sysv.S src/mips/ffi.c src/mips/o32.S \ + src/mips/n32.S src/moxie/ffi.c src/moxie/eabi.S \ + src/nios2/ffi.c src/nios2/sysv.S src/or1k/ffi.c \ + src/or1k/sysv.S src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S \ + src/powerpc/ffi.c src/powerpc/ffi_sysv.c \ + src/powerpc/ffi_linux64.c src/powerpc/sysv.S \ + src/powerpc/linux64.S src/powerpc/linux64_closure.S \ + src/powerpc/ppc_closure.S src/powerpc/aix.S \ + src/powerpc/darwin.S src/powerpc/aix_closure.S \ + src/powerpc/darwin_closure.S src/powerpc/ffi_darwin.c \ + src/riscv/ffi.c src/riscv/sysv.S src/s390/ffi.c \ + src/s390/sysv.S src/sh/ffi.c src/sh/sysv.S src/sh64/ffi.c \ + src/sh64/sysv.S src/sparc/ffi.c src/sparc/ffi64.c \ + src/sparc/v8.S src/sparc/v9.S src/tile/ffi.c src/tile/tile.S \ + src/vax/ffi.c src/vax/elfbsd.S src/x86/ffi.c src/x86/sysv.S \ + src/x86/ffiw64.c src/x86/win64.S src/x86/ffi64.c \ + src/x86/unix64.S src/x86/sysv_intel.S src/x86/win64_intel.S \ + src/xtensa/ffi.c src/xtensa/sysv.S src/kvx/ffi.c \ + src/kvx/sysv.S libffi_la_LIBADD = $(TARGET_OBJ) libffi_convenience_la_SOURCES = $(libffi_la_SOURCES) @@ -605,12 +587,12 @@ libffi_convenience_la_DEPENDENCIES = $(libffi_la_DEPENDENCIES) nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES) LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) AM_CFLAGS = -Wall -g -fexceptions $(am__append_2) -@LIBAT_BUILD_VERSIONED_SHLIB_FALSE@libffi_version_script = -@LIBAT_BUILD_VERSIONED_SHLIB_GNU_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@libffi_version_script = -Wl,--version-script,libffi.map -@LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@libffi_version_script = -Wl,-M,libffi.map-sun -@LIBAT_BUILD_VERSIONED_SHLIB_FALSE@libffi_version_dep = -@LIBAT_BUILD_VERSIONED_SHLIB_GNU_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@libffi_version_dep = libffi.map -@LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@libffi_version_dep = libffi.map-sun +@LIBFFI_BUILD_VERSIONED_SHLIB_FALSE@libffi_version_script = +@LIBFFI_BUILD_VERSIONED_SHLIB_GNU_TRUE@@LIBFFI_BUILD_VERSIONED_SHLIB_TRUE@libffi_version_script = -Wl,--version-script,libffi.map +@LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBFFI_BUILD_VERSIONED_SHLIB_TRUE@libffi_version_script = -Wl,-M,libffi.map-sun +@LIBFFI_BUILD_VERSIONED_SHLIB_FALSE@libffi_version_dep = +@LIBFFI_BUILD_VERSIONED_SHLIB_GNU_TRUE@@LIBFFI_BUILD_VERSIONED_SHLIB_TRUE@libffi_version_dep = libffi.map +@LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBFFI_BUILD_VERSIONED_SHLIB_TRUE@libffi_version_dep = libffi.map-sun libffi_version_info = -version-info `grep -v '^\#' $(srcdir)/libtool-version` libffi_la_LDFLAGS = -no-undefined $(libffi_version_info) $(libffi_version_script) $(LTLDFLAGS) $(AM_LTLDFLAGS) libffi_la_DEPENDENCIES = $(libffi_la_LIBADD) $(libffi_version_dep) @@ -735,6 +717,7 @@ src/types.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/java_raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/closures.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/tramp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/debug.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/aarch64/$(am__dirstamp): @$(MKDIR_P) src/aarch64 @@ -746,6 +729,8 @@ src/aarch64/ffi.lo: src/aarch64/$(am__dirstamp) \ src/aarch64/$(DEPDIR)/$(am__dirstamp) src/aarch64/sysv.lo: src/aarch64/$(am__dirstamp) \ src/aarch64/$(DEPDIR)/$(am__dirstamp) +src/aarch64/win64_armasm.lo: src/aarch64/$(am__dirstamp) \ + src/aarch64/$(DEPDIR)/$(am__dirstamp) src/alpha/$(am__dirstamp): @$(MKDIR_P) src/alpha @: > src/alpha/$(am__dirstamp) @@ -776,6 +761,8 @@ src/arm/ffi.lo: src/arm/$(am__dirstamp) \ src/arm/$(DEPDIR)/$(am__dirstamp) src/arm/sysv.lo: src/arm/$(am__dirstamp) \ src/arm/$(DEPDIR)/$(am__dirstamp) +src/arm/sysv_msvc_arm32.lo: src/arm/$(am__dirstamp) \ + src/arm/$(DEPDIR)/$(am__dirstamp) src/avr32/$(am__dirstamp): @$(MKDIR_P) src/avr32 @: > src/avr32/$(am__dirstamp) @@ -814,6 +801,16 @@ src/frv/$(DEPDIR)/$(am__dirstamp): @: > src/frv/$(DEPDIR)/$(am__dirstamp) src/frv/ffi.lo: src/frv/$(am__dirstamp) \ src/frv/$(DEPDIR)/$(am__dirstamp) +src/csky/$(am__dirstamp): + @$(MKDIR_P) src/csky + @: > src/csky/$(am__dirstamp) +src/csky/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/csky/$(DEPDIR) + @: > src/csky/$(DEPDIR)/$(am__dirstamp) +src/csky/ffi.lo: src/csky/$(am__dirstamp) \ + src/csky/$(DEPDIR)/$(am__dirstamp) +src/csky/sysv.lo: src/csky/$(am__dirstamp) \ + src/csky/$(DEPDIR)/$(am__dirstamp) src/frv/eabi.lo: src/frv/$(am__dirstamp) \ src/frv/$(DEPDIR)/$(am__dirstamp) src/ia64/$(am__dirstamp): @@ -1050,13 +1047,9 @@ src/x86/ffi64.lo: src/x86/$(am__dirstamp) \ src/x86/$(DEPDIR)/$(am__dirstamp) src/x86/unix64.lo: src/x86/$(am__dirstamp) \ src/x86/$(DEPDIR)/$(am__dirstamp) -src/x86/darwin64.lo: src/x86/$(am__dirstamp) \ - src/x86/$(DEPDIR)/$(am__dirstamp) -src/x86/darwin.lo: src/x86/$(am__dirstamp) \ - src/x86/$(DEPDIR)/$(am__dirstamp) -src/x86/darwin64_c.lo: src/x86/$(am__dirstamp) \ +src/x86/sysv_intel.lo: src/x86/$(am__dirstamp) \ src/x86/$(DEPDIR)/$(am__dirstamp) -src/x86/darwin_c.lo: src/x86/$(am__dirstamp) \ +src/x86/win64_intel.lo: src/x86/$(am__dirstamp) \ src/x86/$(DEPDIR)/$(am__dirstamp) src/xtensa/$(am__dirstamp): @$(MKDIR_P) src/xtensa @@ -1068,6 +1061,16 @@ src/xtensa/ffi.lo: src/xtensa/$(am__dirstamp) \ src/xtensa/$(DEPDIR)/$(am__dirstamp) src/xtensa/sysv.lo: src/xtensa/$(am__dirstamp) \ src/xtensa/$(DEPDIR)/$(am__dirstamp) +src/kvx/$(am__dirstamp): + @$(MKDIR_P) src/kvx + @: > src/kvx/$(am__dirstamp) +src/kvx/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/kvx/$(DEPDIR) + @: > src/kvx/$(DEPDIR)/$(am__dirstamp) +src/kvx/ffi.lo: src/kvx/$(am__dirstamp) \ + src/kvx/$(DEPDIR)/$(am__dirstamp) +src/kvx/sysv.lo: src/kvx/$(am__dirstamp) \ + src/kvx/$(DEPDIR)/$(am__dirstamp) libffi.la: $(libffi_la_OBJECTS) $(libffi_la_DEPENDENCIES) $(EXTRA_libffi_la_DEPENDENCIES) $(AM_V_CCLD)$(libffi_la_LINK) -rpath $(toolexeclibdir) $(libffi_la_OBJECTS) $(libffi_la_LIBADD) $(LIBS) @@ -1093,10 +1096,14 @@ mostlyclean-compile: -rm -f src/bfin/*.lo -rm -f src/cris/*.$(OBJEXT) -rm -f src/cris/*.lo + -rm -f src/csky/*.$(OBJEXT) + -rm -f src/csky/*.lo -rm -f src/frv/*.$(OBJEXT) -rm -f src/frv/*.lo -rm -f src/ia64/*.$(OBJEXT) -rm -f src/ia64/*.lo + -rm -f src/kvx/*.$(OBJEXT) + -rm -f src/kvx/*.lo -rm -f src/m32r/*.$(OBJEXT) -rm -f src/m32r/*.lo -rm -f src/m68k/*.$(OBJEXT) @@ -1146,25 +1153,32 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/java_raw_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/prep_cif.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/raw_api.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tramp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/sysv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/win64_armasm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/osf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/arc/$(DEPDIR)/arcompact.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/arc/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/sysv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/sysv_msvc_arm32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/avr32/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/avr32/$(DEPDIR)/sysv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/bfin/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/bfin/$(DEPDIR)/sysv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/cris/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/cris/$(DEPDIR)/sysv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/csky/$(DEPDIR)/ffi.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/csky/$(DEPDIR)/sysv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/frv/$(DEPDIR)/eabi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/frv/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ia64/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ia64/$(DEPDIR)/unix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/kvx/$(DEPDIR)/ffi.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/kvx/$(DEPDIR)/sysv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/m32r/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/m32r/$(DEPDIR)/sysv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/m68k/$(DEPDIR)/ffi.Plo@am__quote@ @@ -1215,16 +1229,14 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/tile/$(DEPDIR)/tile.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/vax/$(DEPDIR)/elfbsd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/vax/$(DEPDIR)/ffi.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin64.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin64_c.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin_c.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffiw64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/sysv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/sysv_intel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/unix64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win64.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win64_intel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/xtensa/$(DEPDIR)/ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/xtensa/$(DEPDIR)/sysv.Plo@am__quote@ @@ -1289,8 +1301,10 @@ clean-libtool: -rm -rf src/avr32/.libs src/avr32/_libs -rm -rf src/bfin/.libs src/bfin/_libs -rm -rf src/cris/.libs src/cris/_libs + -rm -rf src/csky/.libs src/csky/_libs -rm -rf src/frv/.libs src/frv/_libs -rm -rf src/ia64/.libs src/ia64/_libs + -rm -rf src/kvx/.libs src/kvx/_libs -rm -rf src/m32r/.libs src/m32r/_libs -rm -rf src/m68k/.libs src/m68k/_libs -rm -rf src/m88k/.libs src/m88k/_libs @@ -1633,10 +1647,14 @@ distclean-generic: -rm -f src/bfin/$(am__dirstamp) -rm -f src/cris/$(DEPDIR)/$(am__dirstamp) -rm -f src/cris/$(am__dirstamp) + -rm -f src/csky/$(DEPDIR)/$(am__dirstamp) + -rm -f src/csky/$(am__dirstamp) -rm -f src/frv/$(DEPDIR)/$(am__dirstamp) -rm -f src/frv/$(am__dirstamp) -rm -f src/ia64/$(DEPDIR)/$(am__dirstamp) -rm -f src/ia64/$(am__dirstamp) + -rm -f src/kvx/$(DEPDIR)/$(am__dirstamp) + -rm -f src/kvx/$(am__dirstamp) -rm -f src/m32r/$(DEPDIR)/$(am__dirstamp) -rm -f src/m32r/$(am__dirstamp) -rm -f src/m68k/$(DEPDIR)/$(am__dirstamp) @@ -1691,7 +1709,7 @@ clean-am: clean-aminfo clean-generic clean-libtool clean-local \ distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arc/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/m88k/$(DEPDIR) src/metag/$(DEPDIR) src/microblaze/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/nios2/$(DEPDIR) src/or1k/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/riscv/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/vax/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR) + -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arc/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/csky/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/kvx/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/m88k/$(DEPDIR) src/metag/$(DEPDIR) src/microblaze/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/nios2/$(DEPDIR) src/or1k/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/riscv/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/vax/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-local distclean-tags @@ -1830,7 +1848,7 @@ installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arc/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/m88k/$(DEPDIR) src/metag/$(DEPDIR) src/microblaze/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/nios2/$(DEPDIR) src/or1k/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/riscv/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/vax/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR) + -rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arc/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/csky/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/kvx/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/m88k/$(DEPDIR) src/metag/$(DEPDIR) src/microblaze/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/nios2/$(DEPDIR) src/or1k/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/riscv/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/vax/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-aminfo \ maintainer-clean-generic maintainer-clean-local \ @@ -1894,15 +1912,16 @@ doc/libffi.info: $(STAMP_BUILD_INFO) stamp-build-info: doc/libffi.texi $(srcdir)/doc/version.texi doc/$(am__dirstamp) $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)/doc -o doc/libffi.info $(srcdir)/doc/libffi.texi @touch $@ -@LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@libffi.map-sun : libffi.map $(top_srcdir)/../contrib/make_sunver.pl \ -@LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@ $(libffi_la_OBJECTS) $(libffi_la_LIBADD) -@LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@ perl $(top_srcdir)/../contrib/make_sunver.pl libffi.map \ -@LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@ `echo $(libffi_la_OBJECTS) $(libffi_la_LIBADD) | \ -@LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@ sed 's,\([^/ ]*\)\.l\([ao]\),.libs/\1.\2,g'` \ -@LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@ > $@ || (rm -f $@ ; exit 1) +@LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBFFI_BUILD_VERSIONED_SHLIB_TRUE@libffi.map-sun : libffi.map $(top_srcdir)/../contrib/make_sunver.pl \ +@LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBFFI_BUILD_VERSIONED_SHLIB_TRUE@ $(libffi_la_OBJECTS) $(libffi_la_LIBADD) +@LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBFFI_BUILD_VERSIONED_SHLIB_TRUE@ perl $(top_srcdir)/../contrib/make_sunver.pl libffi.map \ +@LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBFFI_BUILD_VERSIONED_SHLIB_TRUE@ `echo $(libffi_la_OBJECTS) $(libffi_la_LIBADD) | \ +@LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBFFI_BUILD_VERSIONED_SHLIB_TRUE@ sed 's,\([^/ ]*\)\.l\([ao]\),.libs/\1.\2,g'` \ +@LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBFFI_BUILD_VERSIONED_SHLIB_TRUE@ > $@ || (rm -f $@ ; exit 1) libffi.map: $(top_srcdir)/libffi.map.in - $(COMPILE) -D$(TARGET) -E -x assembler-with-cpp -o $@ $< + $(COMPILE) -D$(TARGET) -DGENERATE_LIBFFI_MAP \ + -E -x assembler-with-cpp -o $@ $(top_srcdir)/libffi.map.in # Multilib support. Automake should provide these on its own. all-recursive: all-multi diff --git a/libffi/README b/libffi/README deleted file mode 100644 index c072101..0000000 --- a/libffi/README +++ /dev/null @@ -1,450 +0,0 @@ -Status -====== - -libffi-4?? was released on TBD. Check the libffi web -page for updates: <URL:http://sourceware.org/libffi/>. - - -What is libffi? -=============== - -Compilers for high level languages generate code that follow certain -conventions. These conventions are necessary, in part, for separate -compilation to work. One such convention is the "calling -convention". The "calling convention" is essentially a set of -assumptions made by the compiler about where function arguments will -be found on entry to a function. A "calling convention" also specifies -where the return value for a function is found. - -Some programs may not know at the time of compilation what arguments -are to be passed to a function. For instance, an interpreter may be -told at run-time about the number and types of arguments used to call -a given function. Libffi can be used in such programs to provide a -bridge from the interpreter program to compiled code. - -The libffi library provides a portable, high level programming -interface to various calling conventions. This allows a programmer to -call any function specified by a call interface description at run -time. - -FFI stands for Foreign Function Interface. A foreign function -interface is the popular name for the interface that allows code -written in one language to call code written in another language. The -libffi library really only provides the lowest, machine dependent -layer of a fully featured foreign function interface. A layer must -exist above libffi that handles type conversions for values passed -between the two languages. - - -Supported Platforms -=================== - -Libffi has been ported to many different platforms. -For specific configuration details and testing status, please -refer to the wiki page here: - - http://www.moxielogic.org/wiki/index.php?title=Libffi_3.2 - -At the time of release, the following basic configurations have been -tested: - -|-----------------+------------------+-------------------------| -| Architecture | Operating System | Compiler | -|-----------------+------------------+-------------------------| -| AArch64 (ARM64) | iOS | Clang | -| AArch64 | Linux | GCC | -| Alpha | Linux | GCC | -| Alpha | Tru64 | GCC | -| ARC | Linux | GCC | -| ARM | Linux | GCC | -| ARM | iOS | GCC | -| AVR32 | Linux | GCC | -| Blackfin | uClinux | GCC | -| HPPA | HPUX | GCC | -| IA-64 | Linux | GCC | -| M68K | FreeMiNT | GCC | -| M68K | Linux | GCC | -| M68K | RTEMS | GCC | -| M88K | OpenBSD/mvme88k | GCC | -| Meta | Linux | GCC | -| MicroBlaze | Linux | GCC | -| MIPS | IRIX | GCC | -| MIPS | Linux | GCC | -| MIPS | RTEMS | GCC | -| MIPS64 | Linux | GCC | -| Moxie | Bare metal | GCC | -| Nios II | Linux | GCC | -| OpenRISC | Linux | GCC | -| PowerPC 32-bit | AIX | IBM XL C | -| PowerPC 64-bit | AIX | IBM XL C | -| PowerPC | AMIGA | GCC | -| PowerPC | Linux | GCC | -| PowerPC | Mac OSX | GCC | -| PowerPC | FreeBSD | GCC | -| PowerPC 64-bit | FreeBSD | GCC | -| PowerPC 64-bit | Linux ELFv1 | GCC | -| PowerPC 64-bit | Linux ELFv2 | GCC | -| S390 | Linux | GCC | -| S390X | Linux | GCC | -| SPARC | Linux | GCC | -| SPARC | Solaris | GCC | -| SPARC | Solaris | Oracle Solaris Studio C | -| SPARC64 | Linux | GCC | -| SPARC64 | FreeBSD | GCC | -| SPARC64 | Solaris | Oracle Solaris Studio C | -| TILE-Gx/TILEPro | Linux | GCC | -| VAX | OpenBSD/vax | GCC | -| X86 | FreeBSD | GCC | -| X86 | GNU HURD | GCC | -| X86 | Interix | GCC | -| X86 | kFreeBSD | GCC | -| X86 | Linux | GCC | -| X86 | Mac OSX | GCC | -| X86 | OpenBSD | GCC | -| X86 | OS/2 | GCC | -| X86 | Solaris | GCC | -| X86 | Solaris | Oracle Solaris Studio C | -| X86 | Windows/Cygwin | GCC | -| X86 | Windows/MingW | GCC | -| X86-64 | FreeBSD | GCC | -| X86-64 | Linux | GCC | -| X86-64 | Linux/x32 | GCC | -| X86-64 | OpenBSD | GCC | -| X86-64 | Solaris | Oracle Solaris Studio C | -| X86-64 | Windows/Cygwin | GCC | -| X86-64 | Windows/MingW | GCC | -| Xtensa | Linux | GCC | -|-----------------+------------------+-------------------------| - -Please send additional platform test results to -libffi-discuss@sourceware.org and feel free to update the wiki page -above. - -Installing libffi -================= - -First you must configure the distribution for your particular -system. Go to the directory you wish to build libffi in and run the -"configure" program found in the root directory of the libffi source -distribution. - -If you're building libffi directly from version control, configure won't -exist yet; run ./autogen.sh first. - -You may want to tell configure where to install the libffi library and -header files. To do that, use the --prefix configure switch. Libffi -will install under /usr/local by default. - -If you want to enable extra run-time debugging checks use the the ---enable-debug configure switch. This is useful when your program dies -mysteriously while using libffi. - -Another useful configure switch is --enable-purify-safety. Using this -will add some extra code which will suppress certain warnings when you -are using Purify with libffi. Only use this switch when using -Purify, as it will slow down the library. - -It's also possible to build libffi on Windows platforms with -Microsoft's Visual C++ compiler. In this case, use the msvcc.sh -wrapper script during configuration like so: - -path/to/configure CC=path/to/msvcc.sh CXX=path/to/msvcc.sh LD=link CPP="cl -nologo -EP" - -For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64" and -CXX="path/to/msvcc.sh -m64". You may also need to specify --build -appropriately. - -It is also possible to build libffi on Windows platforms with the LLVM -project's clang-cl compiler, like below: - -path/to/configure CC="path/to/msvcc.sh -clang-cl" CXX="path/to/msvcc.sh -clang-cl" LD=link CPP="clang-cl -EP" - -When building with MSVC under a MingW environment, you may need to -remove the line in configure that sets 'fix_srcfile_path' to a 'cygpath' -command. ('cygpath' is not present in MingW, and is not required when -using MingW-style paths.) - -For iOS builds, the 'libffi.xcodeproj' Xcode project is available. - -Configure has many other options. Use "configure --help" to see them all. - -Once configure has finished, type "make". Note that you must be using -GNU make. You can ftp GNU make from ftp.gnu.org:/pub/gnu/make . - -To ensure that libffi is working as advertised, type "make check". -This will require that you have DejaGNU installed. - -To install the library and header files, type "make install". - - -History -======= - -See the git log for details at http://github.com/atgreen/libffi. - -4.0 TBD - New API in support of GO closures. - -3.2.1 Nov-12-14 - Build fix for non-iOS AArch64 targets. - -3.2 Nov-11-14 - Add C99 Complex Type support (currently only supported on - s390). - Add support for PASCAL and REGISTER calling conventions on x86 - Windows/Linux. - Add OpenRISC and Cygwin-64 support. - Bug fixes. - -3.1 May-19-14 - Add AArch64 (ARM64) iOS support. - Add Nios II support. - Add m88k and DEC VAX support. - Add support for stdcall, thiscall, and fastcall on non-Windows - 32-bit x86 targets such as Linux. - Various Android, MIPS N32, x86, FreeBSD and UltraSPARC IIi - fixes. - Make the testsuite more robust: eliminate several spurious - failures, and respect the $CC and $CXX environment variables. - Archive off the manually maintained ChangeLog in favor of git - log. - -3.0.13 Mar-17-13 - Add Meta support. - Add missing Moxie bits. - Fix stack alignment bug on 32-bit x86. - Build fix for m68000 targets. - Build fix for soft-float Power targets. - Fix the install dir location for some platforms when building - with GCC (OS X, Solaris). - Fix Cygwin regression. - -3.0.12 Feb-11-13 - Add Moxie support. - Add AArch64 support. - Add Blackfin support. - Add TILE-Gx/TILEPro support. - Add MicroBlaze support. - Add Xtensa support. - Add support for PaX enabled kernels with MPROTECT. - Add support for native vendor compilers on - Solaris and AIX. - Work around LLVM/GCC interoperability issue on x86_64. - -3.0.11 Apr-11-12 - Lots of build fixes. - Add support for variadic functions (ffi_prep_cif_var). - Add Linux/x32 support. - Add thiscall, fastcall and MSVC cdecl support on Windows. - Add Amiga and newer MacOS support. - Add m68k FreeMiNT support. - Integration with iOS' xcode build tools. - Fix Octeon and MC68881 support. - Fix code pessimizations. - -3.0.10 Aug-23-11 - Add support for Apple's iOS. - Add support for ARM VFP ABI. - Add RTEMS support for MIPS and M68K. - Fix instruction cache clearing problems on - ARM and SPARC. - Fix the N64 build on mips-sgi-irix6.5. - Enable builds with Microsoft's compiler. - Enable x86 builds with Oracle's Solaris compiler. - Fix support for calling code compiled with Oracle's Sparc - Solaris compiler. - Testsuite fixes for Tru64 Unix. - Additional platform support. - -3.0.9 Dec-31-09 - Add AVR32 and win64 ports. Add ARM softfp support. - Many fixes for AIX, Solaris, HP-UX, *BSD. - Several PowerPC and x86-64 bug fixes. - Build DLL for windows. - -3.0.8 Dec-19-08 - Add *BSD, BeOS, and PA-Linux support. - -3.0.7 Nov-11-08 - Fix for ppc FreeBSD. - (thanks to Andreas Tobler) - -3.0.6 Jul-17-08 - Fix for closures on sh. - Mark the sh/sh64 stack as non-executable. - (both thanks to Kaz Kojima) - -3.0.5 Apr-3-08 - Fix libffi.pc file. - Fix #define ARM for IcedTea users. - Fix x86 closure bug. - -3.0.4 Feb-24-08 - Fix x86 OpenBSD configury. - -3.0.3 Feb-22-08 - Enable x86 OpenBSD thanks to Thomas Heller, and - x86-64 FreeBSD thanks to Björn König and Andreas Tobler. - Clean up test instruction in README. - -3.0.2 Feb-21-08 - Improved x86 FreeBSD support. - Thanks to Björn König. - -3.0.1 Feb-15-08 - Fix instruction cache flushing bug on MIPS. - Thanks to David Daney. - -3.0.0 Feb-15-08 - Many changes, mostly thanks to the GCC project. - Cygnus Solutions is now Red Hat. - - [10 years go by...] - -1.20 Oct-5-98 - Raffaele Sena produces ARM port. - -1.19 Oct-5-98 - Fixed x86 long double and long long return support. - m68k bug fixes from Andreas Schwab. - Patch for DU assembler compatibility for the Alpha from Richard - Henderson. - -1.18 Apr-17-98 - Bug fixes and MIPS configuration changes. - -1.17 Feb-24-98 - Bug fixes and m68k port from Andreas Schwab. PowerPC port from - Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes. - -1.16 Feb-11-98 - Richard Henderson produces Alpha port. - -1.15 Dec-4-97 - Fixed an n32 ABI bug. New libtool, auto* support. - -1.14 May-13-97 - libtool is now used to generate shared and static libraries. - Fixed a minor portability problem reported by Russ McManus - <mcmanr@eq.gs.com>. - -1.13 Dec-2-96 - Added --enable-purify-safety to keep Purify from complaining - about certain low level code. - Sparc fix for calling functions with < 6 args. - Linux x86 a.out fix. - -1.12 Nov-22-96 - Added missing ffi_type_void, needed for supporting void return - types. Fixed test case for non MIPS machines. Cygnus Support - is now Cygnus Solutions. - -1.11 Oct-30-96 - Added notes about GNU make. - -1.10 Oct-29-96 - Added configuration fix for non GNU compilers. - -1.09 Oct-29-96 - Added --enable-debug configure switch. Clean-ups based on LCLint - feedback. ffi_mips.h is always installed. Many configuration - fixes. Fixed ffitest.c for sparc builds. - -1.08 Oct-15-96 - Fixed n32 problem. Many clean-ups. - -1.07 Oct-14-96 - Gordon Irlam rewrites v8.S again. Bug fixes. - -1.06 Oct-14-96 - Gordon Irlam improved the sparc port. - -1.05 Oct-14-96 - Interface changes based on feedback. - -1.04 Oct-11-96 - Sparc port complete (modulo struct passing bug). - -1.03 Oct-10-96 - Passing struct args, and returning struct values works for - all architectures/calling conventions. Expanded tests. - -1.02 Oct-9-96 - Added SGI n32 support. Fixed bugs in both o32 and Linux support. - Added "make test". - -1.01 Oct-8-96 - Fixed float passing bug in mips version. Restructured some - of the code. Builds cleanly with SGI tools. - -1.00 Oct-7-96 - First release. No public announcement. - - -Authors & Credits -================= - -libffi was originally written by Anthony Green <green@moxielogic.com>. - -The developers of the GNU Compiler Collection project have made -innumerable valuable contributions. See the ChangeLog file for -details. - -Some of the ideas behind libffi were inspired by Gianni Mariani's free -gencall library for Silicon Graphics machines. - -The closure mechanism was designed and implemented by Kresten Krab -Thorup. - -Major processor architecture ports were contributed by the following -developers: - -aarch64 Marcus Shawcroft, James Greenhalgh -alpha Richard Henderson -arm Raffaele Sena -blackfin Alexandre Keunecke I. de Mendonca -cris Simon Posnjak, Hans-Peter Nilsson -frv Anthony Green -ia64 Hans Boehm -m32r Kazuhiro Inaoka -m68k Andreas Schwab -m88k Miod Vallat -microblaze Nathan Rossi -mips Anthony Green, Casey Marshall -mips64 David Daney -moxie Anthony Green -nios ii Sandra Loosemore -openrisc Sebastian Macke -pa Randolph Chung, Dave Anglin, Andreas Tobler -powerpc Geoffrey Keating, Andreas Tobler, - David Edelsohn, John Hornkvist -powerpc64 Jakub Jelinek -s390 Gerhard Tonn, Ulrich Weigand -sh Kaz Kojima -sh64 Kaz Kojima -sparc Anthony Green, Gordon Irlam -tile-gx/tilepro Walter Lee -vax Miod Vallat -x86 Anthony Green, Jon Beniston -x86-64 Bo Thorsen -xtensa Chris Zankel - -Jesper Skov and Andrew Haley both did more than their fair share of -stepping through the code and tracking down bugs. - -Thanks also to Tom Tromey for bug fixes, documentation and -configuration help. - -Thanks to Jim Blandy, who provided some useful feedback on the libffi -interface. - -Andreas Tobler has done a tremendous amount of work on the testsuite. - -Alex Oliva solved the executable page problem for SElinux. - -The list above is almost certainly incomplete and inaccurate. I'm -happy to make corrections or additions upon request. - -If you have a problem, or have found a bug, please send a note to the -author at green@moxielogic.com, or the project mailing list at -libffi-discuss@sourceware.org. diff --git a/libffi/README.md b/libffi/README.md new file mode 100644 index 0000000..b95bd74 --- /dev/null +++ b/libffi/README.md @@ -0,0 +1,495 @@ +Status +====== + +libffi-3.4.1 was released on June 28, 2021. Check the libffi web page +for updates: <URL:http://sourceware.org/libffi/>. + + +What is libffi? +=============== + +Compilers for high level languages generate code that follow certain +conventions. These conventions are necessary, in part, for separate +compilation to work. One such convention is the "calling +convention". The "calling convention" is essentially a set of +assumptions made by the compiler about where function arguments will +be found on entry to a function. A "calling convention" also specifies +where the return value for a function is found. + +Some programs may not know at the time of compilation what arguments +are to be passed to a function. For instance, an interpreter may be +told at run-time about the number and types of arguments used to call +a given function. Libffi can be used in such programs to provide a +bridge from the interpreter program to compiled code. + +The libffi library provides a portable, high level programming +interface to various calling conventions. This allows a programmer to +call any function specified by a call interface description at run +time. + +FFI stands for Foreign Function Interface. A foreign function +interface is the popular name for the interface that allows code +written in one language to call code written in another language. The +libffi library really only provides the lowest, machine dependent +layer of a fully featured foreign function interface. A layer must +exist above libffi that handles type conversions for values passed +between the two languages. + + +Supported Platforms +=================== + +Libffi has been ported to many different platforms. + +At the time of release, the following basic configurations have been +tested: + +| Architecture | Operating System | Compiler | +| --------------- | ---------------- | ----------------------- | +| AArch64 (ARM64) | iOS | Clang | +| AArch64 | Linux | GCC | +| AArch64 | Windows | MSVC | +| Alpha | Linux | GCC | +| Alpha | Tru64 | GCC | +| ARC | Linux | GCC | +| ARM | Linux | GCC | +| ARM | iOS | GCC | +| ARM | Windows | MSVC | +| AVR32 | Linux | GCC | +| Blackfin | uClinux | GCC | +| CSKY | Linux | GCC | +| HPPA | HPUX | GCC | +| KVX | Linux | GCC | +| IA-64 | Linux | GCC | +| M68K | FreeMiNT | GCC | +| M68K | Linux | GCC | +| M68K | RTEMS | GCC | +| M88K | OpenBSD/mvme88k | GCC | +| Meta | Linux | GCC | +| MicroBlaze | Linux | GCC | +| MIPS | IRIX | GCC | +| MIPS | Linux | GCC | +| MIPS | RTEMS | GCC | +| MIPS64 | Linux | GCC | +| Moxie | Bare metal | GCC | +| Nios II | Linux | GCC | +| OpenRISC | Linux | GCC | +| PowerPC 32-bit | AIX | IBM XL C | +| PowerPC 64-bit | AIX | IBM XL C | +| PowerPC | AMIGA | GCC | +| PowerPC | Linux | GCC | +| PowerPC | Mac OSX | GCC | +| PowerPC | FreeBSD | GCC | +| PowerPC 64-bit | FreeBSD | GCC | +| PowerPC 64-bit | Linux ELFv1 | GCC | +| PowerPC 64-bit | Linux ELFv2 | GCC | +| RISC-V 32-bit | Linux | GCC | +| RISC-V 64-bit | Linux | GCC | +| S390 | Linux | GCC | +| S390X | Linux | GCC | +| SPARC | Linux | GCC | +| SPARC | Solaris | GCC | +| SPARC | Solaris | Oracle Solaris Studio C | +| SPARC64 | Linux | GCC | +| SPARC64 | FreeBSD | GCC | +| SPARC64 | Solaris | Oracle Solaris Studio C | +| TILE-Gx/TILEPro | Linux | GCC | +| VAX | OpenBSD/vax | GCC | +| X86 | FreeBSD | GCC | +| X86 | GNU HURD | GCC | +| X86 | Interix | GCC | +| X86 | kFreeBSD | GCC | +| X86 | Linux | GCC | +| X86 | OpenBSD | GCC | +| X86 | OS/2 | GCC | +| X86 | Solaris | GCC | +| X86 | Solaris | Oracle Solaris Studio C | +| X86 | Windows/Cygwin | GCC | +| X86 | Windows/MingW | GCC | +| X86-64 | FreeBSD | GCC | +| X86-64 | Linux | GCC | +| X86-64 | Linux/x32 | GCC | +| X86-64 | OpenBSD | GCC | +| X86-64 | Solaris | Oracle Solaris Studio C | +| X86-64 | Windows/Cygwin | GCC | +| X86-64 | Windows/MingW | GCC | +| X86-64 | Mac OSX | GCC | +| Xtensa | Linux | GCC | + +Please send additional platform test results to +libffi-discuss@sourceware.org. + +Installing libffi +================= + +First you must configure the distribution for your particular +system. Go to the directory you wish to build libffi in and run the +"configure" program found in the root directory of the libffi source +distribution. Note that building libffi requires a C99 compatible +compiler. + +If you're building libffi directly from git hosted sources, configure +won't exist yet; run ./autogen.sh first. This will require that you +install autoconf, automake and libtool. + +You may want to tell configure where to install the libffi library and +header files. To do that, use the ``--prefix`` configure switch. Libffi +will install under /usr/local by default. + +If you want to enable extra run-time debugging checks use the the +``--enable-debug`` configure switch. This is useful when your program dies +mysteriously while using libffi. + +Another useful configure switch is ``--enable-purify-safety``. Using this +will add some extra code which will suppress certain warnings when you +are using Purify with libffi. Only use this switch when using +Purify, as it will slow down the library. + +If you don't want to build documentation, use the ``--disable-docs`` +configure switch. + +It's also possible to build libffi on Windows platforms with +Microsoft's Visual C++ compiler. In this case, use the msvcc.sh +wrapper script during configuration like so: + + path/to/configure CC=path/to/msvcc.sh CXX=path/to/msvcc.sh LD=link CPP="cl -nologo -EP" CPPFLAGS="-DFFI_BUILDING_DLL" + +For 64-bit Windows builds, use ``CC="path/to/msvcc.sh -m64"`` and +``CXX="path/to/msvcc.sh -m64"``. You may also need to specify +``--build`` appropriately. + +It is also possible to build libffi on Windows platforms with the LLVM +project's clang-cl compiler, like below: + + path/to/configure CC="path/to/msvcc.sh -clang-cl" CXX="path/to/msvcc.sh -clang-cl" LD=link CPP="clang-cl -EP" + +When building with MSVC under a MingW environment, you may need to +remove the line in configure that sets 'fix_srcfile_path' to a 'cygpath' +command. ('cygpath' is not present in MingW, and is not required when +using MingW-style paths.) + +To build static library for ARM64 with MSVC using visual studio solution, msvc_build folder have + aarch64/Ffi_staticLib.sln + required header files in aarch64/aarch64_include/ + + +SPARC Solaris builds require the use of the GNU assembler and linker. +Point ``AS`` and ``LD`` environment variables at those tool prior to +configuration. + +For iOS builds, the ``libffi.xcodeproj`` Xcode project is available. + +Configure has many other options. Use ``configure --help`` to see them all. + +Once configure has finished, type "make". Note that you must be using +GNU make. You can ftp GNU make from ftp.gnu.org:/pub/gnu/make . + +To ensure that libffi is working as advertised, type "make check". +This will require that you have DejaGNU installed. + +To install the library and header files, type ``make install``. + + +History +======= + +See the git log for details at http://github.com/libffi/libffi. + + 3.4.2 Jun-28-21 + Add static trampoline support for Linux on x86_64 and ARM64. + Add support for Alibaba's CSKY architecture. + Add support for Kalray's KVX architecture. + Add support for Intel Control-flow Enforcement Technology (CET). + Add support for ARM Pointer Authentication (PA). + Fix 32-bit PPC regression. + Fix MIPS soft-float problem. + Enable tmpdir override with the $LIBFFI_TMPDIR environment variable. + Enable compatibility with MSVC runtime stack checking. + Reject float and small integer argument in ffi_prep_cif_var(). + Callers must promote these types themselves. + + 3.3 Nov-23-19 + Add RISC-V support. + New API in support of GO closures. + Add IEEE754 binary128 long double support for 64-bit Power + Default to Microsoft's 64 bit long double ABI with Visual C++. + GNU compiler uses 80 bits (128 in memory) FFI_GNUW64 ABI. + Add Windows on ARM64 (WOA) support. + Add Windows 32-bit ARM support. + Raw java (gcj) API deprecated. + Add pre-built PDF documentation to source distribution. + Many new test cases and bug fixes. + + 3.2.1 Nov-12-14 + Build fix for non-iOS AArch64 targets. + + 3.2 Nov-11-14 + Add C99 Complex Type support (currently only supported on + s390). + Add support for PASCAL and REGISTER calling conventions on x86 + Windows/Linux. + Add OpenRISC and Cygwin-64 support. + Bug fixes. + + 3.1 May-19-14 + Add AArch64 (ARM64) iOS support. + Add Nios II support. + Add m88k and DEC VAX support. + Add support for stdcall, thiscall, and fastcall on non-Windows + 32-bit x86 targets such as Linux. + Various Android, MIPS N32, x86, FreeBSD and UltraSPARC IIi + fixes. + Make the testsuite more robust: eliminate several spurious + failures, and respect the $CC and $CXX environment variables. + Archive off the manually maintained ChangeLog in favor of git + log. + + 3.0.13 Mar-17-13 + Add Meta support. + Add missing Moxie bits. + Fix stack alignment bug on 32-bit x86. + Build fix for m68000 targets. + Build fix for soft-float Power targets. + Fix the install dir location for some platforms when building + with GCC (OS X, Solaris). + Fix Cygwin regression. + + 3.0.12 Feb-11-13 + Add Moxie support. + Add AArch64 support. + Add Blackfin support. + Add TILE-Gx/TILEPro support. + Add MicroBlaze support. + Add Xtensa support. + Add support for PaX enabled kernels with MPROTECT. + Add support for native vendor compilers on + Solaris and AIX. + Work around LLVM/GCC interoperability issue on x86_64. + + 3.0.11 Apr-11-12 + Lots of build fixes. + Add support for variadic functions (ffi_prep_cif_var). + Add Linux/x32 support. + Add thiscall, fastcall and MSVC cdecl support on Windows. + Add Amiga and newer MacOS support. + Add m68k FreeMiNT support. + Integration with iOS' xcode build tools. + Fix Octeon and MC68881 support. + Fix code pessimizations. + + 3.0.10 Aug-23-11 + Add support for Apple's iOS. + Add support for ARM VFP ABI. + Add RTEMS support for MIPS and M68K. + Fix instruction cache clearing problems on + ARM and SPARC. + Fix the N64 build on mips-sgi-irix6.5. + Enable builds with Microsoft's compiler. + Enable x86 builds with Oracle's Solaris compiler. + Fix support for calling code compiled with Oracle's Sparc + Solaris compiler. + Testsuite fixes for Tru64 Unix. + Additional platform support. + + 3.0.9 Dec-31-09 + Add AVR32 and win64 ports. Add ARM softfp support. + Many fixes for AIX, Solaris, HP-UX, *BSD. + Several PowerPC and x86-64 bug fixes. + Build DLL for windows. + + 3.0.8 Dec-19-08 + Add *BSD, BeOS, and PA-Linux support. + + 3.0.7 Nov-11-08 + Fix for ppc FreeBSD. + (thanks to Andreas Tobler) + + 3.0.6 Jul-17-08 + Fix for closures on sh. + Mark the sh/sh64 stack as non-executable. + (both thanks to Kaz Kojima) + + 3.0.5 Apr-3-08 + Fix libffi.pc file. + Fix #define ARM for IcedTea users. + Fix x86 closure bug. + + 3.0.4 Feb-24-08 + Fix x86 OpenBSD configury. + + 3.0.3 Feb-22-08 + Enable x86 OpenBSD thanks to Thomas Heller, and + x86-64 FreeBSD thanks to Björn König and Andreas Tobler. + Clean up test instruction in README. + + 3.0.2 Feb-21-08 + Improved x86 FreeBSD support. + Thanks to Björn König. + + 3.0.1 Feb-15-08 + Fix instruction cache flushing bug on MIPS. + Thanks to David Daney. + + 3.0.0 Feb-15-08 + Many changes, mostly thanks to the GCC project. + Cygnus Solutions is now Red Hat. + + [10 years go by...] + + 1.20 Oct-5-98 + Raffaele Sena produces ARM port. + + 1.19 Oct-5-98 + Fixed x86 long double and long long return support. + m68k bug fixes from Andreas Schwab. + Patch for DU assembler compatibility for the Alpha from Richard + Henderson. + + 1.18 Apr-17-98 + Bug fixes and MIPS configuration changes. + + 1.17 Feb-24-98 + Bug fixes and m68k port from Andreas Schwab. PowerPC port from + Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes. + + 1.16 Feb-11-98 + Richard Henderson produces Alpha port. + + 1.15 Dec-4-97 + Fixed an n32 ABI bug. New libtool, auto* support. + + 1.14 May-13-97 + libtool is now used to generate shared and static libraries. + Fixed a minor portability problem reported by Russ McManus + <mcmanr@eq.gs.com>. + + 1.13 Dec-2-96 + Added --enable-purify-safety to keep Purify from complaining + about certain low level code. + Sparc fix for calling functions with < 6 args. + Linux x86 a.out fix. + + 1.12 Nov-22-96 + Added missing ffi_type_void, needed for supporting void return + types. Fixed test case for non MIPS machines. Cygnus Support + is now Cygnus Solutions. + + 1.11 Oct-30-96 + Added notes about GNU make. + + 1.10 Oct-29-96 + Added configuration fix for non GNU compilers. + + 1.09 Oct-29-96 + Added --enable-debug configure switch. Clean-ups based on LCLint + feedback. ffi_mips.h is always installed. Many configuration + fixes. Fixed ffitest.c for sparc builds. + + 1.08 Oct-15-96 + Fixed n32 problem. Many clean-ups. + + 1.07 Oct-14-96 + Gordon Irlam rewrites v8.S again. Bug fixes. + + 1.06 Oct-14-96 + Gordon Irlam improved the sparc port. + + 1.05 Oct-14-96 + Interface changes based on feedback. + + 1.04 Oct-11-96 + Sparc port complete (modulo struct passing bug). + + 1.03 Oct-10-96 + Passing struct args, and returning struct values works for + all architectures/calling conventions. Expanded tests. + + 1.02 Oct-9-96 + Added SGI n32 support. Fixed bugs in both o32 and Linux support. + Added "make test". + + 1.01 Oct-8-96 + Fixed float passing bug in mips version. Restructured some + of the code. Builds cleanly with SGI tools. + + 1.00 Oct-7-96 + First release. No public announcement. + +Authors & Credits +================= + +libffi was originally written by Anthony Green <green@moxielogic.com>. + +The developers of the GNU Compiler Collection project have made +innumerable valuable contributions. See the ChangeLog file for +details. + +Some of the ideas behind libffi were inspired by Gianni Mariani's free +gencall library for Silicon Graphics machines. + +The closure mechanism was designed and implemented by Kresten Krab +Thorup. + +Major processor architecture ports were contributed by the following +developers: + + aarch64 Marcus Shawcroft, James Greenhalgh + alpha Richard Henderson + arc Hackers at Synopsis + arm Raffaele Sena + avr32 Bradley Smith + blackfin Alexandre Keunecke I. de Mendonca + cris Simon Posnjak, Hans-Peter Nilsson + csky Ma Jun, Zhang Wenmeng + frv Anthony Green + ia64 Hans Boehm + kvx Yann Sionneau + m32r Kazuhiro Inaoka + m68k Andreas Schwab + m88k Miod Vallat + metag Hackers at Imagination Technologies + microblaze Nathan Rossi + mips Anthony Green, Casey Marshall + mips64 David Daney + moxie Anthony Green + nios ii Sandra Loosemore + openrisc Sebastian Macke + pa Randolph Chung, Dave Anglin, Andreas Tobler + powerpc Geoffrey Keating, Andreas Tobler, + David Edelsohn, John Hornkvist + powerpc64 Jakub Jelinek + riscv Michael Knyszek, Andrew Waterman, Stef O'Rear + s390 Gerhard Tonn, Ulrich Weigand + sh Kaz Kojima + sh64 Kaz Kojima + sparc Anthony Green, Gordon Irlam + tile-gx/tilepro Walter Lee + vax Miod Vallat + x86 Anthony Green, Jon Beniston + x86-64 Bo Thorsen + xtensa Chris Zankel + +Jesper Skov and Andrew Haley both did more than their fair share of +stepping through the code and tracking down bugs. + +Thanks also to Tom Tromey for bug fixes, documentation and +configuration help. + +Thanks to Jim Blandy, who provided some useful feedback on the libffi +interface. + +Andreas Tobler has done a tremendous amount of work on the testsuite. + +Alex Oliva solved the executable page problem for SElinux. + +The list above is almost certainly incomplete and inaccurate. I'm +happy to make corrections or additions upon request. + +If you have a problem, or have found a bug, please file an issue on +our issue tracker at https://github.com/libffi/libffi/issues. + +The author can be reached at green@moxielogic.com. + +To subscribe/unsubscribe to our mailing lists, visit: +https://sourceware.org/mailman/listinfo/libffi-announce +https://sourceware.org/mailman/listinfo/libffi-discuss diff --git a/libffi/acinclude.m4 b/libffi/acinclude.m4 index b09be64..1a70efb 100644 --- a/libffi/acinclude.m4 +++ b/libffi/acinclude.m4 @@ -95,14 +95,14 @@ dnl ---------------------------------------------------------------------- dnl This whole bit snagged from libstdc++-v3, via libatomic. dnl -dnl LIBAT_ENABLE +dnl LIBFFI_ENABLE dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING) dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, permit a|b|c) dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, SHELL-CODE-HANDLER) dnl dnl See docs/html/17_intro/configury.html#enable for documentation. dnl -m4_define([LIBAT_ENABLE],[dnl +m4_define([LIBFFI_ENABLE],[dnl m4_define([_g_switch],[--enable-$1])dnl m4_define([_g_help],[AC_HELP_STRING(_g_switch$3,[$4 @<:@default=$2@:>@])])dnl AC_ARG_ENABLE($1,_g_help, @@ -146,7 +146,7 @@ dnl dnl The last will be a single integer, e.g., version 1.23.45.0.67.89 will dnl set libat_gnu_ld_version to 12345. Zeros cause problems. dnl -AC_DEFUN([LIBAT_CHECK_LINKER_FEATURES], [ +AC_DEFUN([LIBFFI_CHECK_LINKER_FEATURES], [ # If we're not using GNU ld, then there's no point in even trying these # tests. Check for that first. We should have already tested for gld # by now (in libtool), but require it now just to be safe... @@ -178,7 +178,7 @@ AC_DEFUN([LIBAT_CHECK_LINKER_FEATURES], [ fi changequote(,) ldver=`$LD --version 2>/dev/null | - sed -e 's/[. ][0-9]\{8\}$//;s/.* \([^ ]\{1,\}\)$/\1/; q'` + sed -e 's/GNU gold /GNU ld /;s/GNU ld version /GNU ld /;s/GNU ld ([^)]*) /GNU ld /;s/GNU ld \([0-9.][0-9.]*\).*/\1/; q'` changequote([,]) libat_gnu_ld_version=`echo $ldver | \ $AWK -F. '{ if (NF<3) [$]3=0; print ([$]1*100+[$]2)*100+[$]3 }'` @@ -248,7 +248,7 @@ dnl dnl The last will be a single integer, e.g., version 1.23.45.0.67.89 will dnl set libat_gnu_ld_version to 12345. Zeros cause problems. dnl -AC_DEFUN([LIBAT_CHECK_LINKER_FEATURES], [ +AC_DEFUN([LIBFFI_CHECK_LINKER_FEATURES], [ # If we're not using GNU ld, then there's no point in even trying these # tests. Check for that first. We should have already tested for gld # by now (in libtool), but require it now just to be safe... @@ -278,9 +278,13 @@ AC_DEFUN([LIBAT_CHECK_LINKER_FEATURES], [ if $LD --version 2>/dev/null | grep 'GNU gold'> /dev/null 2>&1; then libat_ld_is_gold=yes fi + libat_ld_is_lld=no + if $LD --version 2>/dev/null | grep 'LLD '> /dev/null 2>&1; then + libat_ld_is_lld=yes + fi changequote(,) ldver=`$LD --version 2>/dev/null | - sed -e 's/[. ][0-9]\{8\}$//;s/.* \([^ ]\{1,\}\)$/\1/; q'` + sed -e 's/GNU gold /GNU ld /;s/GNU ld version /GNU ld /;s/GNU ld ([^)]*) /GNU ld /;s/GNU ld \([0-9.][0-9.]*\).*/\1/; q'` changequote([,]) libat_gnu_ld_version=`echo $ldver | \ $AWK -F. '{ if (NF<3) [$]3=0; print ([$]1*100+[$]2)*100+[$]3 }'` @@ -341,20 +345,20 @@ dnl --enable-symvers=style adds a version script to the linker call when dnl creating the shared library. The choice of version script is dnl controlled by 'style'. dnl --disable-symvers does not. -dnl + Usage: LIBAT_ENABLE_SYMVERS[(DEFAULT)] +dnl + Usage: LIBFFI_ENABLE_SYMVERS[(DEFAULT)] dnl Where DEFAULT is either 'yes' or 'no'. Passing `yes' tries to dnl choose a default style based on linker characteristics. Passing dnl 'no' disables versioning. dnl -AC_DEFUN([LIBAT_ENABLE_SYMVERS], [ +AC_DEFUN([LIBFFI_ENABLE_SYMVERS], [ -LIBAT_ENABLE(symvers,yes,[=STYLE], +LIBFFI_ENABLE(symvers,yes,[=STYLE], [enables symbol versioning of the shared library], [permit yes|no|gnu*|sun]) -# If we never went through the LIBAT_CHECK_LINKER_FEATURES macro, then we +# If we never went through the LIBFFI_CHECK_LINKER_FEATURES macro, then we # don't know enough about $LD to do tricks... -AC_REQUIRE([LIBAT_CHECK_LINKER_FEATURES]) +AC_REQUIRE([LIBFFI_CHECK_LINKER_FEATURES]) # Turn a 'yes' into a suitable default. if test x$enable_symvers = xyes ; then @@ -420,7 +424,7 @@ changequote([,])dnl fi # For GNU ld, we need at least this version. The format is described in -# LIBAT_CHECK_LINKER_FEATURES above. +# LIBFFI_CHECK_LINKER_FEATURES above. libat_min_gnu_ld_version=21400 # XXXXXXXXXXX libat_gnu_ld_version=21390 @@ -432,6 +436,8 @@ if test $enable_symvers != no && test $libat_shared_libgcc = yes; then enable_symvers=gnu elif test $libat_ld_is_gold = yes ; then enable_symvers=gnu + elif test $libat_ld_is_lld = yes ; then + enable_symvers=gnu else # The right tools, the right setup, but too old. Fallbacks? AC_MSG_WARN(=== Linker version $libat_gnu_ld_version is too old for) @@ -462,12 +468,12 @@ if test $enable_symvers != no && test $libat_shared_libgcc = yes; then fi fi if test $enable_symvers = gnu; then - AC_DEFINE(LIBAT_GNU_SYMBOL_VERSIONING, 1, + AC_DEFINE(LIBFFI_GNU_SYMBOL_VERSIONING, 1, [Define to 1 if GNU symbol versioning is used for libatomic.]) fi -AM_CONDITIONAL(LIBAT_BUILD_VERSIONED_SHLIB, test $enable_symvers != no) -AM_CONDITIONAL(LIBAT_BUILD_VERSIONED_SHLIB_GNU, test $enable_symvers = gnu) -AM_CONDITIONAL(LIBAT_BUILD_VERSIONED_SHLIB_SUN, test $enable_symvers = sun) +AM_CONDITIONAL(LIBFFI_BUILD_VERSIONED_SHLIB, test $enable_symvers != no) +AM_CONDITIONAL(LIBFFI_BUILD_VERSIONED_SHLIB_GNU, test $enable_symvers = gnu) +AM_CONDITIONAL(LIBFFI_BUILD_VERSIONED_SHLIB_SUN, test $enable_symvers = sun) AC_MSG_NOTICE(versioning on shared library symbols is $enable_symvers) ]) diff --git a/libffi/autogen.sh b/libffi/autogen.sh new file mode 100755 index 0000000..95bfc38 --- /dev/null +++ b/libffi/autogen.sh @@ -0,0 +1,11 @@ +#!/bin/sh +#exec autoreconf -v -i + +rm -rf autom4te.cache +aclocal -I .. -I ../config +autoheader -I .. -I ../config +autoconf +automake --foreign --add-missing --copy Makefile +automake --foreign include/Makefile +automake --foreign man/Makefile +automake --foreign testsuite/Makefile diff --git a/libffi/configure b/libffi/configure index 8d52ec4..4bababb 100755 --- a/libffi/configure +++ b/libffi/configure @@ -1,8 +1,8 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for libffi 3.99999. +# Generated by GNU Autoconf 2.69 for libffi 3.4.2. # -# Report bugs to <http://github.com/atgreen/libffi/issues>. +# Report bugs to <http://github.com/libffi/libffi/issues>. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -275,7 +275,7 @@ fi $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and -$0: http://github.com/atgreen/libffi/issues about your +$0: http://github.com/libffi/libffi/issues about your $0: system, including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." @@ -590,9 +590,9 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='libffi' PACKAGE_TARNAME='libffi' -PACKAGE_VERSION='3.99999' -PACKAGE_STRING='libffi 3.99999' -PACKAGE_BUGREPORT='http://github.com/atgreen/libffi/issues' +PACKAGE_VERSION='3.4.2' +PACKAGE_STRING='libffi 3.4.2' +PACKAGE_BUGREPORT='http://github.com/libffi/libffi/issues' PACKAGE_URL='' # Factoring default headers for most tests. @@ -636,12 +636,12 @@ am__EXEEXT_TRUE LTLIBOBJS LIBOBJS get_gcc_base_ver -LIBAT_BUILD_VERSIONED_SHLIB_SUN_FALSE -LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE -LIBAT_BUILD_VERSIONED_SHLIB_GNU_FALSE -LIBAT_BUILD_VERSIONED_SHLIB_GNU_TRUE -LIBAT_BUILD_VERSIONED_SHLIB_FALSE -LIBAT_BUILD_VERSIONED_SHLIB_TRUE +LIBFFI_BUILD_VERSIONED_SHLIB_SUN_FALSE +LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE +LIBFFI_BUILD_VERSIONED_SHLIB_GNU_FALSE +LIBFFI_BUILD_VERSIONED_SHLIB_GNU_TRUE +LIBFFI_BUILD_VERSIONED_SHLIB_FALSE +LIBFFI_BUILD_VERSIONED_SHLIB_TRUE OPT_LDFLAGS SECTION_LDFLAGS toolexeclibdir @@ -651,6 +651,8 @@ FFI_DEBUG_TRUE TARGET_OBJ TARGETDIR TARGET +BUILD_DOCS_FALSE +BUILD_DOCS_TRUE FFI_EXEC_TRAMPOLINE_TABLE FFI_EXEC_TRAMPOLINE_TABLE_FALSE FFI_EXEC_TRAMPOLINE_TABLE_TRUE @@ -664,6 +666,7 @@ TESTSUBDIR_TRUE MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE +READELF CXXCPP CPP OTOOL64 @@ -714,8 +717,6 @@ CFLAGS CC GENINSRC_FALSE GENINSRC_TRUE -BUILD_INFO_FALSE -BUILD_INFO_TRUE AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V @@ -812,6 +813,7 @@ enable_pax_emutramp enable_debug enable_structs enable_raw_api +enable_exec_static_tramp enable_purify_safety with_toolexeclibdir enable_symvers @@ -1365,7 +1367,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libffi 3.99999 to adapt to many kinds of systems. +\`configure' configures libffi 3.4.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1436,7 +1438,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libffi 3.99999:";; + short | recursive ) echo "Configuration of libffi 3.4.2:";; esac cat <<\_ACEOF @@ -1467,6 +1469,7 @@ Optional Features: --enable-debug debugging mode --disable-structs omit code for struct support --disable-raw-api make the raw api unavailable + --enable-exec-static-tramp enable use of static exec trampolines --enable-purify-safety purify-safe mode --enable-symvers=STYLE enables symbol versioning of the shared library [default=yes] @@ -1501,7 +1504,7 @@ Some influential environment variables: Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. -Report bugs to <http://github.com/atgreen/libffi/issues>. +Report bugs to <http://github.com/libffi/libffi/issues>. _ACEOF ac_status=$? fi @@ -1564,7 +1567,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libffi configure 3.99999 +libffi configure 3.4.2 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2213,9 +2216,9 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( $as_echo "## ------------------------------------------------------ ## -## Report this to http://github.com/atgreen/libffi/issues ## -## ------------------------------------------------------ ##" +( $as_echo "## ----------------------------------------------------- ## +## Report this to http://github.com/libffi/libffi/issues ## +## ----------------------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac @@ -2291,7 +2294,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libffi $as_me 3.99999, which was +It was created by libffi $as_me 3.4.2, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3311,7 +3314,7 @@ fi # Define the identity of the package. PACKAGE='libffi' - VERSION='3.99999' + VERSION='3.4.2' cat >>confdefs.h <<_ACEOF @@ -3405,81 +3408,6 @@ END fi -# See if makeinfo has been installed and is modern enough -# that we can use it. - - # Extract the first word of "makeinfo", so it can be a program name with args. -set dummy makeinfo; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_MAKEINFO+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$MAKEINFO"; then - ac_cv_prog_MAKEINFO="$MAKEINFO" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_MAKEINFO="makeinfo" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -MAKEINFO=$ac_cv_prog_MAKEINFO -if test -n "$MAKEINFO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKEINFO" >&5 -$as_echo "$MAKEINFO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - if test -n "$MAKEINFO"; then - # Found it, now check the version. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for modern makeinfo" >&5 -$as_echo_n "checking for modern makeinfo... " >&6; } -if ${gcc_cv_prog_makeinfo_modern+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_prog_version=`eval $MAKEINFO --version 2>&1 | - sed -n 's/^.*GNU texinfo.* \([0-9][0-9.]*\).*$/\1/p'` - - case $ac_prog_version in - '') gcc_cv_prog_makeinfo_modern=no;; - 4.[4-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*) gcc_cv_prog_makeinfo_modern=yes;; - *) gcc_cv_prog_makeinfo_modern=no;; - esac - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_prog_makeinfo_modern" >&5 -$as_echo "$gcc_cv_prog_makeinfo_modern" >&6; } - else - gcc_cv_prog_makeinfo_modern=no - fi - if test $gcc_cv_prog_makeinfo_modern = no; then - MAKEINFO="${CONFIG_SHELL-/bin/sh} $ac_aux_dir/missing makeinfo" - fi - - if test $gcc_cv_prog_makeinfo_modern = "yes"; then - BUILD_INFO_TRUE= - BUILD_INFO_FALSE='#' -else - BUILD_INFO_TRUE='#' - BUILD_INFO_FALSE= -fi - - # We would like our source tree to be readonly. However when releases or # pre-releases are generated, the flex/bison generated files as well as the # various formats of manuals need to be included along with the rest of the @@ -11553,7 +11481,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11566 "configure" +#line 11484 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11659,7 +11587,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11672 "configure" +#line 11590 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -14398,16 +14326,6 @@ freebsd* | dragonfly*) esac ;; -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - haiku*) version_type=linux need_lib_prefix=no @@ -14529,7 +14447,7 @@ linux*oldld* | linux*aout* | linux*coff*) # project, but have not yet been accepted: they are GCC-local changes # for the time being. (See # https://lists.gnu.org/archive/html/libtool-patches/2018-05/msg00000.html) -linux* | k*bsd*-gnu | kopensolaris*-gnu | uclinuxfdpiceabi) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu* | uclinuxfdpiceabi) version_type=linux need_lib_prefix=no need_version=no @@ -14918,6 +14836,99 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}readelf", so it can be a program name with args. +set dummy ${ac_tool_prefix}readelf; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_READELF+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$READELF"; then + ac_cv_prog_READELF="$READELF" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_READELF="${ac_tool_prefix}readelf" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +READELF=$ac_cv_prog_READELF +if test -n "$READELF"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READELF" >&5 +$as_echo "$READELF" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_READELF"; then + ac_ct_READELF=$READELF + # Extract the first word of "readelf", so it can be a program name with args. +set dummy readelf; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_READELF+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_READELF"; then + ac_cv_prog_ac_ct_READELF="$ac_ct_READELF" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_READELF="readelf" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_READELF=$ac_cv_prog_ac_ct_READELF +if test -n "$ac_ct_READELF"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_READELF" >&5 +$as_echo "$ac_ct_READELF" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_READELF" = x; then + READELF="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + READELF=$ac_ct_READELF + fi +else + READELF="$ac_cv_prog_READELF" +fi + + # Test for 64-bit build. # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects @@ -14956,6 +14967,7 @@ _ACEOF cat > local.exp <<EOF set CC_FOR_TARGET "$CC" set CXX_FOR_TARGET "$CXX" +set compiler_vendor "$ax_cv_c_compiler_vendor" EOF @@ -14982,6 +14994,30 @@ fi +for ac_header in sys/memfd.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "sys/memfd.h" "ac_cv_header_sys_memfd_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_memfd_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_MEMFD_H 1 +_ACEOF + +fi + +done + +for ac_func in memfd_create +do : + ac_fn_c_check_func "$LINENO" "memfd_create" "ac_cv_func_memfd_create" +if test "x$ac_cv_func_memfd_create" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_MEMFD_CREATE 1 +_ACEOF + +fi +done + + for ac_header in sys/mman.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" @@ -14994,7 +15030,7 @@ fi done -for ac_func in mmap mkostemp +for ac_func in mmap mkostemp mkstemp do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -15965,6 +16001,50 @@ $as_echo "#define HAVE_AS_S390_ZARCH 1" >>confdefs.h ;; esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports pointer authentication" >&5 +$as_echo_n "checking whether compiler supports pointer authentication... " >&6; } +if ${libffi_cv_as_ptrauth+:} false; then : + $as_echo_n "(cached) " >&6 +else + + libffi_cv_as_ptrauth=unknown + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifdef __clang__ +# if __has_feature(ptrauth_calls) +# define HAVE_PTRAUTH 1 +# endif +#endif + +#ifndef HAVE_PTRAUTH +# error Pointer authentication not supported +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libffi_cv_as_ptrauth=yes +else + libffi_cv_as_ptrauth=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_ptrauth" >&5 +$as_echo "$libffi_cv_as_ptrauth" >&6; } +if test "x$libffi_cv_as_ptrauth" = xyes; then + +$as_echo "#define HAVE_PTRAUTH 1" >>confdefs.h + +fi + # On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. # Check whether --enable-pax_emutramp was given. if test "${enable_pax_emutramp+set}" = set; then : @@ -15978,13 +16058,13 @@ fi FFI_EXEC_TRAMPOLINE_TABLE=0 case "$target" in - *arm*-apple-darwin* | aarch64-apple-darwin*) + *arm*-apple-* | aarch64-apple-*) FFI_EXEC_TRAMPOLINE_TABLE=1 $as_echo "#define FFI_EXEC_TRAMPOLINE_TABLE 1" >>confdefs.h ;; - *-apple-darwin1* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris*) + *-apple-* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris* | *-linux-android*) $as_echo "#define FFI_MMAP_EXEC_WRIT 1" >>confdefs.h @@ -16046,17 +16126,11 @@ if ${libffi_cv_ro_eh_frame+:} false; then : $as_echo_n "(cached) " >&6 else - libffi_cv_ro_eh_frame=no + libffi_cv_ro_eh_frame=yes echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c - if $CC $CFLAGS -c -fpic -fexceptions -o conftest.o conftest.c > /dev/null 2>&1; then - objdump -h conftest.o > conftest.dump 2>&1 - libffi_eh_frame_line=`grep -n eh_frame conftest.dump | cut -d: -f 1` - if test "x$libffi_eh_frame_line" != "x"; then - libffi_test_line=`expr $libffi_eh_frame_line + 1`p - sed -n $libffi_test_line conftest.dump > conftest.line - if grep READONLY conftest.line > /dev/null; then - libffi_cv_ro_eh_frame=yes - fi + if $CC $CFLAGS -c -fpic -fexceptions -fno-lto -o conftest.o conftest.c > /dev/null 2>&1; then + if $READELF -WS conftest.o | grep -q -n 'eh_frame .* WA'; then + libffi_cv_ro_eh_frame=no fi fi rm -f conftest.* @@ -16091,7 +16165,7 @@ else ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then - if grep '\.hidden.*foo' conftest.s >/dev/null; then + if egrep '(\.hidden|\.private_extern).*foo' conftest.s >/dev/null; then libffi_cv_hidden_visibility_attribute=yes fi fi @@ -16107,6 +16181,81 @@ $as_echo "#define HAVE_HIDDEN_VISIBILITY_ATTRIBUTE 1" >>confdefs.h fi fi +# See if makeinfo has been installed and is modern enough +# that we can use it. + + # Extract the first word of "makeinfo", so it can be a program name with args. +set dummy makeinfo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MAKEINFO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MAKEINFO"; then + ac_cv_prog_MAKEINFO="$MAKEINFO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MAKEINFO="makeinfo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MAKEINFO=$ac_cv_prog_MAKEINFO +if test -n "$MAKEINFO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKEINFO" >&5 +$as_echo "$MAKEINFO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test -n "$MAKEINFO"; then + # Found it, now check the version. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for modern makeinfo" >&5 +$as_echo_n "checking for modern makeinfo... " >&6; } +if ${gcc_cv_prog_makeinfo_modern+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_prog_version=`eval $MAKEINFO --version 2>&1 | + sed -n 's/^.*GNU texinfo.* \([0-9][0-9.]*\).*$/\1/p'` + + case $ac_prog_version in + '') gcc_cv_prog_makeinfo_modern=no;; + 4.[4-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*) gcc_cv_prog_makeinfo_modern=yes;; + *) gcc_cv_prog_makeinfo_modern=no;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_prog_makeinfo_modern" >&5 +$as_echo "$gcc_cv_prog_makeinfo_modern" >&6; } + else + gcc_cv_prog_makeinfo_modern=no + fi + if test $gcc_cv_prog_makeinfo_modern = no; then + MAKEINFO="${CONFIG_SHELL-/bin/sh} $ac_aux_dir/missing makeinfo" + fi + + if test $gcc_cv_prog_makeinfo_modern = "yes"; then + BUILD_DOCS_TRUE= + BUILD_DOCS_FALSE='#' +else + BUILD_DOCS_TRUE='#' + BUILD_DOCS_FALSE= +fi + + @@ -16168,6 +16317,24 @@ $as_echo "#define FFI_NO_RAW_API 1" >>confdefs.h fi +# Check whether --enable-exec-static-tramp was given. +if test "${enable_exec_static_tramp+set}" = set; then : + enableval=$enable_exec_static_tramp; +fi + + +if test "$enable_exec_static_tramp" = yes; then +case "$target" in + *-cygwin*) + ;; + *arm*-*-linux-* | aarch64*-*-linux-* | i*86-*-linux-* | x86_64-*-linux-*) + +$as_echo "#define FFI_EXEC_STATIC_TRAMP 1" >>confdefs.h + + ;; +esac +fi + # Check whether --enable-purify-safety was given. if test "${enable_purify_safety+set}" = set; then : enableval=$enable_purify_safety; if test "$enable_purify_safety" = "yes"; then @@ -16364,9 +16531,13 @@ with_gnu_ld=$lt_cv_prog_gnu_ld if $LD --version 2>/dev/null | grep 'GNU gold'> /dev/null 2>&1; then libat_ld_is_gold=yes fi + libat_ld_is_lld=no + if $LD --version 2>/dev/null | grep 'LLD '> /dev/null 2>&1; then + libat_ld_is_lld=yes + fi ldver=`$LD --version 2>/dev/null | - sed -e 's/[. ][0-9]\{8\}$//;s/.* \([^ ]\{1,\}\)$/\1/; q'` + sed -e 's/GNU gold /GNU ld /;s/GNU ld version /GNU ld /;s/GNU ld ([^)]*) /GNU ld /;s/GNU ld \([0-9.][0-9.]*\).*/\1/; q'` libat_gnu_ld_version=`echo $ldver | \ $AWK -F. '{ if (NF<3) $3=0; print ($1*100+$2)*100+$3 }'` @@ -16450,7 +16621,7 @@ fi -# If we never went through the LIBAT_CHECK_LINKER_FEATURES macro, then we +# If we never went through the LIBFFI_CHECK_LINKER_FEATURES macro, then we # don't know enough about $LD to do tricks... @@ -16553,7 +16724,7 @@ $as_echo "$libat_shared_libgcc" >&6; } fi # For GNU ld, we need at least this version. The format is described in -# LIBAT_CHECK_LINKER_FEATURES above. +# LIBFFI_CHECK_LINKER_FEATURES above. libat_min_gnu_ld_version=21400 # XXXXXXXXXXX libat_gnu_ld_version=21390 @@ -16565,6 +16736,8 @@ if test $enable_symvers != no && test $libat_shared_libgcc = yes; then enable_symvers=gnu elif test $libat_ld_is_gold = yes ; then enable_symvers=gnu + elif test $libat_ld_is_lld = yes ; then + enable_symvers=gnu else # The right tools, the right setup, but too old. Fallbacks? { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === Linker version $libat_gnu_ld_version is too old for" >&5 @@ -16604,32 +16777,32 @@ $as_echo "$as_me: WARNING: === Symbol versioning will be disabled." >&2;} fi if test $enable_symvers = gnu; then -$as_echo "#define LIBAT_GNU_SYMBOL_VERSIONING 1" >>confdefs.h +$as_echo "#define LIBFFI_GNU_SYMBOL_VERSIONING 1" >>confdefs.h fi if test $enable_symvers != no; then - LIBAT_BUILD_VERSIONED_SHLIB_TRUE= - LIBAT_BUILD_VERSIONED_SHLIB_FALSE='#' + LIBFFI_BUILD_VERSIONED_SHLIB_TRUE= + LIBFFI_BUILD_VERSIONED_SHLIB_FALSE='#' else - LIBAT_BUILD_VERSIONED_SHLIB_TRUE='#' - LIBAT_BUILD_VERSIONED_SHLIB_FALSE= + LIBFFI_BUILD_VERSIONED_SHLIB_TRUE='#' + LIBFFI_BUILD_VERSIONED_SHLIB_FALSE= fi if test $enable_symvers = gnu; then - LIBAT_BUILD_VERSIONED_SHLIB_GNU_TRUE= - LIBAT_BUILD_VERSIONED_SHLIB_GNU_FALSE='#' + LIBFFI_BUILD_VERSIONED_SHLIB_GNU_TRUE= + LIBFFI_BUILD_VERSIONED_SHLIB_GNU_FALSE='#' else - LIBAT_BUILD_VERSIONED_SHLIB_GNU_TRUE='#' - LIBAT_BUILD_VERSIONED_SHLIB_GNU_FALSE= + LIBFFI_BUILD_VERSIONED_SHLIB_GNU_TRUE='#' + LIBFFI_BUILD_VERSIONED_SHLIB_GNU_FALSE= fi if test $enable_symvers = sun; then - LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE= - LIBAT_BUILD_VERSIONED_SHLIB_SUN_FALSE='#' + LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE= + LIBFFI_BUILD_VERSIONED_SHLIB_SUN_FALSE='#' else - LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE='#' - LIBAT_BUILD_VERSIONED_SHLIB_SUN_FALSE= + LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE='#' + LIBFFI_BUILD_VERSIONED_SHLIB_SUN_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: versioning on shared library symbols is $enable_symvers" >&5 @@ -16656,10 +16829,10 @@ ac_config_commands="$ac_config_commands include" ac_config_commands="$ac_config_commands src" -ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETDIR/ffitarget.h" +ac_config_files="$ac_config_files include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc" -ac_config_files="$ac_config_files include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc" +ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETDIR/ffitarget.h" cat >confcache <<\_ACEOF @@ -16787,10 +16960,6 @@ else am__EXEEXT_FALSE= fi -if test -z "${BUILD_INFO_TRUE}" && test -z "${BUILD_INFO_FALSE}"; then - as_fn_error $? "conditional \"BUILD_INFO\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${GENINSRC_TRUE}" && test -z "${GENINSRC_FALSE}"; then as_fn_error $? "conditional \"GENINSRC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -16824,6 +16993,10 @@ if test -z "${FFI_EXEC_TRAMPOLINE_TABLE_TRUE}" && test -z "${FFI_EXEC_TRAMPOLINE as_fn_error $? "conditional \"FFI_EXEC_TRAMPOLINE_TABLE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${BUILD_DOCS_TRUE}" && test -z "${BUILD_DOCS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_DOCS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${FFI_DEBUG_TRUE}" && test -z "${FFI_DEBUG_FALSE}"; then as_fn_error $? "conditional \"FFI_DEBUG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -16832,16 +17005,16 @@ if test -z "${FFI_DEBUG_TRUE}" && test -z "${FFI_DEBUG_FALSE}"; then as_fn_error $? "conditional \"FFI_DEBUG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${LIBAT_BUILD_VERSIONED_SHLIB_TRUE}" && test -z "${LIBAT_BUILD_VERSIONED_SHLIB_FALSE}"; then - as_fn_error $? "conditional \"LIBAT_BUILD_VERSIONED_SHLIB\" was never defined. +if test -z "${LIBFFI_BUILD_VERSIONED_SHLIB_TRUE}" && test -z "${LIBFFI_BUILD_VERSIONED_SHLIB_FALSE}"; then + as_fn_error $? "conditional \"LIBFFI_BUILD_VERSIONED_SHLIB\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${LIBAT_BUILD_VERSIONED_SHLIB_GNU_TRUE}" && test -z "${LIBAT_BUILD_VERSIONED_SHLIB_GNU_FALSE}"; then - as_fn_error $? "conditional \"LIBAT_BUILD_VERSIONED_SHLIB_GNU\" was never defined. +if test -z "${LIBFFI_BUILD_VERSIONED_SHLIB_GNU_TRUE}" && test -z "${LIBFFI_BUILD_VERSIONED_SHLIB_GNU_FALSE}"; then + as_fn_error $? "conditional \"LIBFFI_BUILD_VERSIONED_SHLIB_GNU\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE}" && test -z "${LIBAT_BUILD_VERSIONED_SHLIB_SUN_FALSE}"; then - as_fn_error $? "conditional \"LIBAT_BUILD_VERSIONED_SHLIB_SUN\" was never defined. +if test -z "${LIBFFI_BUILD_VERSIONED_SHLIB_SUN_TRUE}" && test -z "${LIBFFI_BUILD_VERSIONED_SHLIB_SUN_FALSE}"; then + as_fn_error $? "conditional \"LIBFFI_BUILD_VERSIONED_SHLIB_SUN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi @@ -17241,7 +17414,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libffi $as_me 3.99999, which was +This file was extended by libffi $as_me 3.4.2, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -17305,13 +17478,13 @@ $config_links Configuration commands: $config_commands -Report bugs to <http://github.com/atgreen/libffi/issues>." +Report bugs to <http://github.com/libffi/libffi/issues>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -libffi config.status 3.99999 +libffi config.status 3.4.2 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -17821,13 +17994,13 @@ do "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "include") CONFIG_COMMANDS="$CONFIG_COMMANDS include" ;; "src") CONFIG_COMMANDS="$CONFIG_COMMANDS src" ;; - "include/ffitarget.h") CONFIG_LINKS="$CONFIG_LINKS include/ffitarget.h:src/$TARGETDIR/ffitarget.h" ;; "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; "include/ffi.h") CONFIG_FILES="$CONFIG_FILES include/ffi.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;; "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; "libffi.pc") CONFIG_FILES="$CONFIG_FILES libffi.pc" ;; + "include/ffitarget.h") CONFIG_LINKS="$CONFIG_LINKS include/ffitarget.h:src/$TARGETDIR/ffitarget.h" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac diff --git a/libffi/configure.ac b/libffi/configure.ac index 0bf4af4..bff5a1e 100644 --- a/libffi/configure.ac +++ b/libffi/configure.ac @@ -1,7 +1,8 @@ dnl Process this with autoconf to create configure +AC_PREREQ(2.68) -AC_INIT([libffi], [3.99999], [http://github.com/atgreen/libffi/issues]) +AC_INIT([libffi], [3.4.2], [http://github.com/libffi/libffi/issues]) AC_CONFIG_HEADERS([fficonfig.h]) AM_ENABLE_MULTILIB(, ..) @@ -11,13 +12,6 @@ target_alias=${target_alias-$host_alias} AM_INIT_AUTOMAKE([no-dist]) -# See if makeinfo has been installed and is modern enough -# that we can use it. -ACX_CHECK_PROG_VER([MAKEINFO], [makeinfo], [--version], - [GNU texinfo.* \([0-9][0-9.]*\)], - [4.[4-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*]) -AM_CONDITIONAL(BUILD_INFO, test $gcc_cv_prog_makeinfo_modern = "yes") - # We would like our source tree to be readonly. However when releases or # pre-releases are generated, the flex/bison generated files as well as the # various formats of manuals need to be included along with the rest of the @@ -58,18 +52,24 @@ AM_PROG_AS AM_PROG_CC_C_O AC_PROG_LIBTOOL +AC_CHECK_TOOL(READELF, readelf) + # Test for 64-bit build. AC_CHECK_SIZEOF([size_t]) cat > local.exp <<EOF set CC_FOR_TARGET "$CC" set CXX_FOR_TARGET "$CXX" +set compiler_vendor "$ax_cv_c_compiler_vendor" EOF AM_MAINTAINER_MODE +AC_CHECK_HEADERS(sys/memfd.h) +AC_CHECK_FUNCS([memfd_create]) + AC_CHECK_HEADERS(sys/mman.h) -AC_CHECK_FUNCS([mmap mkostemp]) +AC_CHECK_FUNCS([mmap mkostemp mkstemp]) AC_FUNC_MMAP_BLACKLIST dnl The -no-testsuite modules omit the test subdir. @@ -181,6 +181,28 @@ case "$TARGET" in ;; esac +AC_CACHE_CHECK([whether compiler supports pointer authentication], + libffi_cv_as_ptrauth, [ + libffi_cv_as_ptrauth=unknown + AC_TRY_COMPILE(,[ +#ifdef __clang__ +# if __has_feature(ptrauth_calls) +# define HAVE_PTRAUTH 1 +# endif +#endif + +#ifndef HAVE_PTRAUTH +# error Pointer authentication not supported +#endif + ], + [libffi_cv_as_ptrauth=yes], + [libffi_cv_as_ptrauth=no]) +]) +if test "x$libffi_cv_as_ptrauth" = xyes; then + AC_DEFINE(HAVE_PTRAUTH, 1, + [Define if your compiler supports pointer authentication.]) +fi + # On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. AC_ARG_ENABLE(pax_emutramp, [ --enable-pax_emutramp enable pax emulated trampolines, for we can't use PROT_EXEC], @@ -191,13 +213,13 @@ AC_ARG_ENABLE(pax_emutramp, FFI_EXEC_TRAMPOLINE_TABLE=0 case "$target" in - *arm*-apple-darwin* | aarch64-apple-darwin*) + *arm*-apple-* | aarch64-apple-*) FFI_EXEC_TRAMPOLINE_TABLE=1 AC_DEFINE(FFI_EXEC_TRAMPOLINE_TABLE, 1, [Cannot use PROT_EXEC on this target, so, we revert to alternative means]) ;; - *-apple-darwin1* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris*) + *-apple-* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris* | *-linux-android*) AC_DEFINE(FFI_MMAP_EXEC_WRIT, 1, [Cannot use malloc on this target, so, we revert to alternative means]) @@ -240,17 +262,11 @@ fi if test "x$GCC" = "xyes"; then AC_CACHE_CHECK([whether .eh_frame section should be read-only], libffi_cv_ro_eh_frame, [ - libffi_cv_ro_eh_frame=no + libffi_cv_ro_eh_frame=yes echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c - if $CC $CFLAGS -c -fpic -fexceptions -o conftest.o conftest.c > /dev/null 2>&1; then - objdump -h conftest.o > conftest.dump 2>&1 - libffi_eh_frame_line=`grep -n eh_frame conftest.dump | cut -d: -f 1` - if test "x$libffi_eh_frame_line" != "x"; then - libffi_test_line=`expr $libffi_eh_frame_line + 1`p - sed -n $libffi_test_line conftest.dump > conftest.line - if grep READONLY conftest.line > /dev/null; then - libffi_cv_ro_eh_frame=yes - fi + if $CC $CFLAGS -c -fpic -fexceptions -fno-lto -o conftest.o conftest.c > /dev/null 2>&1; then + if $READELF -WS conftest.o | grep -q -n 'eh_frame .* WA'; then + libffi_cv_ro_eh_frame=no fi fi rm -f conftest.* @@ -270,7 +286,7 @@ if test "x$GCC" = "xyes"; then echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1 ; }' > conftest.c libffi_cv_hidden_visibility_attribute=no if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then - if grep '\.hidden.*foo' conftest.s >/dev/null; then + if egrep '(\.hidden|\.private_extern).*foo' conftest.s >/dev/null; then libffi_cv_hidden_visibility_attribute=yes fi fi @@ -282,10 +298,21 @@ if test "x$GCC" = "xyes"; then fi fi +# See if makeinfo has been installed and is modern enough +# that we can use it. +ACX_CHECK_PROG_VER([MAKEINFO], [makeinfo], [--version], + [GNU texinfo.* \([0-9][0-9.]*\)], + [4.[4-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*]) +AM_CONDITIONAL(BUILD_DOCS, test $gcc_cv_prog_makeinfo_modern = "yes") + AH_BOTTOM([ #ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE #ifdef LIBFFI_ASM +#ifdef __APPLE__ +#define FFI_HIDDEN(name) .private_extern name +#else #define FFI_HIDDEN(name) .hidden name +#endif #else #define FFI_HIDDEN __attribute__ ((visibility ("hidden"))) #endif @@ -331,6 +358,20 @@ AC_ARG_ENABLE(raw-api, AC_DEFINE(FFI_NO_RAW_API, 1, [Define this if you do not want support for the raw API.]) fi) +AC_ARG_ENABLE(exec-static-tramp, +[ --enable-exec-static-tramp enable use of static exec trampolines]) + +if test "$enable_exec_static_tramp" = yes; then +case "$target" in + *-cygwin*) + ;; + *arm*-*-linux-* | aarch64*-*-linux-* | i*86-*-linux-* | x86_64-*-linux-*) + AC_DEFINE(FFI_EXEC_STATIC_TRAMP, 1, + [Define this if you want statically defined trampolines]) + ;; +esac +fi + AC_ARG_ENABLE(purify-safety, [ --enable-purify-safety purify-safe mode], if test "$enable_purify_safety" = "yes"; then @@ -369,7 +410,7 @@ else fi # Check linker support. -LIBAT_ENABLE_SYMVERS +LIBFFI_ENABLE_SYMVERS # Determine what GCC version number to use in filesystem paths. GCC_BASE_VER @@ -380,8 +421,8 @@ test -d src || mkdir src test -d src/$TARGETDIR || mkdir src/$TARGETDIR ], [TARGETDIR="$TARGETDIR"]) -AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h) - AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc) +AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h) + AC_OUTPUT diff --git a/libffi/configure.host b/libffi/configure.host index 7248acb..2682671 100644 --- a/libffi/configure.host +++ b/libffi/configure.host @@ -6,6 +6,13 @@ # THIS TABLE IS SORTED. KEEP IT THAT WAY. # Most of the time we can define all the variables all at once... case "${host}" in + aarch64*-*-cygwin* | aarch64*-*-mingw* | aarch64*-*-win* ) + TARGET=ARM_WIN64; TARGETDIR=aarch64 + if test "${ax_cv_c_compiler_vendor}" = "microsoft"; then + MSVC=1 + fi + ;; + aarch64*-*-*) TARGET=AARCH64; TARGETDIR=aarch64 SOURCES="ffi.c sysv.S" @@ -23,6 +30,13 @@ case "${host}" in SOURCES="ffi.c arcompact.S" ;; + arm*-*-cygwin* | arm*-*-mingw* | arm*-*-win* ) + TARGET=ARM_WIN32; TARGETDIR=arm + if test "${ax_cv_c_compiler_vendor}" = "microsoft"; then + MSVC=1 + fi + ;; + arm*-*-*) TARGET=ARM; TARGETDIR=arm SOURCES="ffi.c sysv.S" @@ -43,6 +57,11 @@ case "${host}" in SOURCES="ffi.c sysv.S" ;; + csky-*-*) + TARGET=CSKY; TARGETDIR=csky + SOURCES="ffi.c sysv.S" + ;; + frv-*-*) TARGET=FRV; TARGETDIR=frv SOURCES="ffi.c eabi.S" @@ -64,14 +83,17 @@ case "${host}" in TARGET=X86_FREEBSD; TARGETDIR=x86 ;; - i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix* \ - | x86_64-*-cygwin* | x86_64-*-mingw*) + i?86-*-cygwin* | i?86-*-mingw* | i?86-*-win* | i?86-*-os2* | i?86-*-interix* \ + | x86_64-*-cygwin* | x86_64-*-mingw* | x86_64-*-win* ) TARGETDIR=x86 if test $ac_cv_sizeof_size_t = 4; then TARGET=X86_WIN32 else TARGET=X86_WIN64 fi + if test "${ax_cv_c_compiler_vendor}" = "microsoft"; then + MSVC=1 + fi # All mingw/cygwin/win32 builds require -no-undefined for sharedlib. # We must also check with_cross_host to decide if this is a native # or cross-build and select where to install dlls appropriately. @@ -83,12 +105,12 @@ case "${host}" in fi ;; - i?86-*-darwin* | x86_64-*-darwin*) + i?86-*-darwin* | x86_64-*-darwin* | i?86-*-ios | x86_64-*-ios) TARGETDIR=x86 if test $ac_cv_sizeof_size_t = 4; then TARGET=X86_DARWIN else - TARGET=X86_64_DARWIN + TARGET=X86_64 fi ;; @@ -97,11 +119,12 @@ case "${host}" in if test $ac_cv_sizeof_size_t = 4; then echo 'int foo (void) { return __x86_64__; }' > conftest.c if $CC $CFLAGS -Werror -S conftest.c -o conftest.s > /dev/null 2>&1; then - TARGET=X86_64; + TARGET_X32=yes + TARGET=X86_64 else TARGET=X86; - fi - rm -f conftest.* + fi + rm -f conftest.* else TARGET=X86_64; fi @@ -112,6 +135,11 @@ case "${host}" in SOURCES="ffi.c unix.S" ;; + kvx-*-*) + TARGET=KVX; TARGETDIR=kvx + SOURCES="ffi.c sysv.S" + ;; + m32r*-*-*) TARGET=M32R; TARGETDIR=m32r SOURCES="ffi.c sysv.S" @@ -145,7 +173,7 @@ case "${host}" in mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*) TARGET=MIPS; TARGETDIR=mips ;; - mips*-*linux* | mips*-*-openbsd*) + mips*-*linux* | mips*-*-openbsd* | mips*-*-freebsd*) # Support 128-bit long double for NewABI. HAVE_LONG_DOUBLE='defined(__mips64)' TARGET=MIPS; TARGETDIR=mips @@ -156,7 +184,7 @@ case "${host}" in SOURCES="ffi.c sysv.S" ;; - or1k*-linux*) + or1k*-*-*) TARGET=OR1K; TARGETDIR=or1k SOURCES="ffi.c sysv.S" ;; @@ -168,6 +196,9 @@ case "${host}" in powerpc-*-amigaos*) TARGET=POWERPC; TARGETDIR=powerpc ;; + powerpc-*-eabi*) + TARGET=POWERPC; TARGETDIR=powerpc + ;; powerpc-*-beos*) TARGET=POWERPC; TARGETDIR=powerpc ;; @@ -177,11 +208,15 @@ case "${host}" in powerpc-*-aix* | rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc ;; - powerpc-*-freebsd* | powerpc-*-openbsd*) + powerpc-*-freebsd* | powerpc-*-openbsd* | powerpc-*-netbsd*) TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc HAVE_LONG_DOUBLE_VARIANT=1 ;; - powerpc64-*-freebsd*) + powerpcspe-*-freebsd*) + TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc + CFLAGS="$CFLAGS -D__NO_FPRS__" + ;; + powerpc64-*-freebsd* | powerpc64le-*-freebsd*) TARGET=POWERPC; TARGETDIR=powerpc ;; powerpc*-*-rtems*) @@ -230,6 +265,20 @@ esac # ... but some of the cases above share configury. case "${TARGET}" in + ARM_WIN32) + if test "$MSVC" = 1; then + SOURCES="ffi.c sysv_msvc_arm32.S" + else + SOURCES="ffi.c sysv.S" + fi + ;; + ARM_WIN64) + if test "$MSVC" = 1; then + SOURCES="ffi.c win64_armasm.S" + else + SOURCES="ffi.c sysv.S" + fi + ;; MIPS) SOURCES="ffi.c o32.S n32.S" ;; @@ -246,20 +295,26 @@ case "${TARGET}" in POWERPC_FREEBSD) SOURCES="ffi.c ffi_sysv.c sysv.S ppc_closure.S" ;; - X86 | X86_FREEBSD | X86_WIN32) - SOURCES="ffi.c sysv.S" + X86 | X86_DARWIN | X86_FREEBSD | X86_WIN32) + if test "$MSVC" = 1; then + SOURCES="ffi.c sysv_intel.S" + else + SOURCES="ffi.c sysv.S" + fi ;; X86_64) - SOURCES="ffi64.c unix64.S" + if test x"$TARGET_X32" = xyes; then + SOURCES="ffi64.c unix64.S" + else + SOURCES="ffi64.c unix64.S ffiw64.c win64.S" + fi ;; X86_WIN64) - SOURCES="ffiw64.c win64.S" - ;; - X86_DARWIN) - SOURCES="darwin_c.c darwin.S" - ;; - X86_64_DARWIN) - SOURCES="darwin64_c.c darwin64.S" + if test "$MSVC" = 1; then + SOURCES="ffiw64.c win64_intel.S" + else + SOURCES="ffiw64.c win64.S" + fi ;; esac diff --git a/libffi/doc/Makefile.am b/libffi/doc/Makefile.am new file mode 100644 index 0000000..43b650a --- /dev/null +++ b/libffi/doc/Makefile.am @@ -0,0 +1,3 @@ +## Process this with automake to create Makefile.in + +info_TEXINFOS = libffi.texi diff --git a/libffi/doc/libffi.texi b/libffi/doc/libffi.texi index b9887a8..7fd3625 100644 --- a/libffi/doc/libffi.texi +++ b/libffi/doc/libffi.texi @@ -1,7 +1,8 @@ \input texinfo @c -*-texinfo-*- @c %**start of header @setfilename libffi.info -@settitle libffi +@include version.texi +@settitle libffi: the portable foreign function interface library @setchapternewpage off @c %**end of header @@ -12,32 +13,43 @@ @syncodeindex pg cp @syncodeindex tp cp -@include version.texi - @copying -This manual is for Libffi, a portable foreign-function interface +This manual is for libffi, a portable foreign function interface library. -Copyright @copyright{} 2008, 2010, 2011 Red Hat, Inc. +Copyright @copyright{} 2008--2019, 2021 Anthony Green and Red Hat, Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -@quotation -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. A copy of the license is included in the -section entitled ``GNU General Public License''. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -@end quotation @end copying @dircategory Development @direntry -* libffi: (libffi). Portable foreign-function interface library. +* libffi: (libffi). Portable foreign function interface library. @end direntry @titlepage -@title Libffi +@title libffi: a foreign function interface library +@subtitle For Version @value{VERSION} of libffi +@author Anthony Green @page @vskip 0pt plus 1filll @insertcopying @@ -53,6 +65,7 @@ section entitled ``GNU General Public License''. @menu * Introduction:: What is libffi? * Using libffi:: How to use libffi. +* Memory Usage:: Where memory for closures comes from. * Missing Features:: Things libffi can't do. * Index:: Index. @end menu @@ -107,6 +120,7 @@ values passed between the two languages. * Multiple ABIs:: Different passing styles on one platform. * The Closure API:: Writing a generic function. * Closure Example:: A closure example. +* Thread Safety:: Thread safety. @end menu @@ -152,16 +166,21 @@ If the function being called is variadic (varargs) then @code{ffi_prep_cif_var} must be used instead of @code{ffi_prep_cif}. @findex ffi_prep_cif_var -@defun ffi_status ffi_prep_cif_var (ffi_cif *@var{cif}, ffi_abi var{abi}, unsigned int @var{nfixedargs}, unsigned int var{ntotalargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes}) +@defun ffi_status ffi_prep_cif_var (ffi_cif *@var{cif}, ffi_abi @var{abi}, unsigned int @var{nfixedargs}, unsigned int @var{ntotalargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes}) This initializes @var{cif} according to the given parameters for -a call to a variadic function. In general it's operation is the +a call to a variadic function. In general its operation is the same as for @code{ffi_prep_cif} except that: @var{nfixedargs} is the number of fixed arguments, prior to any variadic arguments. It must be greater than zero. @var{ntotalargs} the total number of arguments, including variadic -and fixed arguments. +and fixed arguments. @var{argtypes} must have this many elements. + +@code{ffi_prep_cif_var} will return @code{FFI_BAD_ARGTYPE} if any of +the variable argument types are @code{ffi_type_float} (promote to +@code{ffi_type_double} first), or any integer type small than an int +(promote to an int-sized type first). Note that, different cif's must be prepped for calls to the same function when different numbers of arguments are passed. @@ -172,6 +191,10 @@ Also note that a call to @code{ffi_prep_cif_var} with @end defun +Note that the resulting @code{ffi_cif} holds pointers to all the +@code{ffi_type} objects that were used during initialization. You +must ensure that these type objects have a lifetime at least as long +as that of the @code{ffi_cif}. To call a function using an initialized @code{ffi_cif}, use the @code{ffi_call} function: @@ -190,12 +213,29 @@ to ensure this. If @var{cif} declares that the function returns @code{void} (using @code{ffi_type_void}), then @var{rvalue} is ignored. +In most situations, @samp{libffi} will handle promotion according to +the ABI. However, for historical reasons, there is a special case +with return values that must be handled by your code. In particular, +for integral (not @code{struct}) types that are narrower than the +system register size, the return value will be widened by +@samp{libffi}. @samp{libffi} provides a type, @code{ffi_arg}, that +can be used as the return type. For example, if the CIF was defined +with a return type of @code{char}, @samp{libffi} will try to store a +full @code{ffi_arg} into the return value. + @var{avalues} is a vector of @code{void *} pointers that point to the memory locations holding the argument values for a call. If @var{cif} declares that the function has no arguments (i.e., @var{nargs} was 0), then @var{avalues} is ignored. Note that argument values may be modified by the callee (for instance, structs passed by value); the burden of copying pass-by-value arguments is placed on the caller. + +Note that while the return value must be register-sized, arguments +should exactly match their declared type. For example, if an argument +is a @code{short}, then the entry in @var{avalues} should point to an +object declared as @code{short}; but if the return type is +@code{short}, then @var{rvalue} should point to an object declared as +a larger type -- usually @code{ffi_arg}. @end defun @@ -215,26 +255,26 @@ int main() void *values[1]; char *s; ffi_arg rc; - - /* Initialize the argument info vectors */ + + /* Initialize the argument info vectors */ args[0] = &ffi_type_pointer; values[0] = &s; - + /* Initialize the cif */ - if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, + if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_sint, args) == FFI_OK) @{ s = "Hello World!"; ffi_call(&cif, puts, &rc, values); /* rc now holds the result of the call to puts */ - - /* values holds a pointer to the function's arg, so to - call puts() again all we need to do is change the + + /* values holds a pointer to the function's arg, so to + call puts() again all we need to do is change the value of s */ s = "This is cool!"; ffi_call(&cif, puts, &rc, values); @} - + return 0; @} @end example @@ -246,6 +286,8 @@ int main() @menu * Primitive Types:: Built-in types. * Structures:: Structure types. +* Size and Alignment:: Size and alignment of types. +* Arrays Unions Enums:: Arrays, unions, and enumerations. * Type Example:: Structure type example. * Complex:: Complex types. * Complex Type Example:: Complex type example. @@ -370,8 +412,7 @@ when passing to @code{ffi_prep_cif}. @node Structures @subsection Structures -Although @samp{libffi} has no special support for unions or -bit-fields, it is perfectly happy passing structures back and forth. +@samp{libffi} is perfectly happy passing structures back and forth. You must first describe the structure to @samp{libffi} by creating a new @code{ffi_type} object for it. @@ -391,9 +432,166 @@ For a structure, this should be set to @code{FFI_TYPE_STRUCT}. @item ffi_type **elements This is a @samp{NULL}-terminated array of pointers to @code{ffi_type} objects. There is one element per field of the struct. + +Note that @samp{libffi} has no special support for bit-fields. You +must manage these manually. @end table @end deftp +The @code{size} and @code{alignment} fields will be filled in by +@code{ffi_prep_cif} or @code{ffi_prep_cif_var}, as needed. + +@node Size and Alignment +@subsection Size and Alignment + +@code{libffi} will set the @code{size} and @code{alignment} fields of +an @code{ffi_type} object for you. It does so using its knowledge of +the ABI. + +You might expect that you can simply read these fields for a type that +has been laid out by @code{libffi}. However, there are some caveats. + +@itemize @bullet +@item +The size or alignment of some of the built-in types may vary depending +on the chosen ABI. + +@item +The size and alignment of a new structure type will not be set by +@code{libffi} until it has been passed to @code{ffi_prep_cif} or +@code{ffi_get_struct_offsets}. + +@item +A structure type cannot be shared across ABIs. Instead each ABI needs +its own copy of the structure type. +@end itemize + +So, before examining these fields, it is safest to pass the +@code{ffi_type} object to @code{ffi_prep_cif} or +@code{ffi_get_struct_offsets} first. This function will do all the +needed setup. + +@example +ffi_type *desired_type; +ffi_abi desired_abi; +@dots{} +ffi_cif cif; +if (ffi_prep_cif (&cif, desired_abi, 0, desired_type, NULL) == FFI_OK) + @{ + size_t size = desired_type->size; + unsigned short alignment = desired_type->alignment; + @} +@end example + +@code{libffi} also provides a way to get the offsets of the members of +a structure. + +@findex ffi_get_struct_offsets +@defun ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets) +Compute the offset of each element of the given structure type. +@var{abi} is the ABI to use; this is needed because in some cases the +layout depends on the ABI. + +@var{offsets} is an out parameter. The caller is responsible for +providing enough space for all the results to be written -- one +element per element type in @var{struct_type}. If @var{offsets} is +@code{NULL}, then the type will be laid out but not otherwise +modified. This can be useful for accessing the type's size or layout, +as mentioned above. + +This function returns @code{FFI_OK} on success; @code{FFI_BAD_ABI} if +@var{abi} is invalid; or @code{FFI_BAD_TYPEDEF} if @var{struct_type} +is invalid in some way. Note that only @code{FFI_STRUCT} types are +valid here. +@end defun + +@node Arrays Unions Enums +@subsection Arrays, Unions, and Enumerations + +@subsubsection Arrays + +@samp{libffi} does not have direct support for arrays or unions. +However, they can be emulated using structures. + +To emulate an array, simply create an @code{ffi_type} using +@code{FFI_TYPE_STRUCT} with as many members as there are elements in +the array. + +@example +ffi_type array_type; +ffi_type **elements +int i; + +elements = malloc ((n + 1) * sizeof (ffi_type *)); +for (i = 0; i < n; ++i) + elements[i] = array_element_type; +elements[n] = NULL; + +array_type.size = array_type.alignment = 0; +array_type.type = FFI_TYPE_STRUCT; +array_type.elements = elements; +@end example + +Note that arrays cannot be passed or returned by value in C -- +structure types created like this should only be used to refer to +members of real @code{FFI_TYPE_STRUCT} objects. + +However, a phony array type like this will not cause any errors from +@samp{libffi} if you use it as an argument or return type. This may +be confusing. + +@subsubsection Unions + +A union can also be emulated using @code{FFI_TYPE_STRUCT}. In this +case, however, you must make sure that the size and alignment match +the real requirements of the union. + +One simple way to do this is to ensue that each element type is laid +out. Then, give the new structure type a single element; the size of +the largest element; and the largest alignment seen as well. + +This example uses the @code{ffi_prep_cif} trick to ensure that each +element type is laid out. + +@example +ffi_abi desired_abi; +ffi_type union_type; +ffi_type **union_elements; + +int i; +ffi_type element_types[2]; + +element_types[1] = NULL; + +union_type.size = union_type.alignment = 0; +union_type.type = FFI_TYPE_STRUCT; +union_type.elements = element_types; + +for (i = 0; union_elements[i]; ++i) + @{ + ffi_cif cif; + if (ffi_prep_cif (&cif, desired_abi, 0, union_elements[i], NULL) == FFI_OK) + @{ + if (union_elements[i]->size > union_type.size) + @{ + union_type.size = union_elements[i]; + size = union_elements[i]->size; + @} + if (union_elements[i]->alignment > union_type.alignment) + union_type.alignment = union_elements[i]->alignment; + @} + @} +@end example + +@subsubsection Enumerations + +@code{libffi} does not have any special support for C @code{enum}s. +Although any given @code{enum} is implemented using a specific +underlying integral type, exactly which type will be used cannot be +determined by @code{libffi} -- it may depend on the values in the +enumeration or on compiler flags such as @option{-fshort-enums}. +@xref{Structures unions enumerations and bit-fields implementation, , , gcc}, +for more information about how GCC handles enumerations. @node Type Example @subsection Type Example @@ -432,7 +630,7 @@ Here is the corresponding code to describe this struct to tm_type.size = tm_type.alignment = 0; tm_type.type = FFI_TYPE_STRUCT; tm_type.elements = &tm_type_elements; - + for (i = 0; i < 9; i++) tm_type_elements[i] = &ffi_type_sint; @@ -630,30 +828,47 @@ the closure function: @findex ffi_prep_closure_loc @defun ffi_status ffi_prep_closure_loc (ffi_closure *@var{closure}, ffi_cif *@var{cif}, void (*@var{fun}) (ffi_cif *@var{cif}, void *@var{ret}, void **@var{args}, void *@var{user_data}), void *@var{user_data}, void *@var{codeloc}) -Prepare a closure function. +Prepare a closure function. The arguments to +@code{ffi_prep_closure_loc} are: -@var{closure} is the address of a @code{ffi_closure} object; this is -the writable address returned by @code{ffi_closure_alloc}. +@table @var +@item closure +The address of a @code{ffi_closure} object; this is the writable +address returned by @code{ffi_closure_alloc}. + +@item cif +The @code{ffi_cif} describing the function parameters. Note that this +object, and the types to which it refers, must be kept alive until the +closure itself is freed. -@var{cif} is the @code{ffi_cif} describing the function parameters. +@item user_data +An arbitrary datum that is passed, uninterpreted, to your closure +function. -@var{user_data} is an arbitrary datum that is passed, uninterpreted, -to your closure function. +@item codeloc +The executable address returned by @code{ffi_closure_alloc}. -@var{codeloc} is the executable address returned by -@code{ffi_closure_alloc}. +@item fun +The function which will be called when the closure is invoked. It is +called with the arguments: -@var{fun} is the function which will be called when the closure is -invoked. It is called with the arguments: @table @var @item cif The @code{ffi_cif} passed to @code{ffi_prep_closure_loc}. @item ret A pointer to the memory used for the function's return value. -@var{fun} must fill this, unless the function is declared as returning -@code{void}. -@c FIXME: is this NULL for void-returning functions? + +If the function is declared as returning @code{void}, then this value +is garbage and should not be used. + +Otherwise, @var{fun} must fill the object to which this points, +following the same special promotion behavior as @code{ffi_call}. +That is, in most cases, @var{ret} points to an object of exactly the +size of the type specified when @var{cif} was constructed. However, +integral types narrower than the system register size are widened. In +these cases your program may assume that @var{ret} points to an +@code{ffi_arg} object. @item args A vector of pointers to memory holding the arguments to the function. @@ -662,10 +877,10 @@ A vector of pointers to memory holding the arguments to the function. The same @var{user_data} that was passed to @code{ffi_prep_closure_loc}. @end table +@end table @code{ffi_prep_closure_loc} will return @code{FFI_OK} if everything -went ok, and something else on error. -@c FIXME: what? +went ok, and one of the other @code{ffi_status} values on error. After calling @code{ffi_prep_closure_loc}, you can cast @var{codeloc} to the appropriate pointer-to-function type. @@ -678,7 +893,7 @@ writable and executable addresses. @node Closure Example @section Closure Example -A trivial example that creates a new @code{puts} by binding +A trivial example that creates a new @code{puts} by binding @code{fputs} with @code{stdout}. @example @@ -733,6 +948,77 @@ int main() @end example +@node Thread Safety +@section Thread Safety + +@code{libffi} is not completely thread-safe. However, many parts are, +and if you follow some simple rules, you can use it safely in a +multi-threaded program. + +@itemize @bullet +@item +@code{ffi_prep_cif} may modify the @code{ffi_type} objects passed to +it. It is best to ensure that only a single thread prepares a given +@code{ffi_cif} at a time. + +@item +On some platforms, @code{ffi_prep_cif} may modify the size and +alignment of some types, depending on the chosen ABI. On these +platforms, if you switch between ABIs, you must ensure that there is +only one call to @code{ffi_prep_cif} at a time. + +Currently the only affected platform is PowerPC and the only affected +type is @code{long double}. +@end itemize + +@node Memory Usage +@chapter Memory Usage + +Note that memory allocated by @code{ffi_closure_alloc} and freed by +@code{ffi_closure_free} does not come from the same general pool of +memory that @code{malloc} and @code{free} use. To accomodate security +settings, @samp{libffi} may aquire memory, for example, by mapping +temporary files into multiple places in the address space (once to +write out the closure, a second to execute it). The search follows +this list, using the first that works: + +@itemize @bullet + +@item +A anonymous mapping (i.e. not file-backed) + +@item +@code{memfd_create()}, if the kernel supports it. + +@item +A file created in the directory referenced by the environment variable +@code{LIBFFI_TMPDIR}. + +@item +Likewise for the environment variable @code{TMPDIR}. + +@item +A file created in @code{/tmp}. + +@item +A file created in @code{/var/tmp}. + +@item +A file created in @code{/dev/shm}. + +@item +A file created in the user's home directory (@code{$HOME}). + +@item +A file created in any directory listed in @code{/etc/mtab}. + +@item +A file created in any directory listed in @code{/proc/mounts}. + +@end itemize + +If security settings prohibit using any of these for closures, +@code{ffi_closure_alloc} will fail. @node Missing Features @chapter Missing Features @@ -749,13 +1035,11 @@ There is no support for bit fields in structures. @item The ``raw'' API is undocumented. -@c argument promotion? -@c unions? @c anything else? -@end itemize -Note that variadic support is very new and tested on a relatively -small number of platforms. +@item +The Go API is undocumented. +@end itemize @node Index @unnumbered Index diff --git a/libffi/doc/version.texi b/libffi/doc/version.texi index ccef70f4..f2b741e 100644 --- a/libffi/doc/version.texi +++ b/libffi/doc/version.texi @@ -1,4 +1,4 @@ -@set UPDATED 8 November 2014 -@set UPDATED-MONTH November 2014 -@set EDITION 3.2.1 -@set VERSION 3.2.1 +@set UPDATED 27 June 2021 +@set UPDATED-MONTH June 2021 +@set EDITION 3.4.2 +@set VERSION 3.4.2 diff --git a/libffi/fficonfig.h.in b/libffi/fficonfig.h.in index 2cf8de9..15aa54c 100644 --- a/libffi/fficonfig.h.in +++ b/libffi/fficonfig.h.in @@ -17,6 +17,9 @@ /* Define this if you want extra debugging. */ #undef FFI_DEBUG +/* Define this if you want statically defined trampolines */ +#undef FFI_EXEC_STATIC_TRAMP + /* Cannot use PROT_EXEC on this target, so, we revert to alternative means */ #undef FFI_EXEC_TRAMPOLINE_TABLE @@ -76,12 +79,18 @@ /* Define to 1 if you have the `memcpy' function. */ #undef HAVE_MEMCPY +/* Define to 1 if you have the `memfd_create' function. */ +#undef HAVE_MEMFD_CREATE + /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `mkostemp' function. */ #undef HAVE_MKOSTEMP +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + /* Define to 1 if you have the `mmap' function. */ #undef HAVE_MMAP @@ -94,6 +103,9 @@ /* Define if read-only mmap of a plain file works. */ #undef HAVE_MMAP_FILE +/* Define if your compiler supports pointer authentication. */ +#undef HAVE_PTRAUTH + /* Define if .eh_frame sections should be read-only. */ #undef HAVE_RO_EH_FRAME @@ -109,6 +121,9 @@ /* Define to 1 if you have the <string.h> header file. */ #undef HAVE_STRING_H +/* Define to 1 if you have the <sys/memfd.h> header file. */ +#undef HAVE_SYS_MEMFD_H + /* Define to 1 if you have the <sys/mman.h> header file. */ #undef HAVE_SYS_MMAN_H @@ -122,7 +137,7 @@ #undef HAVE_UNISTD_H /* Define to 1 if GNU symbol versioning is used for libatomic. */ -#undef LIBAT_GNU_SYMBOL_VERSIONING +#undef LIBFFI_GNU_SYMBOL_VERSIONING /* Define to the sub-directory in which libtool stores uninstalled libraries. */ @@ -194,7 +209,11 @@ #ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE #ifdef LIBFFI_ASM +#ifdef __APPLE__ +#define FFI_HIDDEN(name) .private_extern name +#else #define FFI_HIDDEN(name) .hidden name +#endif #else #define FFI_HIDDEN __attribute__ ((visibility ("hidden"))) #endif diff --git a/libffi/generate-darwin-source-and-headers.py b/libffi/generate-darwin-source-and-headers.py index 306136f..9921b0d 100644..100755 --- a/libffi/generate-darwin-source-and-headers.py +++ b/libffi/generate-darwin-source-and-headers.py @@ -6,59 +6,73 @@ import collections import glob import argparse + class Platform(object): pass + class simulator_platform(Platform): - directory = 'darwin_ios' - sdk = 'iphonesimulator' arch = 'i386' triple = 'i386-apple-darwin11' - version_min = '-miphoneos-version-min=7.0' prefix = "#ifdef __i386__\n\n" suffix = "\n\n#endif" src_dir = 'x86' - src_files = ['darwin.S', 'win32.S', 'ffi.c'] + src_files = ['sysv.S', 'ffi.c', 'internal.h'] class simulator64_platform(Platform): - directory = 'darwin_ios' - sdk = 'iphonesimulator' arch = 'x86_64' triple = 'x86_64-apple-darwin13' - version_min = '-miphoneos-version-min=7.0' prefix = "#ifdef __x86_64__\n\n" suffix = "\n\n#endif" src_dir = 'x86' - src_files = ['darwin64.S', 'ffi64.c'] + src_files = ['unix64.S', 'ffi64.c', 'ffiw64.c', 'win64.S', 'internal64.h', 'asmnames.h'] class device_platform(Platform): - directory = 'darwin_ios' - sdk = 'iphoneos' arch = 'armv7' triple = 'arm-apple-darwin11' - version_min = '-miphoneos-version-min=7.0' prefix = "#ifdef __arm__\n\n" suffix = "\n\n#endif" src_dir = 'arm' - src_files = ['sysv.S', 'trampoline.S', 'ffi.c'] + src_files = ['sysv.S', 'ffi.c', 'internal.h'] class device64_platform(Platform): - directory = 'darwin_ios' - sdk = 'iphoneos' arch = 'arm64' triple = 'aarch64-apple-darwin13' - version_min = '-miphoneos-version-min=7.0' prefix = "#ifdef __arm64__\n\n" suffix = "\n\n#endif" src_dir = 'aarch64' - src_files = ['sysv.S', 'ffi.c'] + src_files = ['sysv.S', 'ffi.c', 'internal.h'] + + +class ios_simulator_platform(simulator_platform): + directory = 'darwin_ios' + sdk = 'iphonesimulator' + version_min = '-miphoneos-version-min=7.0' + + +class ios_simulator64_platform(simulator64_platform): + directory = 'darwin_ios' + sdk = 'iphonesimulator' + version_min = '-miphoneos-version-min=7.0' + + +class ios_device_platform(device_platform): + directory = 'darwin_ios' + sdk = 'iphoneos' + version_min = '-miphoneos-version-min=7.0' + + +class ios_device64_platform(device64_platform): + directory = 'darwin_ios' + sdk = 'iphoneos' + version_min = '-miphoneos-version-min=7.0' class desktop32_platform(Platform): @@ -68,7 +82,7 @@ class desktop32_platform(Platform): triple = 'i386-apple-darwin10' version_min = '-mmacosx-version-min=10.6' src_dir = 'x86' - src_files = ['darwin.S', 'win32.S', 'ffi.c'] + src_files = ['sysv.S', 'ffi.c', 'internal.h'] prefix = "#ifdef __i386__\n\n" suffix = "\n\n#endif" @@ -84,16 +98,39 @@ class desktop64_platform(Platform): prefix = "#ifdef __x86_64__\n\n" suffix = "\n\n#endif" src_dir = 'x86' - src_files = ['darwin64.S', 'ffi64.c'] + src_files = ['unix64.S', 'ffi64.c', 'ffiw64.c', 'win64.S', 'internal64.h', 'asmnames.h'] + + +class tvos_simulator64_platform(simulator64_platform): + directory = 'darwin_tvos' + sdk = 'appletvsimulator' + version_min = '-mtvos-version-min=9.0' + + +class tvos_device64_platform(device64_platform): + directory = 'darwin_tvos' + sdk = 'appletvos' + version_min = '-mtvos-version-min=9.0' + + +class watchos_simulator_platform(simulator_platform): + directory = 'darwin_watchos' + sdk = 'watchsimulator' + version_min = '-mwatchos-version-min=4.0' + + +class watchos_device_platform(device_platform): + directory = 'darwin_watchos' + sdk = 'watchos' + arch = 'armv7k' + version_min = '-mwatchos-version-min=4.0' def mkdir_p(path): try: os.makedirs(path) except OSError as exc: # Python >2.5 - if exc.errno == errno.EEXIST: - pass - else: + if exc.errno != errno.EEXIST: raise @@ -102,8 +139,11 @@ def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix='' out_filename = filename if file_suffix: - split_name = os.path.splitext(filename) - out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1]) + if filename in ['internal64.h', 'asmnames.h', 'internal.h']: + out_filename = filename + else: + split_name = os.path.splitext(filename) + out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1]) with open(os.path.join(src_dir, filename)) as in_file: with open(os.path.join(dst_dir, out_filename), 'w') as out_file: @@ -142,7 +182,7 @@ def build_target(platform, platform_headers): mkdir_p(build_dir) env = dict(CC=xcrun_cmd('clang'), LD=xcrun_cmd('ld'), - CFLAGS='%s' % (platform.version_min)) + CFLAGS='%s -fembed-bitcode' % (platform.version_min)) working_dir = os.getcwd() try: os.chdir(build_dir) @@ -162,39 +202,47 @@ def build_target(platform, platform_headers): platform_headers[filename].add((platform.prefix, platform.arch, platform.suffix)) -def make_tramp(): - with open('src/arm/trampoline.S', 'w') as tramp_out: - p = subprocess.Popen(['bash', 'src/arm/gentramp.sh'], stdout=tramp_out) - p.wait() - - -def generate_source_and_headers(generate_osx=True, generate_ios=True): +def generate_source_and_headers( + generate_osx=True, + generate_ios=True, + generate_tvos=True, + generate_watchos=True, +): copy_files('src', 'darwin_common/src', pattern='*.c') copy_files('include', 'darwin_common/include', pattern='*.h') if generate_ios: - make_tramp() - copy_src_platform_files(simulator_platform) - copy_src_platform_files(simulator64_platform) - copy_src_platform_files(device_platform) - copy_src_platform_files(device64_platform) + copy_src_platform_files(ios_simulator_platform) + copy_src_platform_files(ios_simulator64_platform) + copy_src_platform_files(ios_device_platform) + copy_src_platform_files(ios_device64_platform) if generate_osx: - copy_src_platform_files(desktop32_platform) copy_src_platform_files(desktop64_platform) + if generate_tvos: + copy_src_platform_files(tvos_simulator64_platform) + copy_src_platform_files(tvos_device64_platform) + if generate_watchos: + copy_src_platform_files(watchos_simulator_platform) + copy_src_platform_files(watchos_device_platform) platform_headers = collections.defaultdict(set) if generate_ios: - build_target(simulator_platform, platform_headers) - build_target(simulator64_platform, platform_headers) - build_target(device_platform, platform_headers) - build_target(device64_platform, platform_headers) + build_target(ios_simulator_platform, platform_headers) + build_target(ios_simulator64_platform, platform_headers) + build_target(ios_device_platform, platform_headers) + build_target(ios_device64_platform, platform_headers) if generate_osx: - build_target(desktop32_platform, platform_headers) build_target(desktop64_platform, platform_headers) + if generate_tvos: + build_target(tvos_simulator64_platform, platform_headers) + build_target(tvos_device64_platform, platform_headers) + if generate_watchos: + build_target(watchos_simulator_platform, platform_headers) + build_target(watchos_device_platform, platform_headers) mkdir_p('darwin_common/include') - for header_name, tag_tuples in platform_headers.iteritems(): + for header_name, tag_tuples in platform_headers.items(): basename, suffix = os.path.splitext(header_name) with open(os.path.join('darwin_common/include', header_name), 'w') as header: for tag_tuple in tag_tuples: @@ -204,6 +252,13 @@ if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--only-ios', action='store_true', default=False) parser.add_argument('--only-osx', action='store_true', default=False) + parser.add_argument('--only-tvos', action='store_true', default=False) + parser.add_argument('--only-watchos', action='store_true', default=False) args = parser.parse_args() - generate_source_and_headers(generate_osx=not args.only_ios, generate_ios=not args.only_osx) + generate_source_and_headers( + generate_osx=not args.only_ios and not args.only_tvos and not args.only_watchos, + generate_ios=not args.only_osx and not args.only_tvos and not args.only_watchos, + generate_tvos=not args.only_ios and not args.only_osx and not args.only_watchos, + generate_watchos=not args.only_ios and not args.only_osx and not args.only_tvos, + ) diff --git a/libffi/include/Makefile.am b/libffi/include/Makefile.am index 37fde6e..d7d1641 100644 --- a/libffi/include/Makefile.am +++ b/libffi/include/Makefile.am @@ -3,7 +3,7 @@ AUTOMAKE_OPTIONS=foreign DISTCLEANFILES=ffitarget.h -noinst_HEADERS=ffi_common.h ffi_cfi.h +noinst_HEADERS=ffi_common.h ffi_cfi.h tramp.h EXTRA_DIST=ffi.h.in # Where generated headers like ffitarget.h get installed. diff --git a/libffi/include/Makefile.in b/libffi/include/Makefile.in index 99da841..c76e2a8 100644 --- a/libffi/include/Makefile.in +++ b/libffi/include/Makefile.in @@ -246,6 +246,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ +READELF = @READELF@ SECTION_LDFLAGS = @SECTION_LDFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -317,7 +318,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign DISTCLEANFILES = ffitarget.h -noinst_HEADERS = ffi_common.h ffi_cfi.h +noinst_HEADERS = ffi_common.h ffi_cfi.h tramp.h EXTRA_DIST = ffi.h.in # Where generated headers like ffitarget.h get installed. diff --git a/libffi/include/ffi.h.in b/libffi/include/ffi.h.in index 191aef7..d16f307 100644 --- a/libffi/include/ffi.h.in +++ b/libffi/include/ffi.h.in @@ -1,6 +1,7 @@ /* -----------------------------------------------------------------*-C-*- - libffi @VERSION@ - Copyright (c) 2011, 2014 Anthony Green - - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc. + libffi @VERSION@ + - Copyright (c) 2011, 2014, 2019, 2021 Anthony Green + - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -25,23 +26,14 @@ ----------------------------------------------------------------------- */ /* ------------------------------------------------------------------- - The basic API is described in the README file. + Most of the API is documented in doc/libffi.texi. - The raw API is designed to bypass some of the argument packing - and unpacking on architectures for which it can be avoided. + The raw API is designed to bypass some of the argument packing and + unpacking on architectures for which it can be avoided. Routines + are provided to emulate the raw API if the underlying platform + doesn't allow faster implementation. - The closure API allows interpreted functions to be packaged up - inside a C function pointer, so that they can be called as C functions, - with no understanding on the client side that they are interpreted. - It can also be used in other cases in which it is necessary to package - up a user specified parameter and a function pointer as a single - function pointer. - - The closure API must be implemented in order to get its functionality, - e.g. for use by gij. Routines are provided to emulate the raw API - if the underlying platform doesn't allow faster implementation. - - More details on the raw and cloure API can be found in: + More details on the raw API can be found in: http://gcc.gnu.org/ml/java/1999-q3/msg00138.html @@ -106,8 +98,8 @@ extern "C" { # endif #endif -/* The closure code assumes that this works on pointers, i.e. a size_t */ -/* can hold a pointer. */ +/* The closure code assumes that this works on pointers, i.e. a size_t + can hold a pointer. */ typedef struct _ffi_type { @@ -117,6 +109,32 @@ typedef struct _ffi_type struct _ffi_type **elements; } ffi_type; +/* Need minimal decorations for DLLs to work on Windows. GCC has + autoimport and autoexport. Always mark externally visible symbols + as dllimport for MSVC clients, even if it means an extra indirection + when using the static version of the library. + Besides, as a workaround, they can define FFI_BUILDING if they + *know* they are going to link with the static library. */ +#if defined _MSC_VER +# if defined FFI_BUILDING_DLL /* Building libffi.DLL with msvcc.sh */ +# define FFI_API __declspec(dllexport) +# elif !defined FFI_BUILDING /* Importing libffi.DLL */ +# define FFI_API __declspec(dllimport) +# else /* Building/linking static library */ +# define FFI_API +# endif +#else +# define FFI_API +#endif + +/* The externally visible type declarations also need the MSVC DLL + decorations, or they will not be exported from the object file. */ +#if defined LIBFFI_HIDE_BASIC_TYPES +# define FFI_EXTERN FFI_API +#else +# define FFI_EXTERN extern FFI_API +#endif + #ifndef LIBFFI_HIDE_BASIC_TYPES #if SCHAR_MAX == 127 # define ffi_type_uchar ffi_type_uint8 @@ -166,21 +184,7 @@ typedef struct _ffi_type #error "long size not supported" #endif -/* Need minimal decorations for DLLs to works on Windows. */ -/* GCC has autoimport and autoexport. Rely on Libtool to */ -/* help MSVC export from a DLL, but always declare data */ -/* to be imported for MSVC clients. This costs an extra */ -/* indirection for MSVC clients using the static version */ -/* of the library, but don't worry about that. Besides, */ -/* as a workaround, they can define FFI_BUILDING if they */ -/* *know* they are going to link with the static library. */ -#if defined _MSC_VER && !defined FFI_BUILDING -#define FFI_EXTERN extern __declspec(dllimport) -#else -#define FFI_EXTERN extern -#endif - -/* These are defined in types.c */ +/* These are defined in types.c. */ FFI_EXTERN ffi_type ffi_type_void; FFI_EXTERN ffi_type ffi_type_uint8; FFI_EXTERN ffi_type ffi_type_sint8; @@ -214,11 +218,10 @@ FFI_EXTERN ffi_type ffi_type_complex_longdouble; typedef enum { FFI_OK = 0, FFI_BAD_TYPEDEF, - FFI_BAD_ABI + FFI_BAD_ABI, + FFI_BAD_ARGTYPE } ffi_status; -typedef unsigned FFI_TYPE; - typedef struct { ffi_abi abi; unsigned nargs; @@ -231,20 +234,6 @@ typedef struct { #endif } ffi_cif; -#if @HAVE_LONG_DOUBLE_VARIANT@ -/* Used to adjust size/alignment of ffi types. */ -void ffi_prep_types (ffi_abi abi); -#endif - -/* Used internally, but overridden by some architectures */ -ffi_status ffi_prep_cif_core(ffi_cif *cif, - ffi_abi abi, - unsigned int isvariadic, - unsigned int nfixedargs, - unsigned int ntotalargs, - ffi_type *rtype, - ffi_type **atypes); - /* ---- Definitions for the raw API -------------------------------------- */ #ifndef FFI_SIZEOF_ARG @@ -282,27 +271,34 @@ typedef ffi_raw ffi_java_raw; #endif +FFI_API void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue); -void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); -void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); -size_t ffi_raw_size (ffi_cif *cif); +FFI_API void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); +FFI_API void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); +FFI_API size_t ffi_raw_size (ffi_cif *cif); -/* This is analogous to the raw API, except it uses Java parameter */ -/* packing, even on 64-bit machines. I.e. on 64-bit machines */ -/* longs and doubles are followed by an empty 64-bit word. */ +/* This is analogous to the raw API, except it uses Java parameter + packing, even on 64-bit machines. I.e. on 64-bit machines longs + and doubles are followed by an empty 64-bit word. */ +#if !FFI_NATIVE_RAW_API +FFI_API void ffi_java_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, - ffi_java_raw *avalue); + ffi_java_raw *avalue) __attribute__((deprecated)); +#endif -void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw); -void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args); -size_t ffi_java_raw_size (ffi_cif *cif); +FFI_API +void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw) __attribute__((deprecated)); +FFI_API +void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args) __attribute__((deprecated)); +FFI_API +size_t ffi_java_raw_size (ffi_cif *cif) __attribute__((deprecated)); /* ---- Definitions for closures ----------------------------------------- */ @@ -316,30 +312,50 @@ typedef struct { void *trampoline_table; void *trampoline_table_entry; #else - char tramp[FFI_TRAMPOLINE_SIZE]; + union { + char tramp[FFI_TRAMPOLINE_SIZE]; + void *ftramp; + }; #endif ffi_cif *cif; void (*fun)(ffi_cif*,void*,void**,void*); void *user_data; +} ffi_closure #ifdef __GNUC__ -} ffi_closure __attribute__((aligned (8))); -#else -} ffi_closure; + __attribute__((aligned (8))) +#endif + ; + +#ifndef __GNUC__ # ifdef __sgi # pragma pack 0 # endif #endif -void *ffi_closure_alloc (size_t size, void **code); -void ffi_closure_free (void *); +FFI_API void *ffi_closure_alloc (size_t size, void **code); +FFI_API void ffi_closure_free (void *); + +#if defined(PA_LINUX) || defined(PA_HPUX) +#define FFI_CLOSURE_PTR(X) ((void *)((unsigned int)(X) | 2)) +#define FFI_RESTORE_PTR(X) ((void *)((unsigned int)(X) & ~3)) +#else +#define FFI_CLOSURE_PTR(X) (X) +#define FFI_RESTORE_PTR(X) (X) +#endif -ffi_status +FFI_API ffi_status ffi_prep_closure (ffi_closure*, ffi_cif *, void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data); + void *user_data) +#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 405) + __attribute__((deprecated ("use ffi_prep_closure_loc instead"))) +#elif defined(__GNUC__) && __GNUC__ >= 3 + __attribute__((deprecated)) +#endif + ; -ffi_status +FFI_API ffi_status ffi_prep_closure_loc (ffi_closure*, ffi_cif *, void (*fun)(ffi_cif*,void*,void**,void*), @@ -360,9 +376,9 @@ typedef struct { #if !FFI_NATIVE_RAW_API - /* if this is enabled, then a raw closure has the same layout - as a regular closure. We use this to install an intermediate - handler to do the transaltion, void** -> ffi_raw*. */ + /* If this is enabled, then a raw closure has the same layout + as a regular closure. We use this to install an intermediate + handler to do the transaltion, void** -> ffi_raw*. */ void (*translate_args)(ffi_cif*,void*,void**,void*); void *this_closure; @@ -386,9 +402,9 @@ typedef struct { #if !FFI_NATIVE_RAW_API - /* if this is enabled, then a raw closure has the same layout - as a regular closure. We use this to install an intermediate - handler to do the transaltion, void** -> ffi_raw*. */ + /* If this is enabled, then a raw closure has the same layout + as a regular closure. We use this to install an intermediate + handler to do the translation, void** -> ffi_raw*. */ void (*translate_args)(ffi_cif*,void*,void**,void*); void *this_closure; @@ -400,31 +416,33 @@ typedef struct { } ffi_java_raw_closure; -ffi_status +FFI_API ffi_status ffi_prep_raw_closure (ffi_raw_closure*, ffi_cif *cif, void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void *user_data); -ffi_status +FFI_API ffi_status ffi_prep_raw_closure_loc (ffi_raw_closure*, ffi_cif *cif, void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void *user_data, void *codeloc); -ffi_status +#if !FFI_NATIVE_RAW_API +FFI_API ffi_status ffi_prep_java_raw_closure (ffi_java_raw_closure*, ffi_cif *cif, void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), - void *user_data); + void *user_data) __attribute__((deprecated)); -ffi_status +FFI_API ffi_status ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*, ffi_cif *cif, void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), void *user_data, - void *codeloc); + void *codeloc) __attribute__((deprecated)); +#endif #endif /* FFI_CLOSURES */ @@ -436,22 +454,24 @@ typedef struct { void (*fun)(ffi_cif*,void*,void**,void*); } ffi_go_closure; -ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *, +FFI_API ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *, void (*fun)(ffi_cif*,void*,void**,void*)); -void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, +FFI_API void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, void *closure); #endif /* FFI_GO_CLOSURES */ /* ---- Public interface definition -------------------------------------- */ +FFI_API ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, ffi_type *rtype, ffi_type **atypes); +FFI_API ffi_status ffi_prep_cif_var(ffi_cif *cif, ffi_abi abi, unsigned int nfixedargs, @@ -459,12 +479,17 @@ ffi_status ffi_prep_cif_var(ffi_cif *cif, ffi_type *rtype, ffi_type **atypes); +FFI_API void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue); -/* Useful for eliminating compiler warnings */ +FFI_API +ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, + size_t *offsets); + +/* Useful for eliminating compiler warnings. */ #define FFI_FN(f) ((void (*)(void))f) /* ---- Definitions shared with assembly code ---------------------------- */ @@ -472,18 +497,18 @@ void ffi_call(ffi_cif *cif, #endif /* If these change, update src/mips/ffitarget.h. */ -#define FFI_TYPE_VOID 0 +#define FFI_TYPE_VOID 0 #define FFI_TYPE_INT 1 -#define FFI_TYPE_FLOAT 2 +#define FFI_TYPE_FLOAT 2 #define FFI_TYPE_DOUBLE 3 #if @HAVE_LONG_DOUBLE@ #define FFI_TYPE_LONGDOUBLE 4 #else #define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE #endif -#define FFI_TYPE_UINT8 5 +#define FFI_TYPE_UINT8 5 #define FFI_TYPE_SINT8 6 -#define FFI_TYPE_UINT16 7 +#define FFI_TYPE_UINT16 7 #define FFI_TYPE_SINT16 8 #define FFI_TYPE_UINT32 9 #define FFI_TYPE_SINT32 10 @@ -493,14 +518,8 @@ void ffi_call(ffi_cif *cif, #define FFI_TYPE_POINTER 14 #define FFI_TYPE_COMPLEX 15 -/* This should always refer to the last type code (for sanity checks) */ -/* ??? Ideally, anyway. There are assembly files that still depend - on this not including COMPLEX. */ -#ifdef FFI_TARGET_HAS_COMPLEX_TYPE -# define FFI_TYPE_LAST FFI_TYPE_COMPLEX -#else -# define FFI_TYPE_LAST FFI_TYPE_POINTER -#endif +/* This should always refer to the last type code (for sanity checks). */ +#define FFI_TYPE_LAST FFI_TYPE_COMPLEX #ifdef __cplusplus } diff --git a/libffi/include/ffi_cfi.h b/libffi/include/ffi_cfi.h index 244ce57..f4c292d 100644 --- a/libffi/include/ffi_cfi.h +++ b/libffi/include/ffi_cfi.h @@ -2,6 +2,27 @@ ffi_cfi.h - Copyright (c) 2014 Red Hat, Inc. Conditionally assemble cfi directives. Only necessary for building libffi. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the ``Software''), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ #ifndef FFI_CFI_H diff --git a/libffi/include/ffi_common.h b/libffi/include/ffi_common.h index 37f5a9e..2bd31b0 100644 --- a/libffi/include/ffi_common.h +++ b/libffi/include/ffi_common.h @@ -5,6 +5,27 @@ Common internal definitions and macros. Only necessary for building libffi. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the ``Software''), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ #ifndef FFI_COMMON_H @@ -74,14 +95,39 @@ void ffi_type_test(ffi_type *a, char *file, int line); #define FFI_ASSERT_VALID_TYPE(x) #endif -#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) -#define ALIGN_DOWN(v, a) (((size_t) (v)) & -a) +/* v cast to size_t and aligned up to a multiple of a */ +#define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) +/* v cast to size_t and aligned down to a multiple of a */ +#define FFI_ALIGN_DOWN(v, a) (((size_t) (v)) & -a) /* Perform machine dependent cif processing */ ffi_status ffi_prep_cif_machdep(ffi_cif *cif); ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, unsigned int ntotalargs); + +#if HAVE_LONG_DOUBLE_VARIANT +/* Used to adjust size/alignment of ffi types. */ +void ffi_prep_types (ffi_abi abi); +#endif + +/* Used internally, but overridden by some architectures */ +ffi_status ffi_prep_cif_core(ffi_cif *cif, + ffi_abi abi, + unsigned int isvariadic, + unsigned int nfixedargs, + unsigned int ntotalargs, + ffi_type *rtype, + ffi_type **atypes); + +/* Translate a data pointer to a code pointer. Needed for closures on + some targets. */ +void *ffi_data_to_code_pointer (void *data) FFI_HIDDEN; + +/* The arch code calls this to determine if a given closure has a + static trampoline. */ +int ffi_tramp_is_present (void *closure) FFI_HIDDEN; + /* Extended cif, used in callback from assembly routine */ typedef struct { diff --git a/libffi/include/tramp.h b/libffi/include/tramp.h new file mode 100644 index 0000000..e14e463 --- /dev/null +++ b/libffi/include/tramp.h @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- + ffi_tramp.h - Copyright (C) 2021 Microsoft, Inc. + + Static trampoline definitions. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the ``Software''), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + ----------------------------------------------------------------------- */ + +#ifndef FFI_TRAMP_H +#define FFI_TRAMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +int ffi_tramp_is_supported(void); +void *ffi_tramp_alloc (int flags); +void ffi_tramp_set_parms (void *tramp, void *data, void *code); +void *ffi_tramp_get_addr (void *tramp); +void ffi_tramp_free (void *tramp); + +#ifdef __cplusplus +} +#endif + +#endif /* FFI_TRAMP_H */ diff --git a/libffi/libffi.map.in b/libffi/libffi.map.in index 8bd27ef..de8778a 100644 --- a/libffi/libffi.map.in +++ b/libffi/libffi.map.in @@ -3,7 +3,10 @@ #include <fficonfig.h> #include <ffitarget.h> -LIBFFI_BASE_7.0 { +/* These version numbers correspond to the libtool-version abi numbers, + not to the libffi release numbers. */ + +LIBFFI_BASE_8.0 { global: /* Exported data variables. */ ffi_type_void; @@ -35,28 +38,23 @@ LIBFFI_BASE_7.0 { ffi_java_raw_to_ptrarray; ffi_java_raw_size; - /* Functions in the ffi.h header, but not exported. - These are listed here for documentation purposes only. - ffi_prep_types - ffi_prep_cif_core - */ - + ffi_get_struct_offsets; local: *; }; #ifdef FFI_TARGET_HAS_COMPLEX_TYPE -LIBFFI_COMPLEX_7.0 { +LIBFFI_COMPLEX_8.0 { global: /* Exported data variables. */ ffi_type_complex_float; ffi_type_complex_double; ffi_type_complex_longdouble; -} LIBFFI_BASE_7.0; +} LIBFFI_BASE_8.0; #endif #if FFI_CLOSURES -LIBFFI_CLOSURE_7.0 { +LIBFFI_CLOSURE_8.0 { global: ffi_closure_alloc; ffi_closure_free; @@ -66,13 +64,13 @@ LIBFFI_CLOSURE_7.0 { ffi_prep_raw_closure_loc; ffi_prep_java_raw_closure; ffi_prep_java_raw_closure_loc; -} LIBFFI_BASE_7.0; +} LIBFFI_BASE_8.0; #endif #if FFI_GO_CLOSURES -LIBFFI_GO_CLOSURE_7.0 { +LIBFFI_GO_CLOSURE_8.0 { global: ffi_call_go; ffi_prep_go_closure; -} LIBFFI_CLOSURE_7.0; +} LIBFFI_CLOSURE_8.0; #endif diff --git a/libffi/libffi.pc.in b/libffi/libffi.pc.in index edf6fde..6fad83b 100644 --- a/libffi/libffi.pc.in +++ b/libffi/libffi.pc.in @@ -2,7 +2,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ toolexeclibdir=@toolexeclibdir@ -includedir=${libdir}/@PACKAGE_NAME@-@PACKAGE_VERSION@/include +includedir=@includedir@ Name: @PACKAGE_NAME@ Description: Library supporting Foreign Function Interfaces diff --git a/libffi/libffi.xcodeproj/project.pbxproj b/libffi/libffi.xcodeproj/project.pbxproj index 1cf396f..480c4a4 100644 --- a/libffi/libffi.xcodeproj/project.pbxproj +++ b/libffi/libffi.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 43B5D3F81D35473200D1E1FD /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */; }; + 43B5D3FA1D3547CE00D1E1FD /* win64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F91D3547CE00D1E1FD /* win64_x86_64.S */; }; + 43E9A5C81D352C1500926A8F /* unix64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43E9A5C61D352C1500926A8F /* unix64_x86_64.S */; }; DBFA714A187F1D8600A76262 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; }; DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713F187F1D8600A76262 /* ffi_common.h */; }; DBFA714C187F1D8600A76262 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7140187F1D8600A76262 /* fficonfig.h */; }; @@ -23,36 +26,110 @@ DBFA7178187F1D9B00A76262 /* sysv_arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716D187F1D9B00A76262 /* sysv_arm64.S */; }; DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716F187F1D9B00A76262 /* ffi_armv7.c */; }; DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7170187F1D9B00A76262 /* sysv_armv7.S */; }; - DBFA717B187F1D9B00A76262 /* trampoline_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */; }; - DBFA717C187F1D9B00A76262 /* darwin64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */; }; - DBFA717D187F1D9B00A76262 /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7174187F1D9B00A76262 /* darwin_i386.S */; }; DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */; }; - DBFA717F187F1D9B00A76262 /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7176187F1D9B00A76262 /* ffi_i386.c */; }; - DBFA718E187F1DA100A76262 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7182187F1DA100A76262 /* ffi_i386.h */; }; DBFA718F187F1DA100A76262 /* ffi_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7183187F1DA100A76262 /* ffi_x86_64.h */; }; - DBFA7190187F1DA100A76262 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7184187F1DA100A76262 /* fficonfig_i386.h */; }; DBFA7191187F1DA100A76262 /* fficonfig_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */; }; - DBFA7192187F1DA100A76262 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7186187F1DA100A76262 /* ffitarget_i386.h */; }; DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */; }; - DBFA7194187F1DA100A76262 /* darwin64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */; }; - DBFA7195187F1DA100A76262 /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718B187F1DA100A76262 /* darwin_i386.S */; }; + DBFA7194187F1DA100A76262 /* unix64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718A187F1DA100A76262 /* unix64_x86_64.S */; }; DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */; }; - DBFA7197187F1DA100A76262 /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718D187F1DA100A76262 /* ffi_i386.c */; }; + FDB52FB31F6144FA00AA92E6 /* unix64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43E9A5C61D352C1500926A8F /* unix64_x86_64.S */; }; + FDB52FB51F6144FA00AA92E6 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */; }; + FDB52FB61F6144FA00AA92E6 /* ffi_armv7.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716F187F1D9B00A76262 /* ffi_armv7.c */; }; + FDB52FB71F6144FA00AA92E6 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; }; + FDB52FB81F6144FA00AA92E6 /* sysv_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7170187F1D9B00A76262 /* sysv_armv7.S */; }; + FDB52FB91F6144FA00AA92E6 /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */; }; + FDB52FBA1F6144FA00AA92E6 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; }; + FDB52FBC1F6144FA00AA92E6 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; }; + FDB52FBD1F6144FA00AA92E6 /* sysv_arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716D187F1D9B00A76262 /* sysv_arm64.S */; }; + FDB52FBE1F6144FA00AA92E6 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; }; + FDB52FBF1F6144FA00AA92E6 /* ffi_arm64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716C187F1D9B00A76262 /* ffi_arm64.c */; }; + FDB52FC01F6144FA00AA92E6 /* win64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F91D3547CE00D1E1FD /* win64_x86_64.S */; }; + FDB52FD01F614A8B00AA92E6 /* ffi.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; }; + FDB52FD11F614AA700AA92E6 /* ffi_arm64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA715E187F1D9B00A76262 /* ffi_arm64.h */; }; + FDB52FD21F614AAB00AA92E6 /* ffi_armv7.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA715F187F1D9B00A76262 /* ffi_armv7.h */; }; + FDB52FD41F614AB500AA92E6 /* ffi_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */; }; + FDB52FD51F614AE200AA92E6 /* ffi.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; }; + FDB52FD61F614AEA00AA92E6 /* ffi_arm64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA715E187F1D9B00A76262 /* ffi_arm64.h */; }; + FDB52FD71F614AED00AA92E6 /* ffi_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */; }; + FDB52FD81F614B8700AA92E6 /* ffitarget.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7141187F1D8600A76262 /* ffitarget.h */; }; + FDB52FD91F614B8E00AA92E6 /* ffitarget_arm64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */; }; + FDB52FDA1F614B9300AA92E6 /* ffitarget_armv7.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */; }; + FDB52FDD1F614BA900AA92E6 /* ffitarget_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */; }; + FDB52FDE1F6155E300AA92E6 /* ffitarget.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7141187F1D8600A76262 /* ffitarget.h */; }; + FDB52FDF1F6155EA00AA92E6 /* ffitarget_arm64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */; }; + FDB52FE01F6155EF00AA92E6 /* ffitarget_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */; }; + FDB52FE21F6156FA00AA92E6 /* ffi.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; }; + FDB52FE31F61571A00AA92E6 /* ffi_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7183187F1DA100A76262 /* ffi_x86_64.h */; }; + FDB52FE41F61571D00AA92E6 /* ffitarget.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7141187F1D8600A76262 /* ffitarget.h */; }; + FDB52FE61F61573100AA92E6 /* ffitarget_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */; }; + FDDB2F411F5D66E200EF414E /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = FDDB2F3F1F5D666900EF414E /* ffiw64_x86_64.c */; }; + FDDB2F461F5D691E00EF414E /* win64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = FDDB2F441F5D68C900EF414E /* win64_x86_64.S */; }; + FDDB2F4A1F5D846400EF414E /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */; }; + FDDB2F4C1F5D846400EF414E /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; }; + FDDB2F4E1F5D846400EF414E /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = FDDB2F3F1F5D666900EF414E /* ffiw64_x86_64.c */; }; + FDDB2F4F1F5D846400EF414E /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; }; + FDDB2F501F5D846400EF414E /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; }; + FDDB2F511F5D846400EF414E /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; }; + FDDB2F521F5D846400EF414E /* unix64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718A187F1DA100A76262 /* unix64_x86_64.S */; }; + FDDB2F531F5D846400EF414E /* win64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = FDDB2F441F5D68C900EF414E /* win64_x86_64.S */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ DB13B1641849DF1E0010F42D /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; + buildActionMask = 12; dstPath = "include/$(PRODUCT_NAME)"; dstSubfolderSpec = 16; files = ( + FDB52FD01F614A8B00AA92E6 /* ffi.h in CopyFiles */, + FDB52FD11F614AA700AA92E6 /* ffi_arm64.h in CopyFiles */, + FDB52FD21F614AAB00AA92E6 /* ffi_armv7.h in CopyFiles */, + FDB52FD41F614AB500AA92E6 /* ffi_x86_64.h in CopyFiles */, + FDB52FD81F614B8700AA92E6 /* ffitarget.h in CopyFiles */, + FDB52FD91F614B8E00AA92E6 /* ffitarget_arm64.h in CopyFiles */, + FDB52FDA1F614B9300AA92E6 /* ffitarget_armv7.h in CopyFiles */, + FDB52FDD1F614BA900AA92E6 /* ffitarget_x86_64.h in CopyFiles */, ); - runOnlyForDeploymentPostprocessing = 1; + runOnlyForDeploymentPostprocessing = 0; + }; + FDB52FC11F6144FA00AA92E6 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + FDB52FD51F614AE200AA92E6 /* ffi.h in CopyFiles */, + FDB52FD61F614AEA00AA92E6 /* ffi_arm64.h in CopyFiles */, + FDB52FD71F614AED00AA92E6 /* ffi_x86_64.h in CopyFiles */, + FDB52FDE1F6155E300AA92E6 /* ffitarget.h in CopyFiles */, + FDB52FDF1F6155EA00AA92E6 /* ffitarget_arm64.h in CopyFiles */, + FDB52FE01F6155EF00AA92E6 /* ffitarget_x86_64.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDB52FE11F6156E000AA92E6 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + FDB52FE21F6156FA00AA92E6 /* ffi.h in CopyFiles */, + FDB52FE31F61571A00AA92E6 /* ffi_x86_64.h in CopyFiles */, + FDB52FE41F61571D00AA92E6 /* ffitarget.h in CopyFiles */, + FDB52FE61F61573100AA92E6 /* ffitarget_x86_64.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffiw64_x86_64.c; sourceTree = "<group>"; }; + 43B5D3F91D3547CE00D1E1FD /* win64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = win64_x86_64.S; sourceTree = "<group>"; }; + 43E9A5C61D352C1500926A8F /* unix64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = unix64_x86_64.S; sourceTree = "<group>"; }; + 43E9A5DA1D35373600926A8F /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = "<group>"; }; + 43E9A5DB1D35374400926A8F /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = "<group>"; }; + 43E9A5DC1D35375400926A8F /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = "<group>"; }; + 43E9A5DD1D35375400926A8F /* internal64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal64.h; sourceTree = "<group>"; }; DB13B1661849DF1E0010F42D /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; }; DB13B1911849DF510010F42D /* ffi.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = ffi.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; DBFA713E187F1D8600A76262 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; }; @@ -66,35 +143,30 @@ DBFA7149187F1D8600A76262 /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = types.c; sourceTree = "<group>"; }; DBFA715E187F1D9B00A76262 /* ffi_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_arm64.h; sourceTree = "<group>"; }; DBFA715F187F1D9B00A76262 /* ffi_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_armv7.h; sourceTree = "<group>"; }; - DBFA7160187F1D9B00A76262 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; }; DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; }; DBFA7162187F1D9B00A76262 /* fficonfig_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_arm64.h; sourceTree = "<group>"; }; DBFA7163187F1D9B00A76262 /* fficonfig_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_armv7.h; sourceTree = "<group>"; }; - DBFA7164187F1D9B00A76262 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; }; DBFA7165187F1D9B00A76262 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; }; DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm64.h; sourceTree = "<group>"; }; DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_armv7.h; sourceTree = "<group>"; }; - DBFA7168187F1D9B00A76262 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; }; DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; }; - DBFA716C187F1D9B00A76262 /* ffi_arm64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_arm64.c; sourceTree = "<group>"; }; + DBFA716C187F1D9B00A76262 /* ffi_arm64.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = ffi_arm64.c; sourceTree = "<group>"; }; DBFA716D187F1D9B00A76262 /* sysv_arm64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_arm64.S; sourceTree = "<group>"; }; - DBFA716F187F1D9B00A76262 /* ffi_armv7.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_armv7.c; sourceTree = "<group>"; }; + DBFA716F187F1D9B00A76262 /* ffi_armv7.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = ffi_armv7.c; sourceTree = "<group>"; }; DBFA7170187F1D9B00A76262 /* sysv_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_armv7.S; sourceTree = "<group>"; }; - DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = trampoline_armv7.S; sourceTree = "<group>"; }; - DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64_x86_64.S; sourceTree = "<group>"; }; - DBFA7174187F1D9B00A76262 /* darwin_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin_i386.S; sourceTree = "<group>"; }; DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = "<group>"; }; - DBFA7176187F1D9B00A76262 /* ffi_i386.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_i386.c; sourceTree = "<group>"; }; - DBFA7182187F1DA100A76262 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; }; DBFA7183187F1DA100A76262 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; }; - DBFA7184187F1DA100A76262 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; }; DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; }; - DBFA7186187F1DA100A76262 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; }; DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; }; - DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64_x86_64.S; sourceTree = "<group>"; }; - DBFA718B187F1DA100A76262 /* darwin_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin_i386.S; sourceTree = "<group>"; }; - DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = "<group>"; }; - DBFA718D187F1DA100A76262 /* ffi_i386.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_i386.c; sourceTree = "<group>"; }; + DBFA718A187F1DA100A76262 /* unix64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = unix64_x86_64.S; sourceTree = "<group>"; }; + DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = "<group>"; }; + FDB52FC51F6144FA00AA92E6 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; }; + FDDB2F3E1F5D61BC00EF414E /* asmnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asmnames.h; sourceTree = "<group>"; }; + FDDB2F3F1F5D666900EF414E /* ffiw64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffiw64_x86_64.c; sourceTree = "<group>"; }; + FDDB2F421F5D68C900EF414E /* internal64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal64.h; sourceTree = "<group>"; }; + FDDB2F431F5D68C900EF414E /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = "<group>"; }; + FDDB2F441F5D68C900EF414E /* win64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = win64_x86_64.S; sourceTree = "<group>"; }; + FDDB2F621F5D846400EF414E /* libffi.a */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXGroup section */ @@ -113,6 +185,8 @@ children = ( DB13B1661849DF1E0010F42D /* libffi.a */, DB13B1911849DF510010F42D /* ffi.dylib */, + FDDB2F621F5D846400EF414E /* libffi.a */, + FDB52FC51F6144FA00AA92E6 /* libffi.a */, ); name = Products; sourceTree = "<group>"; @@ -123,7 +197,7 @@ DBFA713D187F1D8600A76262 /* include */, DBFA7142187F1D8600A76262 /* src */, ); - path = "darwin_common"; + path = darwin_common; sourceTree = "<group>"; }; DBFA713D187F1D8600A76262 /* include */ = { @@ -155,7 +229,7 @@ DBFA715D187F1D9B00A76262 /* include */, DBFA716A187F1D9B00A76262 /* src */, ); - path = "darwin_ios"; + path = darwin_ios; sourceTree = "<group>"; }; DBFA715D187F1D9B00A76262 /* include */ = { @@ -163,15 +237,12 @@ children = ( DBFA715E187F1D9B00A76262 /* ffi_arm64.h */, DBFA715F187F1D9B00A76262 /* ffi_armv7.h */, - DBFA7160187F1D9B00A76262 /* ffi_i386.h */, DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */, DBFA7162187F1D9B00A76262 /* fficonfig_arm64.h */, DBFA7163187F1D9B00A76262 /* fficonfig_armv7.h */, - DBFA7164187F1D9B00A76262 /* fficonfig_i386.h */, DBFA7165187F1D9B00A76262 /* fficonfig_x86_64.h */, DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */, DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */, - DBFA7168187F1D9B00A76262 /* ffitarget_i386.h */, DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */, ); path = include; @@ -190,6 +261,7 @@ DBFA716B187F1D9B00A76262 /* aarch64 */ = { isa = PBXGroup; children = ( + 43E9A5DA1D35373600926A8F /* internal.h */, DBFA716C187F1D9B00A76262 /* ffi_arm64.c */, DBFA716D187F1D9B00A76262 /* sysv_arm64.S */, ); @@ -199,9 +271,9 @@ DBFA716E187F1D9B00A76262 /* arm */ = { isa = PBXGroup; children = ( + 43E9A5DB1D35374400926A8F /* internal.h */, DBFA716F187F1D9B00A76262 /* ffi_armv7.c */, DBFA7170187F1D9B00A76262 /* sysv_armv7.S */, - DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */, ); path = arm; sourceTree = "<group>"; @@ -209,10 +281,12 @@ DBFA7172187F1D9B00A76262 /* x86 */ = { isa = PBXGroup; children = ( - DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */, - DBFA7174187F1D9B00A76262 /* darwin_i386.S */, + 43E9A5DC1D35375400926A8F /* internal.h */, + 43E9A5DD1D35375400926A8F /* internal64.h */, DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */, - DBFA7176187F1D9B00A76262 /* ffi_i386.c */, + 43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */, + 43E9A5C61D352C1500926A8F /* unix64_x86_64.S */, + 43B5D3F91D3547CE00D1E1FD /* win64_x86_64.S */, ); path = x86; sourceTree = "<group>"; @@ -223,17 +297,14 @@ DBFA7181187F1DA100A76262 /* include */, DBFA7188187F1DA100A76262 /* src */, ); - path = "darwin_osx"; + path = darwin_osx; sourceTree = "<group>"; }; DBFA7181187F1DA100A76262 /* include */ = { isa = PBXGroup; children = ( - DBFA7182187F1DA100A76262 /* ffi_i386.h */, DBFA7183187F1DA100A76262 /* ffi_x86_64.h */, - DBFA7184187F1DA100A76262 /* fficonfig_i386.h */, DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */, - DBFA7186187F1DA100A76262 /* ffitarget_i386.h */, DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */, ); path = include; @@ -250,10 +321,13 @@ DBFA7189187F1DA100A76262 /* x86 */ = { isa = PBXGroup; children = ( - DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */, - DBFA718B187F1DA100A76262 /* darwin_i386.S */, + FDDB2F431F5D68C900EF414E /* internal.h */, + FDDB2F421F5D68C900EF414E /* internal64.h */, + FDDB2F3E1F5D61BC00EF414E /* asmnames.h */, DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */, - DBFA718D187F1DA100A76262 /* ffi_i386.c */, + FDDB2F3F1F5D666900EF414E /* ffiw64_x86_64.c */, + DBFA718A187F1DA100A76262 /* unix64_x86_64.S */, + FDDB2F441F5D68C900EF414E /* win64_x86_64.S */, ); path = x86; sourceTree = "<group>"; @@ -270,11 +344,8 @@ DBFA714A187F1D8600A76262 /* ffi.h in Headers */, DBFA718F187F1DA100A76262 /* ffi_x86_64.h in Headers */, DBFA7191187F1DA100A76262 /* fficonfig_x86_64.h in Headers */, - DBFA718E187F1DA100A76262 /* ffi_i386.h in Headers */, - DBFA7190187F1DA100A76262 /* fficonfig_i386.h in Headers */, DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */, DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */, - DBFA7192187F1DA100A76262 /* ffitarget_i386.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -285,7 +356,7 @@ isa = PBXNativeTarget; buildConfigurationList = DB13B18B1849DF1E0010F42D /* Build configuration list for PBXNativeTarget "libffi-iOS" */; buildPhases = ( - DB13B3051849E01C0010F42D /* ShellScript */, + 43B5D3FB1D35480D00D1E1FD /* Run Script */, DB13B1621849DF1E0010F42D /* Sources */, DB13B1641849DF1E0010F42D /* CopyFiles */, ); @@ -315,13 +386,47 @@ productReference = DB13B1911849DF510010F42D /* ffi.dylib */; productType = "com.apple.product-type.library.dynamic"; }; + FDB52FB01F6144FA00AA92E6 /* libffi-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDB52FC21F6144FA00AA92E6 /* Build configuration list for PBXNativeTarget "libffi-tvOS" */; + buildPhases = ( + FDB52FB11F6144FA00AA92E6 /* Run Script */, + FDB52FB21F6144FA00AA92E6 /* Sources */, + FDB52FC11F6144FA00AA92E6 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "libffi-tvOS"; + productName = ffi; + productReference = FDB52FC51F6144FA00AA92E6 /* libffi.a */; + productType = "com.apple.product-type.library.static"; + }; + FDDB2F471F5D846400EF414E /* libffi-static-Mac */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDDB2F5F1F5D846400EF414E /* Build configuration list for PBXNativeTarget "libffi-static-Mac" */; + buildPhases = ( + FDDB2F481F5D846400EF414E /* ShellScript */, + FDDB2F491F5D846400EF414E /* Sources */, + FDB52FE11F6156E000AA92E6 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "libffi-static-Mac"; + productName = ffi; + productReference = FDDB2F621F5D846400EF414E /* libffi.a */; + productType = "com.apple.product-type.library.dynamic"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ DB13B15C1849DEB70010F42D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0510; + LastUpgradeCheck = 0830; }; buildConfigurationList = DB13B15F1849DEB70010F42D /* Build configuration list for PBXProject "libffi" */; compatibilityVersion = "Xcode 3.2"; @@ -336,24 +441,27 @@ projectRoot = ""; targets = ( DB13B1651849DF1E0010F42D /* libffi-iOS */, + FDB52FB01F6144FA00AA92E6 /* libffi-tvOS */, DB13B1901849DF510010F42D /* libffi-Mac */, + FDDB2F471F5D846400EF414E /* libffi-static-Mac */, ); }; /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ - DB13B3051849E01C0010F42D /* ShellScript */ = { + 43B5D3FB1D35480D00D1E1FD /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); + name = "Run Script"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/usr/bin/python generate-darwin-source-and-headers.py --only-ios"; + shellScript = "if [ ! -f \"./compile\" ]\nthen\nautoreconf -i -f -v\nif [ -f \"../ltmain.sh\" ]\nthen\necho \"fixing ltmain.sh for some reason\"\nmv ../ltmain.sh ./\nautoreconf -i -f -v\nfi\n/usr/bin/python generate-darwin-source-and-headers.py --only-ios\nfi"; }; DB13B3061849E0490010F42D /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -366,7 +474,34 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/usr/bin/python generate-darwin-source-and-headers.py --only-osx"; + shellScript = "if [ ! -f \"./compile\" ]\nthen\nautoreconf -i -f -v\nif [ -f \"../ltmain.sh\" ]\nthen\necho \"fixing ltmain.sh for some reason\"\nmv ../ltmain.sh ./\nautoreconf -i -f -v\nfi\n/usr/bin/python generate-darwin-source-and-headers.py --only-osx\nfi"; + }; + FDB52FB11F6144FA00AA92E6 /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ ! -f \"./compile\" ]\nthen\nautoreconf -i -f -v\nif [ -f \"../ltmain.sh\" ]\nthen\necho \"fixing ltmain.sh for some reason\"\nmv ../ltmain.sh ./\nautoreconf -i -f -v\nfi\n/usr/bin/python generate-darwin-source-and-headers.py --only-ios\nfi"; + }; + FDDB2F481F5D846400EF414E /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ ! -f \"./compile\" ]\nthen\nautoreconf -i -f -v\nif [ -f \"../ltmain.sh\" ]\nthen\necho \"fixing ltmain.sh for some reason\"\nmv ../ltmain.sh ./\nautoreconf -i -f -v\nfi\n/usr/bin/python generate-darwin-source-and-headers.py --only-osx\nfi"; }; /* End PBXShellScriptBuildPhase section */ @@ -375,19 +510,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 43E9A5C81D352C1500926A8F /* unix64_x86_64.S in Sources */, DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */, DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */, - DBFA717B187F1D9B00A76262 /* trampoline_armv7.S in Sources */, DBFA714E187F1D8600A76262 /* closures.c in Sources */, DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */, - DBFA717D187F1D9B00A76262 /* darwin_i386.S in Sources */, + 43B5D3F81D35473200D1E1FD /* ffiw64_x86_64.c in Sources */, DBFA7156187F1D8600A76262 /* prep_cif.c in Sources */, - DBFA717F187F1D9B00A76262 /* ffi_i386.c in Sources */, DBFA7158187F1D8600A76262 /* raw_api.c in Sources */, DBFA7178187F1D9B00A76262 /* sysv_arm64.S in Sources */, - DBFA717C187F1D9B00A76262 /* darwin64_x86_64.S in Sources */, DBFA715A187F1D8600A76262 /* types.c in Sources */, DBFA7177187F1D9B00A76262 /* ffi_arm64.c in Sources */, + 43B5D3FA1D3547CE00D1E1FD /* win64_x86_64.S in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -396,13 +530,47 @@ buildActionMask = 2147483647; files = ( DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */, - DBFA7195187F1DA100A76262 /* darwin_i386.S in Sources */, DBFA7157187F1D8600A76262 /* prep_cif.c in Sources */, - DBFA7197187F1DA100A76262 /* ffi_i386.c in Sources */, + FDDB2F411F5D66E200EF414E /* ffiw64_x86_64.c in Sources */, DBFA715B187F1D8600A76262 /* types.c in Sources */, DBFA7159187F1D8600A76262 /* raw_api.c in Sources */, DBFA714F187F1D8600A76262 /* closures.c in Sources */, - DBFA7194187F1DA100A76262 /* darwin64_x86_64.S in Sources */, + DBFA7194187F1DA100A76262 /* unix64_x86_64.S in Sources */, + FDDB2F461F5D691E00EF414E /* win64_x86_64.S in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDB52FB21F6144FA00AA92E6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDB52FB31F6144FA00AA92E6 /* unix64_x86_64.S in Sources */, + FDB52FB51F6144FA00AA92E6 /* ffi64_x86_64.c in Sources */, + FDB52FB61F6144FA00AA92E6 /* ffi_armv7.c in Sources */, + FDB52FB71F6144FA00AA92E6 /* closures.c in Sources */, + FDB52FB81F6144FA00AA92E6 /* sysv_armv7.S in Sources */, + FDB52FB91F6144FA00AA92E6 /* ffiw64_x86_64.c in Sources */, + FDB52FBA1F6144FA00AA92E6 /* prep_cif.c in Sources */, + FDB52FBC1F6144FA00AA92E6 /* raw_api.c in Sources */, + FDB52FBD1F6144FA00AA92E6 /* sysv_arm64.S in Sources */, + FDB52FBE1F6144FA00AA92E6 /* types.c in Sources */, + FDB52FBF1F6144FA00AA92E6 /* ffi_arm64.c in Sources */, + FDB52FC01F6144FA00AA92E6 /* win64_x86_64.S in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDDB2F491F5D846400EF414E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDDB2F4A1F5D846400EF414E /* ffi64_x86_64.c in Sources */, + FDDB2F4C1F5D846400EF414E /* prep_cif.c in Sources */, + FDDB2F4E1F5D846400EF414E /* ffiw64_x86_64.c in Sources */, + FDDB2F4F1F5D846400EF414E /* types.c in Sources */, + FDDB2F501F5D846400EF414E /* raw_api.c in Sources */, + FDDB2F511F5D846400EF414E /* closures.c in Sources */, + FDDB2F521F5D846400EF414E /* unix64_x86_64.S in Sources */, + FDDB2F531F5D846400EF414E /* win64_x86_64.S in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -412,9 +580,27 @@ DB13B1601849DEB70010F42D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", - "darwin_common/include", + darwin_common/include, ); ONLY_ACTIVE_ARCH = YES; }; @@ -423,9 +609,26 @@ DB13B1611849DEB70010F42D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", - "darwin_common/include", + darwin_common/include, ); }; name = Release; @@ -434,11 +637,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -449,14 +647,11 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DSTROOT = /tmp/ffi.dst; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -465,14 +660,13 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", - "darwin_ios/include", + darwin_ios/include, ); - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - "IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0; - OTHER_LDFLAGS = "-ObjC"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; PRODUCT_NAME = ffi; SDKROOT = iphoneos; SKIP_INSTALL = YES; + VALID_ARCHS = "arm64 armv7 armv7s x86_64"; }; name = Debug; }; @@ -480,11 +674,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -496,7 +685,6 @@ COPY_PHASE_STRIP = YES; DSTROOT = /tmp/ffi.dst; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -505,15 +693,14 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", - "darwin_ios/include", + darwin_ios/include, ); - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - "IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0; - OTHER_LDFLAGS = "-ObjC"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; PRODUCT_NAME = ffi; SDKROOT = iphoneos; SKIP_INSTALL = YES; VALIDATE_PRODUCT = YES; + VALID_ARCHS = "arm64 armv7 armv7s x86_64"; }; name = Release; }; @@ -532,6 +719,7 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -552,7 +740,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", - "darwin_osx/include", + darwin_osx/include, ); MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; @@ -577,6 +765,7 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; @@ -592,7 +781,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", - "darwin_osx/include", + darwin_osx/include, ); MACOSX_DEPLOYMENT_TARGET = 10.6; OTHER_LDFLAGS = "-Wl,-no_compact_unwind"; @@ -601,6 +790,159 @@ }; name = Release; }; + FDB52FC31F6144FA00AA92E6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + darwin_ios/include, + ); + PRODUCT_NAME = ffi; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + FDB52FC41F6144FA00AA92E6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + darwin_ios/include, + ); + PRODUCT_NAME = ffi; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + FDDB2F601F5D846400EF414E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + EXECUTABLE_EXTENSION = a; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + darwin_osx/include, + ); + MACH_O_TYPE = staticlib; + MACOSX_DEPLOYMENT_TARGET = 10.6; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = ffi; + SDKROOT = macosx; + }; + name = Debug; + }; + FDDB2F611F5D846400EF414E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + EXECUTABLE_EXTENSION = a; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + darwin_osx/include, + ); + MACH_O_TYPE = staticlib; + MACOSX_DEPLOYMENT_TARGET = 10.6; + PRODUCT_NAME = ffi; + SDKROOT = macosx; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -631,6 +973,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + FDB52FC21F6144FA00AA92E6 /* Build configuration list for PBXNativeTarget "libffi-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDB52FC31F6144FA00AA92E6 /* Debug */, + FDB52FC41F6144FA00AA92E6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FDDB2F5F1F5D846400EF414E /* Build configuration list for PBXNativeTarget "libffi-static-Mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDDB2F601F5D846400EF414E /* Debug */, + FDDB2F611F5D846400EF414E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = DB13B15C1849DEB70010F42D /* Project object */; diff --git a/libffi/libtool-version b/libffi/libtool-version index dfb8b11..607fee5 100644 --- a/libffi/libtool-version +++ b/libffi/libtool-version @@ -2,5 +2,28 @@ # the libtool manual to understand the meaning of the fields. This is # a separate file so that version updates don't involve re-running # automake. +# +# Here are a set of rules to help you update your library version +# information: +# +# 1. Start with version information of `0:0:0' for each libtool library. +# +# 2. Update the version information only immediately before a public +# release of your software. More frequent updates are unnecessary, +# and only guarantee that the current interface number gets larger +# faster. +# +# 3. If the library source code has changed at all since the last +# update, then increment revision (`c:r:a' becomes `c:r+1:a'). +# +# 4. If any interfaces have been added, removed, or changed since the +# last update, increment current, and set revision to 0. +# +# 5. If any interfaces have been added since the last public release, +# then increment age. +# +# 6. If any interfaces have been removed since the last public +# release, then set age to 0. +# # CURRENT:REVISION:AGE -7:0:0 +9:0:1 diff --git a/libffi/man/Makefile.in b/libffi/man/Makefile.in index 7546910..8dbe52f 100644 --- a/libffi/man/Makefile.in +++ b/libffi/man/Makefile.in @@ -228,6 +228,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ +READELF = @READELF@ SECTION_LDFLAGS = @SECTION_LDFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ diff --git a/libffi/mdate-sh b/libffi/mdate-sh index e631b22..f80075c 100644..100755 --- a/libffi/mdate-sh +++ b/libffi/mdate-sh @@ -1,10 +1,9 @@ #!/bin/sh # Get modification time of a file or directory and pretty-print it. -scriptversion=2009-04-28.21; # UTC +scriptversion=2016-01-11.22; # UTC -# Copyright (C) 1995, 1996, 1997, 2003, 2004, 2005, 2007, 2009 Free -# Software Foundation, Inc. +# Copyright (C) 1995-2017 Free Software Foundation, Inc. # written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995 # # This program is free software; you can redistribute it and/or modify @@ -29,16 +28,26 @@ scriptversion=2009-04-28.21; # UTC # bugs to <bug-automake@gnu.org> or send patches to # <automake-patches@gnu.org>. +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +fi + case $1 in '') - echo "$0: No file. Try \`$0 --help' for more information." 1>&2 + echo "$0: No file. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: mdate-sh [--help] [--version] FILE -Pretty-print the modification time of FILE. +Pretty-print the modification day of FILE, in the format: +1 January 1970 Report bugs to <bug-automake@gnu.org>. EOF @@ -50,6 +59,13 @@ EOF ;; esac +error () +{ + echo "$0: $1" >&2 + exit 1 +} + + # Prevent date giving response in another language. LANG=C export LANG @@ -59,7 +75,7 @@ LC_TIME=C export LC_TIME # GNU ls changes its time format in response to the TIME_STYLE -# variable. Since we cannot assume `unset' works, revert this +# variable. Since we cannot assume 'unset' works, revert this # variable to its documented default. if test "${TIME_STYLE+set}" = set; then TIME_STYLE=posix-long-iso @@ -79,14 +95,14 @@ if ls -n /dev/null 1>/dev/null 2>&1; then ls_command="$ls_command -n" fi -# A `ls -l' line looks as follows on OS/2. +# A 'ls -l' line looks as follows on OS/2. # drwxrwx--- 0 Aug 11 2001 foo # This differs from Unix, which adds ownership information. # drwxrwx--- 2 root root 4096 Aug 11 2001 foo # # To find the date, we split the line on spaces and iterate on words # until we find a month. This cannot work with files whose owner is a -# user named `Jan', or `Feb', etc. However, it's unlikely that `/' +# user named "Jan", or "Feb", etc. However, it's unlikely that '/' # will be owned by a user whose name is a month. So we first look at # the extended ls output of the root directory to decide how many # words should be skipped to get the date. @@ -99,6 +115,7 @@ month= command= until test $month do + test $# -gt 0 || error "failed parsing '$ls_command /' output" shift # Add another shift to the command. command="$command shift;" @@ -118,8 +135,10 @@ do esac done +test -n "$month" || error "failed parsing '$ls_command /' output" + # Get the extended ls output of the file or directory. -set dummy x`eval "$ls_command \"\$save_arg1\""` +set dummy x`eval "$ls_command \"\\\$save_arg1\""` # Remove all preceding arguments eval $command @@ -200,6 +219,6 @@ echo $day $month $year # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/libffi/merge.sh b/libffi/merge.sh new file mode 100755 index 0000000..b36fbb9 --- /dev/null +++ b/libffi/merge.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# FIXME: do we need a license (or whatever else) header here? + +# This script merges libffi sources from upstream. + +# Default to the tip of master branch. +commit=${1-master} + +fatal() { + echo "$1" + exit 1; +} + +get_upstream() { + rm -rf upstream + git clone https://github.com/libffi/libffi.git upstream + pushd upstream + git checkout $commit || fatal "Failed to checkout $commit" + popd +} + +get_current_rev() { + cd upstream + git rev-parse HEAD +} + +pwd | grep 'libffi$' || \ + fatal "Run this script from the libffi directory" +get_upstream +CUR_REV=$(get_current_rev) +echo Current upstream revision: $CUR_REV + +# Remove the unused files. +pushd upstream +rm -rf ChangeLog.old .appveyor* .ci .github .gitignore .travis* \ + config.guess config.sub libtool-ldflags m4 make_sunver.pl \ + msvc_build +rm -rf .git autogen.sh +cp -a . .. +popd + +rm -rf upstream + +# Update the MERGE file. +cat << EOF > MERGE +$CUR_REV + +The first line of this file holds the git revision number of the +last merge done from the master library sources. +EOF diff --git a/libffi/msvcc.sh b/libffi/msvcc.sh index 65fbfef..301e2fb 100755 --- a/libffi/msvcc.sh +++ b/libffi/msvcc.sh @@ -44,17 +44,29 @@ args_orig=$@ args="-nologo -W3" +linkargs= static_crt= debug_crt= cl="cl" ml="ml" safeseh="-safeseh" output= +libpaths= +libversion=8 +verbose= while [ $# -gt 0 ] do case $1 in + --verbose) + verbose=1 + shift 1 + ;; + --version) + args="-help" + shift 1 + ;; -fexceptions) # Don't enable exceptions for now. #args="$args -EHac" @@ -68,9 +80,18 @@ do safeseh= shift 1 ;; + -marm) + ml='armasm' + safeseh= + shift 1 + ;; + -marm64) + ml='armasm64' + safeseh= + shift 1 + ;; -clang-cl) cl="clang-cl" - safeseh= shift 1 ;; -O0) @@ -144,13 +165,44 @@ do shift 1 ;; -I) - args="$args -I$2" - includes="$includes -I$2" + p=$(cygpath -ma "$2") + args="$args -I\"$p\"" + includes="$includes -I\"$p\"" shift 2 ;; -I*) - args="$args $1" - includes="$includes $1" + p=$(cygpath -ma "${1#-I}") + args="$args -I\"$p\"" + includes="$includes -I\"$p\"" + shift 1 + ;; + -L) + p=$(cygpath -ma $2) + linkargs="$linkargs -LIBPATH:$p" + shift 2 + ;; + -L*) + p=$(cygpath -ma ${1#-L}) + linkargs="$linkargs -LIBPATH:$p" + shift 1 + ;; + -link) + # add next argument verbatim to linker args + linkargs="$linkargs $2" + shift 2 + ;; + -l*) + case $1 + in + -lffi) + linkargs="$linkargs lib${1#-l}-${libversion}.lib" + ;; + *) + # ignore other libraries like -lm, hope they are + # covered by MSVCRT + # linkargs="$linkargs ${1#-l}.lib" + ;; + esac shift 1 ;; -W|-Wextra) @@ -166,6 +218,15 @@ do # libffi tests -pedantic with -Wall, so drop it also. shift 1 ;; + -warn) + # ignore -warn all from libtool as well. + if test "$2" = "all"; then + shift 2 + else + args="$args -warn" + shift 1 + fi + ;; -Werror) args="$args -WX" shift 1 @@ -186,6 +247,7 @@ do else output="-Fe$2" fi + armasm_output="-o $2" if [ -n "$assembly" ]; then args="$args $output" else @@ -194,12 +256,12 @@ do shift 2 ;; *.S) - src=$1 + src="$(cygpath -ma $1)" assembly="true" shift 1 ;; *.c) - args="$args $1" + args="$args $(cygpath -ma $1)" shift 1 ;; *) @@ -210,11 +272,16 @@ do esac done -# If -Zi is specified, certain optimizations are implicitly disabled -# by MSVC. Add back those optimizations if this is an optimized build. -# NOTE: These arguments must come after all others. -if [ -n "$opt" ]; then - args="$args -link -OPT:REF -OPT:ICF -INCREMENTAL:NO" +if [ -n "$linkargs" ]; then + + # If -Zi is specified, certain optimizations are implicitly disabled + # by MSVC. Add back those optimizations if this is an optimized build. + # NOTE: These arguments must come after all others. + if [ -n "$opt" ]; then + linkargs="$linkargs -OPT:REF -OPT:ICF -INCREMENTAL:NO" + fi + + args="$args -link $linkargs" fi if [ -n "$static_crt" ]; then @@ -232,12 +299,33 @@ if [ -n "$assembly" ]; then outdir="." fi ppsrc="$outdir/$(basename $src|sed 's/.S$/.asm/g')" - echo "$cl -nologo -EP $includes $defines $src > $ppsrc" - "$cl" -nologo -EP $includes $defines $src > $ppsrc || exit $? + + if [ $ml = "armasm" ]; then + defines="$defines -D_M_ARM" + fi + + if [ $ml = "armasm64" ]; then + defines="$defines -D_M_ARM64" + fi + + if test -n "$verbose"; then + echo "$cl -nologo -EP $includes $defines $src > $ppsrc" + fi + + eval "\"$cl\" -nologo -EP $includes $defines $src" > $ppsrc || exit $? output="$(echo $output | sed 's%/F[dpa][^ ]*%%g')" - args="-nologo $safeseh $single $output $ppsrc" + if [ $ml = "armasm" ]; then + args="-nologo -g -oldit $armasm_output $ppsrc -errorReport:prompt" + elif [ $ml = "armasm64" ]; then + args="-nologo -g $armasm_output $ppsrc -errorReport:prompt" + else + args="-nologo $safeseh $single $output $ppsrc" + fi + + if test -n "$verbose"; then + echo "$ml $args" + fi - echo "$ml $args" eval "\"$ml\" $args" result=$? @@ -245,13 +333,21 @@ if [ -n "$assembly" ]; then #mv *.obj $outdir else args="$md $args" - echo "$cl $args" + + if test -n "$verbose"; then + echo "$cl $args" + fi # Return an error code of 1 if an invalid command line parameter is passed - # instead of just ignoring it. + # instead of just ignoring it. Any output that is not a warning or an + # error is filtered so this command behaves more like gcc. cl.exe prints + # the name of the compiled file otherwise, which breaks the dejagnu checks + # for excess warnings and errors. eval "(\"$cl\" $args 2>&1 1>&3 | \ - awk '{print \$0} /D9002/ {error=1} END{exit error}' >&2) 3>&1" + awk '{print \$0} /D9002/ {error=1} END{exit error}' >&2) 3>&1 | \ + awk '/warning|error/'" result=$? fi exit $result +# vim: noai:ts=4:sw=4 diff --git a/libffi/src/aarch64/ffi.c b/libffi/src/aarch64/ffi.c index f79602b..5c85fcd 100644 --- a/libffi/src/aarch64/ffi.c +++ b/libffi/src/aarch64/ffi.c @@ -19,12 +19,18 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#if defined(__aarch64__) || defined(__arm64__)|| defined (_M_ARM64) #include <stdio.h> #include <stdlib.h> #include <stdint.h> +#include <fficonfig.h> #include <ffi.h> #include <ffi_common.h> #include "internal.h" +#ifdef _WIN32 +#include <windows.h> /* FlushInstructionCache */ +#endif +#include <tramp.h> /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE; all further uses in this file will refer to the 128-bit type. */ @@ -54,6 +60,17 @@ struct call_context UINT64 x[N_X_ARG_REG]; }; +#if FFI_EXEC_TRAMPOLINE_TABLE + +#ifdef __MACH__ +#ifdef HAVE_PTRAUTH +#include <ptrauth.h> +#endif +#include <mach/vm_param.h> +#endif + +#else + #if defined (__clang__) && defined (__APPLE__) extern void sys_icache_invalidate (void *start, size_t len); #endif @@ -65,11 +82,15 @@ ffi_clear_cache (void *start, void *end) sys_icache_invalidate (start, (char *)end - (char *)start); #elif defined (__GNUC__) __builtin___clear_cache (start, end); +#elif defined (_WIN32) + FlushInstructionCache(GetCurrentProcess(), start, (char*)end - (char*)start); #else #error "Missing builtin to flush instruction cache" #endif } +#endif + /* A subroutine of is_vfp_type. Given a structure type, return the type code of the first non-structure element. Recurse for structure elements. Return -1 if the structure is in fact empty, i.e. no nested elements. */ @@ -220,7 +241,7 @@ is_vfp_type (const ffi_type *ty) /* All tests succeeded. Encode the result. */ done: - return candidate * 4 + (4 - ele_count); + return candidate * 4 + (4 - (int)ele_count); } /* Representation of the procedure call argument marshalling @@ -269,7 +290,7 @@ allocate_to_stack (struct arg_state *state, void *stack, alignment = 8; #endif - nsaa = ALIGN (nsaa, alignment); + nsaa = FFI_ALIGN (nsaa, alignment); state->nsaa = nsaa + size; return (char *)stack + nsaa; @@ -304,10 +325,13 @@ extend_integer_type (void *source, int type) } } +#if defined(_MSC_VER) +void extend_hfa_type (void *dest, void *src, int h); +#else static void extend_hfa_type (void *dest, void *src, int h) { - int f = h - AARCH64_RET_S4; + ssize_t f = h - AARCH64_RET_S4; void *x0; asm volatile ( @@ -339,10 +363,10 @@ extend_hfa_type (void *dest, void *src, int h) " b 1f\n" " nop\n" " ldp q16, q17, [%3]\n" /* Q4 */ -" ldp q18, q19, [%3, #16]\n" +" ldp q18, q19, [%3, #32]\n" " b 4f\n" " ldp q16, q17, [%3]\n" /* Q3 */ -" ldr q18, [%3, #16]\n" +" ldr q18, [%3, #32]\n" " b 3f\n" " ldp q16, q17, [%3]\n" /* Q2 */ " b 2f\n" @@ -357,7 +381,11 @@ extend_hfa_type (void *dest, void *src, int h) : "r"(f * 12), "r"(dest), "r"(src) : "memory", "v16", "v17", "v18", "v19"); } +#endif +#if defined(_MSC_VER) +void* compress_hfa_type (void *dest, void *src, int h); +#else static void * compress_hfa_type (void *dest, void *reg, int h) { @@ -426,6 +454,7 @@ compress_hfa_type (void *dest, void *reg, int h) } return dest; } +#endif /* Either allocate an appropriate register for the argument type, or if none are available, allocate a stack slot and return a pointer @@ -443,7 +472,7 @@ allocate_int_to_reg_or_stack (struct call_context *context, return allocate_to_stack (state, stack, size, size); } -ffi_status +ffi_status FFI_HIDDEN ffi_prep_cif_machdep (ffi_cif *cif) { ffi_type *rtype = cif->rtype; @@ -517,7 +546,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) } /* Round the stack up to a multiple of the stack alignment requirement. */ - cif->bytes = ALIGN(bytes, 16); + cif->bytes = (unsigned) FFI_ALIGN(bytes, 16); cif->flags = flags; #if defined (__APPLE__) cif->aarch64_nfixedargs = 0; @@ -528,14 +557,22 @@ ffi_prep_cif_machdep (ffi_cif *cif) #if defined (__APPLE__) /* Perform Apple-specific cif processing for variadic calls */ -ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, - unsigned int nfixedargs, - unsigned int ntotalargs) +ffi_status FFI_HIDDEN +ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, + unsigned int ntotalargs) { ffi_status status = ffi_prep_cif_machdep (cif); cif->aarch64_nfixedargs = nfixedargs; return status; } +#else +ffi_status FFI_HIDDEN +ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, unsigned int ntotalargs) +{ + ffi_status status = ffi_prep_cif_machdep (cif); + cif->flags |= AARCH64_FLAG_VARARG; + return status; +} #endif /* __APPLE__ */ extern void ffi_call_SYSV (struct call_context *context, void *frame, @@ -552,7 +589,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, void *stack, *frame, *rvalue; struct arg_state state; size_t stack_bytes, rtype_size, rsize; - int i, nargs, flags; + int i, nargs, flags, isvariadic = 0; ffi_type *rtype; flags = cif->flags; @@ -560,6 +597,12 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, rtype_size = rtype->size; stack_bytes = cif->bytes; + if (flags & AARCH64_FLAG_VARARG) + { + isvariadic = 1; + flags &= ~AARCH64_FLAG_VARARG; + } + /* If the target function returns a structure via hidden pointer, then we cannot allow a null rvalue. Otherwise, mash a null rvalue to void return type. */ @@ -574,11 +617,12 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, else if (flags & AARCH64_RET_NEED_COPY) rsize = 16; - /* Allocate consectutive stack for everything we'll need. */ - context = alloca (sizeof(struct call_context) + stack_bytes + 32 + rsize); + /* Allocate consectutive stack for everything we'll need. + The frame uses 40 bytes for: lr, fp, rvalue, flags, sp */ + context = alloca (sizeof(struct call_context) + stack_bytes + 40 + rsize); stack = context + 1; - frame = stack + stack_bytes; - rvalue = (rsize ? frame + 32 : orig_rvalue); + frame = (void*)((uintptr_t)stack + (uintptr_t)stack_bytes); + rvalue = (rsize ? (void*)((uintptr_t)frame + 40) : orig_rvalue); arg_init (&state); for (i = 0, nargs = cif->nargs; i < nargs; i++) @@ -639,16 +683,31 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, h = is_vfp_type (ty); if (h) { - int elems = 4 - (h & 3); - if (state.nsrn + elems <= N_V_ARG_REG) - { - dest = &context->v[state.nsrn]; - state.nsrn += elems; - extend_hfa_type (dest, a, h); - break; - } - state.nsrn = N_V_ARG_REG; - dest = allocate_to_stack (&state, stack, ty->alignment, s); + int elems = 4 - (h & 3); + if (cif->abi == FFI_WIN64 && isvariadic) + { + if (state.ngrn + elems <= N_X_ARG_REG) + { + dest = &context->x[state.ngrn]; + state.ngrn += elems; + extend_hfa_type(dest, a, h); + break; + } + state.nsrn = N_X_ARG_REG; + dest = allocate_to_stack(&state, stack, ty->alignment, s); + } + else + { + if (state.nsrn + elems <= N_V_ARG_REG) + { + dest = &context->v[state.nsrn]; + state.nsrn += elems; + extend_hfa_type (dest, a, h); + break; + } + state.nsrn = N_V_ARG_REG; + dest = allocate_to_stack (&state, stack, ty->alignment, s); + } } else if (s > 16) { @@ -657,6 +716,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, the argument is replaced by a pointer to the copy. */ a = &avalue[i]; t = FFI_TYPE_POINTER; + s = sizeof (void *); goto do_pointer; } else @@ -669,7 +729,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, X registers, then the argument is copied into consecutive X registers. */ dest = &context->x[state.ngrn]; - state.ngrn += n; + state.ngrn += (unsigned int)n; } else { @@ -711,6 +771,8 @@ ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue) ffi_call_int (cif, fn, rvalue, avalue, NULL); } +#if FFI_CLOSURES + #ifdef FFI_GO_CLOSURES void ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, @@ -724,239 +786,9 @@ ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, extern void ffi_closure_SYSV (void) FFI_HIDDEN; extern void ffi_closure_SYSV_V (void) FFI_HIDDEN; - -#if FFI_EXEC_TRAMPOLINE_TABLE - -#include <mach/mach.h> -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> - -extern void *ffi_closure_trampoline_table_page; - -typedef struct ffi_trampoline_table ffi_trampoline_table; -typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry; - -struct ffi_trampoline_table -{ - /* contiguous writable and executable pages */ - vm_address_t config_page; - vm_address_t trampoline_page; - - /* free list tracking */ - uint16_t free_count; - ffi_trampoline_table_entry *free_list; - ffi_trampoline_table_entry *free_list_pool; - - ffi_trampoline_table *prev; - ffi_trampoline_table *next; -}; - -struct ffi_trampoline_table_entry -{ - void *(*trampoline) (); - ffi_trampoline_table_entry *next; -}; - -/* The trampoline configuration is placed a page prior to the trampoline's entry point */ -#define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - PAGE_SIZE)); - -/* Total number of trampolines that fit in one trampoline table */ -#define FFI_TRAMPOLINE_COUNT (PAGE_SIZE / FFI_TRAMPOLINE_SIZE) - -static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER; -static ffi_trampoline_table *ffi_trampoline_tables = NULL; - -static ffi_trampoline_table * -ffi_trampoline_table_alloc () -{ - ffi_trampoline_table *table = NULL; - - /* Loop until we can allocate two contiguous pages */ - while (table == NULL) - { - vm_address_t config_page = 0x0; - kern_return_t kt; - - /* Try to allocate two pages */ - kt = - vm_allocate (mach_task_self (), &config_page, PAGE_SIZE * 2, - VM_FLAGS_ANYWHERE); - if (kt != KERN_SUCCESS) - { - fprintf (stderr, "vm_allocate() failure: %d at %s:%d\n", kt, - __FILE__, __LINE__); - break; - } - - /* Now drop the second half of the allocation to make room for the trampoline table */ - vm_address_t trampoline_page = config_page + PAGE_SIZE; - kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE); - if (kt != KERN_SUCCESS) - { - fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, - __FILE__, __LINE__); - break; - } - - /* Remap the trampoline table to directly follow the config page */ - vm_prot_t cur_prot; - vm_prot_t max_prot; - - kt = - vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE, - mach_task_self (), - (vm_address_t) & ffi_closure_trampoline_table_page, FALSE, - &cur_prot, &max_prot, VM_INHERIT_SHARE); - - /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */ - if (kt != KERN_SUCCESS) - { - /* Log unexpected failures */ - if (kt != KERN_NO_SPACE) - { - fprintf (stderr, "vm_remap() failure: %d at %s:%d\n", kt, - __FILE__, __LINE__); - } - - vm_deallocate (mach_task_self (), config_page, PAGE_SIZE); - continue; - } - - /* We have valid trampoline and config pages */ - table = calloc (1, sizeof (ffi_trampoline_table)); - table->free_count = FFI_TRAMPOLINE_COUNT; - table->config_page = config_page; - table->trampoline_page = trampoline_page; - - /* Create and initialize the free list */ - table->free_list_pool = - calloc (FFI_TRAMPOLINE_COUNT, sizeof (ffi_trampoline_table_entry)); - - uint16_t i; - for (i = 0; i < table->free_count; i++) - { - ffi_trampoline_table_entry *entry = &table->free_list_pool[i]; - entry->trampoline = - (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE)); - - if (i < table->free_count - 1) - entry->next = &table->free_list_pool[i + 1]; - } - - table->free_list = table->free_list_pool; - } - - return table; -} - -void * -ffi_closure_alloc (size_t size, void **code) -{ - /* Create the closure */ - ffi_closure *closure = malloc (size); - if (closure == NULL) - return NULL; - - pthread_mutex_lock (&ffi_trampoline_lock); - - /* Check for an active trampoline table with available entries. */ - ffi_trampoline_table *table = ffi_trampoline_tables; - if (table == NULL || table->free_list == NULL) - { - table = ffi_trampoline_table_alloc (); - if (table == NULL) - { - free (closure); - return NULL; - } - - /* Insert the new table at the top of the list */ - table->next = ffi_trampoline_tables; - if (table->next != NULL) - table->next->prev = table; - - ffi_trampoline_tables = table; - } - - /* Claim the free entry */ - ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list; - ffi_trampoline_tables->free_list = entry->next; - ffi_trampoline_tables->free_count--; - entry->next = NULL; - - pthread_mutex_unlock (&ffi_trampoline_lock); - - /* Initialize the return values */ - *code = entry->trampoline; - closure->trampoline_table = table; - closure->trampoline_table_entry = entry; - - return closure; -} - -void -ffi_closure_free (void *ptr) -{ - ffi_closure *closure = ptr; - - pthread_mutex_lock (&ffi_trampoline_lock); - - /* Fetch the table and entry references */ - ffi_trampoline_table *table = closure->trampoline_table; - ffi_trampoline_table_entry *entry = closure->trampoline_table_entry; - - /* Return the entry to the free list */ - entry->next = table->free_list; - table->free_list = entry; - table->free_count++; - - /* If all trampolines within this table are free, and at least one other table exists, deallocate - * the table */ - if (table->free_count == FFI_TRAMPOLINE_COUNT - && ffi_trampoline_tables != table) - { - /* Remove from the list */ - if (table->prev != NULL) - table->prev->next = table->next; - - if (table->next != NULL) - table->next->prev = table->prev; - - /* Deallocate pages */ - kern_return_t kt; - kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE); - if (kt != KERN_SUCCESS) - fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, - __FILE__, __LINE__); - - kt = - vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE); - if (kt != KERN_SUCCESS) - fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, - __FILE__, __LINE__); - - /* Deallocate free list */ - free (table->free_list_pool); - free (table); - } - else if (ffi_trampoline_tables != table) - { - /* Otherwise, bump this table to the top of the list */ - table->prev = NULL; - table->next = ffi_trampoline_tables; - if (ffi_trampoline_tables != NULL) - ffi_trampoline_tables->prev = table; - - ffi_trampoline_tables = table; - } - - pthread_mutex_unlock (&ffi_trampoline_lock); - - /* Free the closure */ - free (closure); -} - +#if defined(FFI_EXEC_STATIC_TRAMP) +extern void ffi_closure_SYSV_alt (void) FFI_HIDDEN; +extern void ffi_closure_SYSV_V_alt (void) FFI_HIDDEN; #endif ffi_status @@ -966,7 +798,7 @@ ffi_prep_closure_loc (ffi_closure *closure, void *user_data, void *codeloc) { - if (cif->abi != FFI_SYSV) + if (cif->abi != FFI_SYSV && cif->abi != FFI_WIN64) return FFI_BAD_ABI; void (*start)(void); @@ -977,9 +809,14 @@ ffi_prep_closure_loc (ffi_closure *closure, start = ffi_closure_SYSV; #if FFI_EXEC_TRAMPOLINE_TABLE - void **config = FFI_TRAMPOLINE_CODELOC_CONFIG (codeloc); +#ifdef __MACH__ +#ifdef HAVE_PTRAUTH + codeloc = ptrauth_auth_data(codeloc, ptrauth_key_function_pointer, 0); +#endif + void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE); config[0] = closure; config[1] = start; +#endif #else static const unsigned char trampoline[16] = { 0x90, 0x00, 0x00, 0x58, /* ldr x16, tramp+16 */ @@ -987,12 +824,37 @@ ffi_prep_closure_loc (ffi_closure *closure, 0x00, 0x02, 0x1f, 0xd6 /* br x16 */ }; char *tramp = closure->tramp; - + +#if defined(FFI_EXEC_STATIC_TRAMP) + if (ffi_tramp_is_present(closure)) + { + /* Initialize the static trampoline's parameters. */ + if (start == ffi_closure_SYSV_V) + start = ffi_closure_SYSV_V_alt; + else + start = ffi_closure_SYSV_alt; + ffi_tramp_set_parms (closure->ftramp, start, closure); + goto out; + } +#endif + + /* Initialize the dynamic trampoline. */ memcpy (tramp, trampoline, sizeof(trampoline)); *(UINT64 *)(tramp + 16) = (uintptr_t)start; ffi_clear_cache(tramp, tramp + FFI_TRAMPOLINE_SIZE); + + /* Also flush the cache for code mapping. */ +#ifdef _WIN32 + // Not using dlmalloc.c for Windows ARM64 builds + // so calling ffi_data_to_code_pointer() isn't necessary + unsigned char *tramp_code = tramp; + #else + unsigned char *tramp_code = ffi_data_to_code_pointer (tramp); + #endif + ffi_clear_cache (tramp_code, tramp_code + FFI_TRAMPOLINE_SIZE); +out: #endif closure->cif = cif; @@ -1012,7 +874,7 @@ ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif* cif, { void (*start)(void); - if (cif->abi != FFI_SYSV) + if (cif->abi != FFI_SYSV && cif->abi != FFI_WIN64) return FFI_BAD_ABI; if (cif->flags & AARCH64_FLAG_ARG_V) @@ -1052,11 +914,18 @@ ffi_closure_SYSV_inner (ffi_cif *cif, void *stack, void *rvalue, void *struct_rvalue) { void **avalue = (void**) alloca (cif->nargs * sizeof (void*)); - int i, h, nargs, flags; + int i, h, nargs, flags, isvariadic = 0; struct arg_state state; arg_init (&state); + flags = cif->flags; + if (flags & AARCH64_FLAG_VARARG) + { + isvariadic = 1; + flags &= ~AARCH64_FLAG_VARARG; + } + for (i = 0, nargs = cif->nargs; i < nargs; i++) { ffi_type *ty = cif->arg_types[i]; @@ -1091,58 +960,85 @@ ffi_closure_SYSV_inner (ffi_cif *cif, if (h) { n = 4 - (h & 3); - if (state.nsrn + n <= N_V_ARG_REG) - { - void *reg = &context->v[state.nsrn]; - state.nsrn += n; - - /* Eeek! We need a pointer to the structure, however the - homogeneous float elements are being passed in individual - registers, therefore for float and double the structure - is not represented as a contiguous sequence of bytes in - our saved register context. We don't need the original - contents of the register storage, so we reformat the - structure into the same memory. */ - avalue[i] = compress_hfa_type (reg, reg, h); - } - else - { - state.nsrn = N_V_ARG_REG; - avalue[i] = allocate_to_stack (&state, stack, - ty->alignment, s); - } - } - else if (s > 16) - { - /* Replace Composite type of size greater than 16 with a - pointer. */ - avalue[i] = *(void **) - allocate_int_to_reg_or_stack (context, &state, stack, - sizeof (void *)); - } - else - { - n = (s + 7) / 8; - if (state.ngrn + n <= N_X_ARG_REG) - { - avalue[i] = &context->x[state.ngrn]; - state.ngrn += n; - } - else - { - state.ngrn = N_X_ARG_REG; - avalue[i] = allocate_to_stack (&state, stack, - ty->alignment, s); - } - } - break; + if (cif->abi == FFI_WIN64 && isvariadic) + { + if (state.ngrn + n <= N_X_ARG_REG) + { + void *reg = &context->x[state.ngrn]; + state.ngrn += (unsigned int)n; + + /* Eeek! We need a pointer to the structure, however the + homogeneous float elements are being passed in individual + registers, therefore for float and double the structure + is not represented as a contiguous sequence of bytes in + our saved register context. We don't need the original + contents of the register storage, so we reformat the + structure into the same memory. */ + avalue[i] = compress_hfa_type(reg, reg, h); + } + else + { + state.ngrn = N_X_ARG_REG; + state.nsrn = N_V_ARG_REG; + avalue[i] = allocate_to_stack(&state, stack, + ty->alignment, s); + } + } + else + { + if (state.nsrn + n <= N_V_ARG_REG) + { + void *reg = &context->v[state.nsrn]; + state.nsrn += (unsigned int)n; + avalue[i] = compress_hfa_type(reg, reg, h); + } + else + { + state.nsrn = N_V_ARG_REG; + avalue[i] = allocate_to_stack(&state, stack, + ty->alignment, s); + } + } + } + else if (s > 16) + { + /* Replace Composite type of size greater than 16 with a + pointer. */ + avalue[i] = *(void **) + allocate_int_to_reg_or_stack (context, &state, stack, + sizeof (void *)); + } + else + { + n = (s + 7) / 8; + if (state.ngrn + n <= N_X_ARG_REG) + { + avalue[i] = &context->x[state.ngrn]; + state.ngrn += (unsigned int)n; + } + else + { + state.ngrn = N_X_ARG_REG; + avalue[i] = allocate_to_stack(&state, stack, + ty->alignment, s); + } + } + break; + + default: + abort(); + } - default: - abort(); +#if defined (__APPLE__) + if (i + 1 == cif->aarch64_nfixedargs) + { + state.ngrn = N_X_ARG_REG; + state.nsrn = N_V_ARG_REG; + state.allocating_variadic = 1; } +#endif } - flags = cif->flags; if (flags & AARCH64_RET_IN_MEM) rvalue = struct_rvalue; @@ -1150,3 +1046,19 @@ ffi_closure_SYSV_inner (ffi_cif *cif, return flags; } + +#if defined(FFI_EXEC_STATIC_TRAMP) +void * +ffi_tramp_arch (size_t *tramp_size, size_t *map_size) +{ + extern void *trampoline_code_table; + + *tramp_size = AARCH64_TRAMP_SIZE; + *map_size = AARCH64_TRAMP_MAP_SIZE; + return &trampoline_code_table; +} +#endif + +#endif /* FFI_CLOSURES */ + +#endif /* (__aarch64__) || defined(__arm64__)|| defined (_M_ARM64)*/ diff --git a/libffi/src/aarch64/ffitarget.h b/libffi/src/aarch64/ffitarget.h index 34200ad..d5622e1 100644 --- a/libffi/src/aarch64/ffitarget.h +++ b/libffi/src/aarch64/ffitarget.h @@ -32,6 +32,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define FFI_SIZEOF_JAVA_RAW 4 typedef unsigned long long ffi_arg; typedef signed long long ffi_sarg; +#elif defined(_WIN32) +#define FFI_SIZEOF_ARG 8 +typedef unsigned long long ffi_arg; +typedef signed long long ffi_sarg; #else typedef unsigned long ffi_arg; typedef signed long ffi_sarg; @@ -41,34 +45,53 @@ typedef enum ffi_abi { FFI_FIRST_ABI = 0, FFI_SYSV, + FFI_WIN64, FFI_LAST_ABI, +#if defined(_WIN32) + FFI_DEFAULT_ABI = FFI_WIN64 +#else FFI_DEFAULT_ABI = FFI_SYSV +#endif } ffi_abi; #endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 -#if defined (__APPLE__) -#define FFI_TRAMPOLINE_SIZE 20 +#define FFI_NATIVE_RAW_API 0 + +#if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE + +#ifdef __MACH__ +#define FFI_TRAMPOLINE_SIZE 16 #define FFI_TRAMPOLINE_CLOSURE_OFFSET 16 #else +#error "No trampoline table implementation" +#endif + +#else #define FFI_TRAMPOLINE_SIZE 24 #define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE #endif -#define FFI_NATIVE_RAW_API 0 + +#ifdef _WIN32 +#define FFI_EXTRA_CIF_FIELDS unsigned is_variadic +#endif +#define FFI_TARGET_SPECIFIC_VARIADIC /* ---- Internal ---- */ #if defined (__APPLE__) -#define FFI_TARGET_SPECIFIC_VARIADIC #define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs -#else -/* iOS reserves x18 for the system. Disable Go closures until +#elif !defined(_WIN32) +/* iOS and Windows reserve x18 for the system. Disable Go closures until a new static chain is chosen. */ #define FFI_GO_CLOSURES 1 #endif +#ifndef _WIN32 +/* No complex type on Windows */ #define FFI_TARGET_HAS_COMPLEX_TYPE +#endif #endif diff --git a/libffi/src/aarch64/internal.h b/libffi/src/aarch64/internal.h index 9c3e077..b5d102b 100644 --- a/libffi/src/aarch64/internal.h +++ b/libffi/src/aarch64/internal.h @@ -61,7 +61,40 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define AARCH64_FLAG_ARG_V_BIT 7 #define AARCH64_FLAG_ARG_V (1 << AARCH64_FLAG_ARG_V_BIT) +#define AARCH64_FLAG_VARARG (1 << 8) #define N_X_ARG_REG 8 #define N_V_ARG_REG 8 #define CALL_CONTEXT_SIZE (N_V_ARG_REG * 16 + N_X_ARG_REG * 8) + +#if defined(FFI_EXEC_STATIC_TRAMP) +/* + * For the trampoline code table mapping, a mapping size of 16K is chosen to + * cover the base page sizes of 4K and 16K. + */ +#define AARCH64_TRAMP_MAP_SHIFT 14 +#define AARCH64_TRAMP_MAP_SIZE (1 << AARCH64_TRAMP_MAP_SHIFT) +#define AARCH64_TRAMP_SIZE 32 + +#endif + +/* Helpers for writing assembly compatible with arm ptr auth */ +#ifdef LIBFFI_ASM + +#ifdef HAVE_PTRAUTH +#define SIGN_LR pacibsp +#define SIGN_LR_WITH_REG(x) pacib lr, x +#define AUTH_LR_AND_RET retab +#define AUTH_LR_WITH_REG(x) autib lr, x +#define BRANCH_AND_LINK_TO_REG blraaz +#define BRANCH_TO_REG braaz +#else +#define SIGN_LR +#define SIGN_LR_WITH_REG(x) +#define AUTH_LR_AND_RET ret +#define AUTH_LR_WITH_REG(x) +#define BRANCH_AND_LINK_TO_REG blr +#define BRANCH_TO_REG br +#endif + +#endif diff --git a/libffi/src/aarch64/sysv.S b/libffi/src/aarch64/sysv.S index c1bf9b9..eeaf3f8 100644 --- a/libffi/src/aarch64/sysv.S +++ b/libffi/src/aarch64/sysv.S @@ -19,6 +19,7 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#if defined(__aarch64__) || defined(__arm64__) #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> @@ -77,9 +78,22 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ cfi_startproc CNAME(ffi_call_SYSV): + /* Sign the lr with x1 since that is where it will be stored */ + SIGN_LR_WITH_REG(x1) + /* Use a stack frame allocated by our caller. */ - cfi_def_cfa(x1, 32); +#if defined(HAVE_PTRAUTH) && defined(__APPLE__) + /* darwin's libunwind assumes that the cfa is the sp and that's the data + * used to sign the lr. In order to allow unwinding through this + * function it is necessary to point the cfa at the signing register. + */ + cfi_def_cfa(x1, 0); +#else + cfi_def_cfa(x1, 40); +#endif stp x29, x30, [x1] + mov x9, sp + str x9, [x1, #32] mov x29, x1 mov sp, x0 cfi_def_cfa_register(x29) @@ -110,13 +124,15 @@ CNAME(ffi_call_SYSV): /* Deallocate the context, leaving the stacked arguments. */ add sp, sp, #CALL_CONTEXT_SIZE - blr x9 /* call fn */ + BRANCH_AND_LINK_TO_REG x9 /* call fn */ ldp x3, x4, [x29, #16] /* reload rvalue and flags */ /* Partially deconstruct the stack frame. */ - mov sp, x29 + ldr x9, [x29, #32] + mov sp, x9 cfi_def_cfa_register (sp) + mov x2, x29 /* Preserve for auth */ ldp x29, x30, [x29] /* Save the return value as directed. */ @@ -130,80 +146,87 @@ CNAME(ffi_call_SYSV): and therefore we want to extend to 64 bits; these types have two consecutive entries allocated for them. */ .align 4 -0: ret /* VOID */ +0: b 99f /* VOID */ nop 1: str x0, [x3] /* INT64 */ - ret + b 99f 2: stp x0, x1, [x3] /* INT128 */ - ret + b 99f 3: brk #1000 /* UNUSED */ - ret + b 99f 4: brk #1000 /* UNUSED */ - ret + b 99f 5: brk #1000 /* UNUSED */ - ret + b 99f 6: brk #1000 /* UNUSED */ - ret + b 99f 7: brk #1000 /* UNUSED */ - ret + b 99f 8: st4 { v0.s, v1.s, v2.s, v3.s }[0], [x3] /* S4 */ - ret + b 99f 9: st3 { v0.s, v1.s, v2.s }[0], [x3] /* S3 */ - ret + b 99f 10: stp s0, s1, [x3] /* S2 */ - ret + b 99f 11: str s0, [x3] /* S1 */ - ret + b 99f 12: st4 { v0.d, v1.d, v2.d, v3.d }[0], [x3] /* D4 */ - ret + b 99f 13: st3 { v0.d, v1.d, v2.d }[0], [x3] /* D3 */ - ret + b 99f 14: stp d0, d1, [x3] /* D2 */ - ret + b 99f 15: str d0, [x3] /* D1 */ - ret + b 99f 16: str q3, [x3, #48] /* Q4 */ nop 17: str q2, [x3, #32] /* Q3 */ nop 18: stp q0, q1, [x3] /* Q2 */ - ret + b 99f 19: str q0, [x3] /* Q1 */ - ret + b 99f 20: uxtb w0, w0 /* UINT8 */ str x0, [x3] -21: ret /* reserved */ +21: b 99f /* reserved */ nop 22: uxth w0, w0 /* UINT16 */ str x0, [x3] -23: ret /* reserved */ +23: b 99f /* reserved */ nop 24: mov w0, w0 /* UINT32 */ str x0, [x3] -25: ret /* reserved */ +25: b 99f /* reserved */ nop 26: sxtb x0, w0 /* SINT8 */ str x0, [x3] -27: ret /* reserved */ +27: b 99f /* reserved */ nop 28: sxth x0, w0 /* SINT16 */ str x0, [x3] -29: ret /* reserved */ +29: b 99f /* reserved */ nop 30: sxtw x0, w0 /* SINT32 */ str x0, [x3] -31: ret /* reserved */ +31: b 99f /* reserved */ nop + /* Return now that result has been populated. */ +99: + AUTH_LR_WITH_REG(x2) + ret + cfi_endproc .globl CNAME(ffi_call_SYSV) + FFI_HIDDEN(CNAME(ffi_call_SYSV)) #ifdef __ELF__ .type CNAME(ffi_call_SYSV), #function - .hidden CNAME(ffi_call_SYSV) .size CNAME(ffi_call_SYSV), .-CNAME(ffi_call_SYSV) #endif +#if FFI_CLOSURES + /* ffi_closure_SYSV Closure invocation glue. This is the low level code invoked directly by @@ -223,6 +246,7 @@ CNAME(ffi_call_SYSV): .align 4 CNAME(ffi_closure_SYSV_V): cfi_startproc + SIGN_LR stp x29, x30, [sp, #-ffi_closure_SYSV_FS]! cfi_adjust_cfa_offset (ffi_closure_SYSV_FS) cfi_rel_offset (x29, 0) @@ -237,15 +261,16 @@ CNAME(ffi_closure_SYSV_V): cfi_endproc .globl CNAME(ffi_closure_SYSV_V) + FFI_HIDDEN(CNAME(ffi_closure_SYSV_V)) #ifdef __ELF__ .type CNAME(ffi_closure_SYSV_V), #function - .hidden CNAME(ffi_closure_SYSV_V) .size CNAME(ffi_closure_SYSV_V), . - CNAME(ffi_closure_SYSV_V) #endif .align 4 cfi_startproc CNAME(ffi_closure_SYSV): + SIGN_LR stp x29, x30, [sp, #-ffi_closure_SYSV_FS]! cfi_adjust_cfa_offset (ffi_closure_SYSV_FS) cfi_rel_offset (x29, 0) @@ -262,7 +287,9 @@ CNAME(ffi_closure_SYSV): /* Load ffi_closure_inner arguments. */ ldp PTR_REG(0), PTR_REG(1), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET] /* load cif, fn */ ldr PTR_REG(2), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET+PTR_SIZE*2] /* load user_data */ +#ifdef FFI_GO_CLOSURES .Ldo_closure: +#endif add x3, sp, #16 /* load context */ add x4, sp, #ffi_closure_SYSV_FS /* load stack */ add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */ @@ -296,7 +323,7 @@ CNAME(ffi_closure_SYSV): nop 8: ldr s3, [x3, #12] /* S4 */ nop -9: ldr s2, [x2, #8] /* S3 */ +9: ldr s2, [x3, #8] /* S3 */ nop 10: ldp s0, s1, [x3] /* S2 */ b 99f @@ -345,35 +372,109 @@ CNAME(ffi_closure_SYSV): cfi_adjust_cfa_offset (-ffi_closure_SYSV_FS) cfi_restore (x29) cfi_restore (x30) - ret + AUTH_LR_AND_RET cfi_endproc .globl CNAME(ffi_closure_SYSV) + FFI_HIDDEN(CNAME(ffi_closure_SYSV)) #ifdef __ELF__ .type CNAME(ffi_closure_SYSV), #function - .hidden CNAME(ffi_closure_SYSV) .size CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV) #endif +#if defined(FFI_EXEC_STATIC_TRAMP) + .align 4 +CNAME(ffi_closure_SYSV_V_alt): + /* See the comments above trampoline_code_table. */ + ldr x17, [sp, #8] /* Load closure in x17 */ + add sp, sp, #16 /* Restore the stack */ + b CNAME(ffi_closure_SYSV_V) + + .globl CNAME(ffi_closure_SYSV_V_alt) + FFI_HIDDEN(CNAME(ffi_closure_SYSV_V_alt)) +#ifdef __ELF__ + .type CNAME(ffi_closure_SYSV_V_alt), #function + .size CNAME(ffi_closure_SYSV_V_alt), . - CNAME(ffi_closure_SYSV_V_alt) +#endif + + .align 4 +CNAME(ffi_closure_SYSV_alt): + /* See the comments above trampoline_code_table. */ + ldr x17, [sp, #8] /* Load closure in x17 */ + add sp, sp, #16 /* Restore the stack */ + b CNAME(ffi_closure_SYSV) + + .globl CNAME(ffi_closure_SYSV_alt) + FFI_HIDDEN(CNAME(ffi_closure_SYSV_alt)) +#ifdef __ELF__ + .type CNAME(ffi_closure_SYSV_alt), #function + .size CNAME(ffi_closure_SYSV_alt), . - CNAME(ffi_closure_SYSV_alt) +#endif + +/* + * Below is the definition of the trampoline code table. Each element in + * the code table is a trampoline. + */ +/* + * The trampoline uses register x17. It saves the original value of x17 on + * the stack. + * + * The trampoline has two parameters - target code to jump to and data for + * the target code. The trampoline extracts the parameters from its parameter + * block (see tramp_table_map()). The trampoline saves the data address on + * the stack. Finally, it jumps to the target code. + * + * The target code can choose to: + * + * - restore the value of x17 + * - load the data address in a register + * - restore the stack pointer to what it was when the trampoline was invoked. + */ + .align AARCH64_TRAMP_MAP_SHIFT +CNAME(trampoline_code_table): + .rept AARCH64_TRAMP_MAP_SIZE / AARCH64_TRAMP_SIZE + sub sp, sp, #16 /* Make space on the stack */ + str x17, [sp] /* Save x17 on stack */ + adr x17, #16376 /* Get data address */ + ldr x17, [x17] /* Copy data into x17 */ + str x17, [sp, #8] /* Save data on stack */ + adr x17, #16372 /* Get code address */ + ldr x17, [x17] /* Load code address into x17 */ + br x17 /* Jump to code */ + .endr + + .globl CNAME(trampoline_code_table) + FFI_HIDDEN(CNAME(trampoline_code_table)) +#ifdef __ELF__ + .type CNAME(trampoline_code_table), #function + .size CNAME(trampoline_code_table), . - CNAME(trampoline_code_table) +#endif + .align AARCH64_TRAMP_MAP_SHIFT +#endif /* FFI_EXEC_STATIC_TRAMP */ + #if FFI_EXEC_TRAMPOLINE_TABLE - .align 12 + +#ifdef __MACH__ +#include <mach/machine/vm_param.h> + .align PAGE_MAX_SHIFT CNAME(ffi_closure_trampoline_table_page): - .rept 16384 / FFI_TRAMPOLINE_SIZE - adr x17, -16384 - adr x16, -16380 - ldr x16, [x16] - ldr x17, [x17] - br x16 + .rept PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE + adr x16, -PAGE_MAX_SIZE + ldp x17, x16, [x16] + br x16 + nop /* each entry in the trampoline config page is 2*sizeof(void*) so the trampoline itself cannot be smaller than 16 bytes */ .endr - + .globl CNAME(ffi_closure_trampoline_table_page) + FFI_HIDDEN(CNAME(ffi_closure_trampoline_table_page)) #ifdef __ELF__ .type CNAME(ffi_closure_trampoline_table_page), #function - .hidden CNAME(ffi_closure_trampoline_table_page) .size CNAME(ffi_closure_trampoline_table_page), . - CNAME(ffi_closure_trampoline_table_page) #endif #endif +#endif /* FFI_EXEC_TRAMPOLINE_TABLE */ + #ifdef FFI_GO_CLOSURES .align 4 CNAME(ffi_go_closure_SYSV_V): @@ -392,9 +493,9 @@ CNAME(ffi_go_closure_SYSV_V): cfi_endproc .globl CNAME(ffi_go_closure_SYSV_V) + FFI_HIDDEN(CNAME(ffi_go_closure_SYSV_V)) #ifdef __ELF__ .type CNAME(ffi_go_closure_SYSV_V), #function - .hidden CNAME(ffi_go_closure_SYSV_V) .size CNAME(ffi_go_closure_SYSV_V), . - CNAME(ffi_go_closure_SYSV_V) #endif @@ -421,12 +522,14 @@ CNAME(ffi_go_closure_SYSV): cfi_endproc .globl CNAME(ffi_go_closure_SYSV) + FFI_HIDDEN(CNAME(ffi_go_closure_SYSV)) #ifdef __ELF__ .type CNAME(ffi_go_closure_SYSV), #function - .hidden CNAME(ffi_go_closure_SYSV) .size CNAME(ffi_go_closure_SYSV), . - CNAME(ffi_go_closure_SYSV) #endif #endif /* FFI_GO_CLOSURES */ +#endif /* FFI_CLOSURES */ +#endif /* __arm64__ */ #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",%progbits diff --git a/libffi/src/aarch64/win64_armasm.S b/libffi/src/aarch64/win64_armasm.S new file mode 100644 index 0000000..7fc185b --- /dev/null +++ b/libffi/src/aarch64/win64_armasm.S @@ -0,0 +1,506 @@ +/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#define LIBFFI_ASM +#include <fficonfig.h> +#include <ffi.h> +#include <ffi_cfi.h> +#include "internal.h" + + OPT 2 /*disable listing */ +/* For some macros to add unwind information */ +#include "ksarm64.h" + OPT 1 /*re-enable listing */ + +#define BE(X) 0 +#define PTR_REG(n) x##n +#define PTR_SIZE 8 + + IMPORT ffi_closure_SYSV_inner + EXPORT ffi_call_SYSV + EXPORT ffi_closure_SYSV_V + EXPORT ffi_closure_SYSV + EXPORT extend_hfa_type + EXPORT compress_hfa_type +#ifdef FFI_GO_CLOSURES + EXPORT ffi_go_closure_SYSV_V + EXPORT ffi_go_closure_SYSV +#endif + + TEXTAREA, ALIGN=8 + +/* ffi_call_SYSV + extern void ffi_call_SYSV (void *stack, void *frame, + void (*fn)(void), void *rvalue, + int flags, void *closure); + Therefore on entry we have: + x0 stack + x1 frame + x2 fn + x3 rvalue + x4 flags + x5 closure +*/ + + NESTED_ENTRY ffi_call_SYSV_fake + + /* For unwind information, Windows has to store fp and lr */ + PROLOG_SAVE_REG_PAIR x29, x30, #-32! + + ALTERNATE_ENTRY ffi_call_SYSV + /* Use a stack frame allocated by our caller. */ + stp x29, x30, [x1] + mov x29, x1 + mov sp, x0 + + mov x9, x2 /* save fn */ + mov x8, x3 /* install structure return */ +#ifdef FFI_GO_CLOSURES + /*mov x18, x5 install static chain */ +#endif + stp x3, x4, [x29, #16] /* save rvalue and flags */ + + /* Load the vector argument passing registers, if necessary. */ + tbz x4, #AARCH64_FLAG_ARG_V_BIT, ffi_call_SYSV_L1 + ldp q0, q1, [sp, #0] + ldp q2, q3, [sp, #32] + ldp q4, q5, [sp, #64] + ldp q6, q7, [sp, #96] + +ffi_call_SYSV_L1 + /* Load the core argument passing registers, including + the structure return pointer. */ + ldp x0, x1, [sp, #16*N_V_ARG_REG + 0] + ldp x2, x3, [sp, #16*N_V_ARG_REG + 16] + ldp x4, x5, [sp, #16*N_V_ARG_REG + 32] + ldp x6, x7, [sp, #16*N_V_ARG_REG + 48] + + /* Deallocate the context, leaving the stacked arguments. */ + add sp, sp, #CALL_CONTEXT_SIZE + + blr x9 /* call fn */ + + ldp x3, x4, [x29, #16] /* reload rvalue and flags */ + + /* Partially deconstruct the stack frame. */ + mov sp, x29 + ldp x29, x30, [x29] + + /* Save the return value as directed. */ + adr x5, ffi_call_SYSV_return + and w4, w4, #AARCH64_RET_MASK + add x5, x5, x4, lsl #3 + br x5 + + /* Note that each table entry is 2 insns, and thus 8 bytes. + For integer data, note that we're storing into ffi_arg + and therefore we want to extend to 64 bits; these types + have two consecutive entries allocated for them. */ + ALIGN 4 +ffi_call_SYSV_return + ret /* VOID */ + nop + str x0, [x3] /* INT64 */ + ret + stp x0, x1, [x3] /* INT128 */ + ret + brk #1000 /* UNUSED */ + ret + brk #1000 /* UNUSED */ + ret + brk #1000 /* UNUSED */ + ret + brk #1000 /* UNUSED */ + ret + brk #1000 /* UNUSED */ + ret + st4 { v0.s, v1.s, v2.s, v3.s }[0], [x3] /* S4 */ + ret + st3 { v0.s, v1.s, v2.s }[0], [x3] /* S3 */ + ret + stp s0, s1, [x3] /* S2 */ + ret + str s0, [x3] /* S1 */ + ret + st4 { v0.d, v1.d, v2.d, v3.d }[0], [x3] /* D4 */ + ret + st3 { v0.d, v1.d, v2.d }[0], [x3] /* D3 */ + ret + stp d0, d1, [x3] /* D2 */ + ret + str d0, [x3] /* D1 */ + ret + str q3, [x3, #48] /* Q4 */ + nop + str q2, [x3, #32] /* Q3 */ + nop + stp q0, q1, [x3] /* Q2 */ + ret + str q0, [x3] /* Q1 */ + ret + uxtb w0, w0 /* UINT8 */ + str x0, [x3] + ret /* reserved */ + nop + uxth w0, w0 /* UINT16 */ + str x0, [x3] + ret /* reserved */ + nop + mov w0, w0 /* UINT32 */ + str x0, [x3] + ret /* reserved */ + nop + sxtb x0, w0 /* SINT8 */ + str x0, [x3] + ret /* reserved */ + nop + sxth x0, w0 /* SINT16 */ + str x0, [x3] + ret /* reserved */ + nop + sxtw x0, w0 /* SINT32 */ + str x0, [x3] + ret /* reserved */ + nop + + + NESTED_END ffi_call_SYSV_fake + + +/* ffi_closure_SYSV + Closure invocation glue. This is the low level code invoked directly by + the closure trampoline to setup and call a closure. + On entry x17 points to a struct ffi_closure, x16 has been clobbered + all other registers are preserved. + We allocate a call context and save the argument passing registers, + then invoked the generic C ffi_closure_SYSV_inner() function to do all + the real work, on return we load the result passing registers back from + the call context. +*/ + +#define ffi_closure_SYSV_FS (8*2 + CALL_CONTEXT_SIZE + 64) + + NESTED_ENTRY ffi_closure_SYSV_V + PROLOG_SAVE_REG_PAIR x29, x30, #-ffi_closure_SYSV_FS! + + /* Save the argument passing vector registers. */ + stp q0, q1, [sp, #16 + 0] + stp q2, q3, [sp, #16 + 32] + stp q4, q5, [sp, #16 + 64] + stp q6, q7, [sp, #16 + 96] + + b ffi_closure_SYSV_save_argument + NESTED_END ffi_closure_SYSV_V + + NESTED_ENTRY ffi_closure_SYSV + PROLOG_SAVE_REG_PAIR x29, x30, #-ffi_closure_SYSV_FS! + +ffi_closure_SYSV_save_argument + /* Save the argument passing core registers. */ + stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0] + stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16] + stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32] + stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48] + + /* Load ffi_closure_inner arguments. */ + ldp PTR_REG(0), PTR_REG(1), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET] /* load cif, fn */ + ldr PTR_REG(2), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET+PTR_SIZE*2] /* load user_data */ + +do_closure + add x3, sp, #16 /* load context */ + add x4, sp, #ffi_closure_SYSV_FS /* load stack */ + add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */ + mov x6, x8 /* load struct_rval */ + + bl ffi_closure_SYSV_inner + + /* Load the return value as directed. */ + adr x1, ffi_closure_SYSV_return_base + and w0, w0, #AARCH64_RET_MASK + add x1, x1, x0, lsl #3 + add x3, sp, #16+CALL_CONTEXT_SIZE + br x1 + + /* Note that each table entry is 2 insns, and thus 8 bytes. */ + ALIGN 8 +ffi_closure_SYSV_return_base + b ffi_closure_SYSV_epilog /* VOID */ + nop + ldr x0, [x3] /* INT64 */ + b ffi_closure_SYSV_epilog + ldp x0, x1, [x3] /* INT128 */ + b ffi_closure_SYSV_epilog + brk #1000 /* UNUSED */ + nop + brk #1000 /* UNUSED */ + nop + brk #1000 /* UNUSED */ + nop + brk #1000 /* UNUSED */ + nop + brk #1000 /* UNUSED */ + nop + ldr s3, [x3, #12] /* S4 */ + nop + ldr s2, [x3, #8] /* S3 */ + nop + ldp s0, s1, [x3] /* S2 */ + b ffi_closure_SYSV_epilog + ldr s0, [x3] /* S1 */ + b ffi_closure_SYSV_epilog + ldr d3, [x3, #24] /* D4 */ + nop + ldr d2, [x3, #16] /* D3 */ + nop + ldp d0, d1, [x3] /* D2 */ + b ffi_closure_SYSV_epilog + ldr d0, [x3] /* D1 */ + b ffi_closure_SYSV_epilog + ldr q3, [x3, #48] /* Q4 */ + nop + ldr q2, [x3, #32] /* Q3 */ + nop + ldp q0, q1, [x3] /* Q2 */ + b ffi_closure_SYSV_epilog + ldr q0, [x3] /* Q1 */ + b ffi_closure_SYSV_epilog + ldrb w0, [x3, #BE(7)] /* UINT8 */ + b ffi_closure_SYSV_epilog + brk #1000 /* reserved */ + nop + ldrh w0, [x3, #BE(6)] /* UINT16 */ + b ffi_closure_SYSV_epilog + brk #1000 /* reserved */ + nop + ldr w0, [x3, #BE(4)] /* UINT32 */ + b ffi_closure_SYSV_epilog + brk #1000 /* reserved */ + nop + ldrsb x0, [x3, #BE(7)] /* SINT8 */ + b ffi_closure_SYSV_epilog + brk #1000 /* reserved */ + nop + ldrsh x0, [x3, #BE(6)] /* SINT16 */ + b ffi_closure_SYSV_epilog + brk #1000 /* reserved */ + nop + ldrsw x0, [x3, #BE(4)] /* SINT32 */ + nop + /* reserved */ + +ffi_closure_SYSV_epilog + EPILOG_RESTORE_REG_PAIR x29, x30, #ffi_closure_SYSV_FS! + EPILOG_RETURN + NESTED_END ffi_closure_SYSV + + +#ifdef FFI_GO_CLOSURES + NESTED_ENTRY ffi_go_closure_SYSV_V + PROLOG_SAVE_REG_PAIR x29, x30, #-ffi_closure_SYSV_FS! + + /* Save the argument passing vector registers. */ + stp q0, q1, [sp, #16 + 0] + stp q2, q3, [sp, #16 + 32] + stp q4, q5, [sp, #16 + 64] + stp q6, q7, [sp, #16 + 96] + b ffi_go_closure_SYSV_save_argument + NESTED_END ffi_go_closure_SYSV_V + + NESTED_ENTRY ffi_go_closure_SYSV + PROLOG_SAVE_REG_PAIR x29, x30, #-ffi_closure_SYSV_FS! + +ffi_go_closure_SYSV_save_argument + /* Save the argument passing core registers. */ + stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0] + stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16] + stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32] + stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48] + + /* Load ffi_closure_inner arguments. */ + ldp PTR_REG(0), PTR_REG(1), [x18, #PTR_SIZE]/* load cif, fn */ + mov x2, x18 /* load user_data */ + b do_closure + NESTED_END ffi_go_closure_SYSV + +#endif /* FFI_GO_CLOSURES */ + + +/* void extend_hfa_type (void *dest, void *src, int h) */ + + LEAF_ENTRY extend_hfa_type + + adr x3, extend_hfa_type_jump_base + and w2, w2, #AARCH64_RET_MASK + sub x2, x2, #AARCH64_RET_S4 + add x3, x3, x2, lsl #4 + br x3 + + ALIGN 4 +extend_hfa_type_jump_base + ldp s16, s17, [x1] /* S4 */ + ldp s18, s19, [x1, #8] + b extend_hfa_type_store_4 + nop + + ldp s16, s17, [x1] /* S3 */ + ldr s18, [x1, #8] + b extend_hfa_type_store_3 + nop + + ldp s16, s17, [x1] /* S2 */ + b extend_hfa_type_store_2 + nop + nop + + ldr s16, [x1] /* S1 */ + b extend_hfa_type_store_1 + nop + nop + + ldp d16, d17, [x1] /* D4 */ + ldp d18, d19, [x1, #16] + b extend_hfa_type_store_4 + nop + + ldp d16, d17, [x1] /* D3 */ + ldr d18, [x1, #16] + b extend_hfa_type_store_3 + nop + + ldp d16, d17, [x1] /* D2 */ + b extend_hfa_type_store_2 + nop + nop + + ldr d16, [x1] /* D1 */ + b extend_hfa_type_store_1 + nop + nop + + ldp q16, q17, [x1] /* Q4 */ + ldp q18, q19, [x1, #16] + b extend_hfa_type_store_4 + nop + + ldp q16, q17, [x1] /* Q3 */ + ldr q18, [x1, #16] + b extend_hfa_type_store_3 + nop + + ldp q16, q17, [x1] /* Q2 */ + b extend_hfa_type_store_2 + nop + nop + + ldr q16, [x1] /* Q1 */ + b extend_hfa_type_store_1 + +extend_hfa_type_store_4 + str q19, [x0, #48] +extend_hfa_type_store_3 + str q18, [x0, #32] +extend_hfa_type_store_2 + str q17, [x0, #16] +extend_hfa_type_store_1 + str q16, [x0] + ret + + LEAF_END extend_hfa_type + + +/* void compress_hfa_type (void *dest, void *reg, int h) */ + + LEAF_ENTRY compress_hfa_type + + adr x3, compress_hfa_type_jump_base + and w2, w2, #AARCH64_RET_MASK + sub x2, x2, #AARCH64_RET_S4 + add x3, x3, x2, lsl #4 + br x3 + + ALIGN 4 +compress_hfa_type_jump_base + ldp q16, q17, [x1] /* S4 */ + ldp q18, q19, [x1, #32] + st4 { v16.s, v17.s, v18.s, v19.s }[0], [x0] + ret + + ldp q16, q17, [x1] /* S3 */ + ldr q18, [x1, #32] + st3 { v16.s, v17.s, v18.s }[0], [x0] + ret + + ldp q16, q17, [x1] /* S2 */ + st2 { v16.s, v17.s }[0], [x0] + ret + nop + + ldr q16, [x1] /* S1 */ + st1 { v16.s }[0], [x0] + ret + nop + + ldp q16, q17, [x1] /* D4 */ + ldp q18, q19, [x1, #32] + st4 { v16.d, v17.d, v18.d, v19.d }[0], [x0] + ret + + ldp q16, q17, [x1] /* D3 */ + ldr q18, [x1, #32] + st3 { v16.d, v17.d, v18.d }[0], [x0] + ret + + ldp q16, q17, [x1] /* D2 */ + st2 { v16.d, v17.d }[0], [x0] + ret + nop + + ldr q16, [x1] /* D1 */ + st1 { v16.d }[0], [x0] + ret + nop + + ldp q16, q17, [x1] /* Q4 */ + ldp q18, q19, [x1, #32] + b compress_hfa_type_store_q4 + nop + + ldp q16, q17, [x1] /* Q3 */ + ldr q18, [x1, #32] + b compress_hfa_type_store_q3 + nop + + ldp q16, q17, [x1] /* Q2 */ + stp q16, q17, [x0] + ret + nop + + ldr q16, [x1] /* Q1 */ + str q16, [x0] + ret + +compress_hfa_type_store_q4 + str q19, [x0, #48] +compress_hfa_type_store_q3 + str q18, [x0, #32] + stp q16, q17, [x0] + ret + + LEAF_END compress_hfa_type + + END
\ No newline at end of file diff --git a/libffi/src/alpha/ffi.c b/libffi/src/alpha/ffi.c index efae4cc..7a95e97 100644 --- a/libffi/src/alpha/ffi.c +++ b/libffi/src/alpha/ffi.c @@ -98,7 +98,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) case FFI_TYPE_VOID: case FFI_TYPE_STRUCT: /* Passed by value in N slots. */ - bytes += ALIGN(itype->size, FFI_SIZEOF_ARG); + bytes += FFI_ALIGN(itype->size, FFI_SIZEOF_ARG); break; case FFI_TYPE_COMPLEX: @@ -285,7 +285,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, case FFI_TYPE_STRUCT: size = ty->size; memcpy(argp + argn, valp, size); - argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + argn += FFI_ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; break; case FFI_TYPE_COMPLEX: @@ -421,7 +421,7 @@ ffi_closure_osf_inner (ffi_cif *cif, case FFI_TYPE_VOID: case FFI_TYPE_STRUCT: size = ty->size; - argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + argn += FFI_ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; break; case FFI_TYPE_FLOAT: diff --git a/libffi/src/arc/ffi.c b/libffi/src/arc/ffi.c index 32f82a7d5..4d10b21 100644 --- a/libffi/src/arc/ffi.c +++ b/libffi/src/arc/ffi.c @@ -46,12 +46,10 @@ void ffi_prep_args (char *stack, extended_cif * ecif) { unsigned int i; - int tmp; void **p_argv; char *argp; ffi_type **p_arg; - tmp = 0; argp = stack; if (ecif->cif->rtype->type == FFI_TYPE_STRUCT) @@ -73,7 +71,7 @@ ffi_prep_args (char *stack, extended_cif * ecif) /* Align if necessary. */ if ((alignment - 1) & (unsigned) argp) - argp = (char *) ALIGN (argp, alignment); + argp = (char *) FFI_ALIGN (argp, alignment); z = (*p_arg)->size; if (z < sizeof (int)) @@ -225,7 +223,7 @@ ffi_closure_inner_ARCompact (ffi_closure * closure, void *rvalue, /* Align if necessary. */ if ((alignment - 1) & (unsigned) argp) - argp = (char *) ALIGN (argp, alignment); + argp = (char *) FFI_ALIGN (argp, alignment); z = (*p_argt)->size; *p_argv = (void *) argp; diff --git a/libffi/src/arm/ffi.c b/libffi/src/arm/ffi.c index 9c8732d..593ab4d 100644 --- a/libffi/src/arm/ffi.c +++ b/libffi/src/arm/ffi.c @@ -28,11 +28,42 @@ DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ +#if defined(__arm__) || defined(_M_ARM) +#include <fficonfig.h> #include <ffi.h> #include <ffi_common.h> +#include <stdint.h> #include <stdlib.h> +#include <tramp.h> #include "internal.h" +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + +#if FFI_EXEC_TRAMPOLINE_TABLE + +#ifdef __MACH__ +#include <mach/machine/vm_param.h> +#endif + +#else +#ifndef _WIN32 +extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN; +#else +// Declare this as an array of char, instead of array of int, +// otherwise Clang optimizes out the "& 0xFFFFFFFE" for clearing +// the thumb bit. +extern unsigned char ffi_arm_trampoline[12] FFI_HIDDEN; +#endif +#endif + +#if defined(__FreeBSD__) && defined(__arm__) +#include <sys/types.h> +#include <machine/sysarch.h> +#endif + /* Forward declares. */ static int vfp_type_p (const ffi_type *); static void layout_vfp_args (ffi_cif *); @@ -49,7 +80,7 @@ ffi_align (ffi_type *ty, void *p) if (alignment < 4) alignment = 4; #endif - return (void *) ALIGN (p, alignment); + return (void *) FFI_ALIGN (p, alignment); } static size_t @@ -76,10 +107,20 @@ ffi_put_arg (ffi_type *ty, void *src, void *dst) case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: case FFI_TYPE_POINTER: +#ifndef _WIN32 case FFI_TYPE_FLOAT: +#endif *(UINT32 *)dst = *(UINT32 *)src; break; +#ifdef _WIN32 + // casting a float* to a UINT32* doesn't work on Windows + case FFI_TYPE_FLOAT: + *(uintptr_t *)dst = 0; + *(float *)dst = *(float *)src; + break; +#endif + case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: case FFI_TYPE_DOUBLE: @@ -95,7 +136,7 @@ ffi_put_arg (ffi_type *ty, void *src, void *dst) abort(); } - return ALIGN (z, 4); + return FFI_ALIGN (z, 4); } /* ffi_prep_args is called once stack space has been allocated @@ -198,7 +239,7 @@ ffi_prep_args_VFP (ffi_cif *cif, int flags, void *rvalue, } /* Perform machine dependent cif processing */ -ffi_status +ffi_status FFI_HIDDEN ffi_prep_cif_machdep (ffi_cif *cif) { int flags = 0, cabi = cif->abi; @@ -276,7 +317,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) /* Round the stack up to a multiple of 8 bytes. This isn't needed everywhere, but it is on some platforms, and it doesn't harm anything when it isn't needed. */ - bytes = ALIGN (bytes, 8); + bytes = FFI_ALIGN (bytes, 8); /* Minimum stack space is the 4 register arguments that we pop. */ if (bytes < 4*4) @@ -289,7 +330,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) } /* Perform machine dependent cif processing for variadic calls */ -ffi_status +ffi_status FFI_HIDDEN ffi_prep_cif_machdep_var (ffi_cif * cif, unsigned int nfixedargs, unsigned int ntotalargs) { @@ -389,12 +430,14 @@ ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue) ffi_call_int (cif, fn, rvalue, avalue, NULL); } +#ifdef FFI_GO_CLOSURES void ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue, void *closure) { ffi_call_int (cif, fn, rvalue, avalue, closure); } +#endif static void * ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue, @@ -408,6 +451,11 @@ ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue, rvalue = *(void **) argp; argp += 4; } + else + { + if (cif->rtype->size && cif->rtype->size < 4) + *(uint32_t *) rvalue = 0; + } for (i = 0, n = cif->nargs; i < n; i++) { @@ -492,6 +540,8 @@ ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack, return rvalue; } +#if FFI_CLOSURES + struct closure_frame { char vfp_space[8*8] __attribute__((aligned(8))); @@ -527,257 +577,28 @@ ffi_closure_inner_VFP (ffi_cif *cif, void ffi_closure_SYSV (void) FFI_HIDDEN; void ffi_closure_VFP (void) FFI_HIDDEN; +#if defined(FFI_EXEC_STATIC_TRAMP) +void ffi_closure_SYSV_alt (void) FFI_HIDDEN; +void ffi_closure_VFP_alt (void) FFI_HIDDEN; +#endif + +#ifdef FFI_GO_CLOSURES void ffi_go_closure_SYSV (void) FFI_HIDDEN; void ffi_go_closure_VFP (void) FFI_HIDDEN; - -#if FFI_EXEC_TRAMPOLINE_TABLE - -#include <mach/mach.h> -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> - -extern void *ffi_closure_trampoline_table_page; - -typedef struct ffi_trampoline_table ffi_trampoline_table; -typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry; - -struct ffi_trampoline_table -{ - /* contiguous writable and executable pages */ - vm_address_t config_page; - vm_address_t trampoline_page; - - /* free list tracking */ - uint16_t free_count; - ffi_trampoline_table_entry *free_list; - ffi_trampoline_table_entry *free_list_pool; - - ffi_trampoline_table *prev; - ffi_trampoline_table *next; -}; - -struct ffi_trampoline_table_entry -{ - void *(*trampoline) (); - ffi_trampoline_table_entry *next; -}; - -/* Override the standard architecture trampoline size */ -// XXX TODO - Fix -#undef FFI_TRAMPOLINE_SIZE -#define FFI_TRAMPOLINE_SIZE 12 - -/* The trampoline configuration is placed at 4080 bytes prior to the trampoline's entry point */ -#define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - 4080)); - -/* The first 16 bytes of the config page are unused, as they are unaddressable from the trampoline page. */ -#define FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET 16 - -/* Total number of trampolines that fit in one trampoline table */ -#define FFI_TRAMPOLINE_COUNT ((PAGE_SIZE - FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) / FFI_TRAMPOLINE_SIZE) - -static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER; -static ffi_trampoline_table *ffi_trampoline_tables = NULL; - -static ffi_trampoline_table * -ffi_trampoline_table_alloc () -{ - ffi_trampoline_table *table = NULL; - - /* Loop until we can allocate two contiguous pages */ - while (table == NULL) - { - vm_address_t config_page = 0x0; - kern_return_t kt; - - /* Try to allocate two pages */ - kt = - vm_allocate (mach_task_self (), &config_page, PAGE_SIZE * 2, - VM_FLAGS_ANYWHERE); - if (kt != KERN_SUCCESS) - { - fprintf (stderr, "vm_allocate() failure: %d at %s:%d\n", kt, - __FILE__, __LINE__); - break; - } - - /* Now drop the second half of the allocation to make room for the trampoline table */ - vm_address_t trampoline_page = config_page + PAGE_SIZE; - kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE); - if (kt != KERN_SUCCESS) - { - fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, - __FILE__, __LINE__); - break; - } - - /* Remap the trampoline table to directly follow the config page */ - vm_prot_t cur_prot; - vm_prot_t max_prot; - - kt = - vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE, - mach_task_self (), - (vm_address_t) & ffi_closure_trampoline_table_page, FALSE, - &cur_prot, &max_prot, VM_INHERIT_SHARE); - - /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */ - if (kt != KERN_SUCCESS) - { - /* Log unexpected failures */ - if (kt != KERN_NO_SPACE) - { - fprintf (stderr, "vm_remap() failure: %d at %s:%d\n", kt, - __FILE__, __LINE__); - } - - vm_deallocate (mach_task_self (), config_page, PAGE_SIZE); - continue; - } - - /* We have valid trampoline and config pages */ - table = calloc (1, sizeof (ffi_trampoline_table)); - table->free_count = FFI_TRAMPOLINE_COUNT; - table->config_page = config_page; - table->trampoline_page = trampoline_page; - - /* Create and initialize the free list */ - table->free_list_pool = - calloc (FFI_TRAMPOLINE_COUNT, sizeof (ffi_trampoline_table_entry)); - - uint16_t i; - for (i = 0; i < table->free_count; i++) - { - ffi_trampoline_table_entry *entry = &table->free_list_pool[i]; - entry->trampoline = - (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE)); - - if (i < table->free_count - 1) - entry->next = &table->free_list_pool[i + 1]; - } - - table->free_list = table->free_list_pool; - } - - return table; -} - -void * -ffi_closure_alloc (size_t size, void **code) -{ - /* Create the closure */ - ffi_closure *closure = malloc (size); - if (closure == NULL) - return NULL; - - pthread_mutex_lock (&ffi_trampoline_lock); - - /* Check for an active trampoline table with available entries. */ - ffi_trampoline_table *table = ffi_trampoline_tables; - if (table == NULL || table->free_list == NULL) - { - table = ffi_trampoline_table_alloc (); - if (table == NULL) - { - free (closure); - return NULL; - } - - /* Insert the new table at the top of the list */ - table->next = ffi_trampoline_tables; - if (table->next != NULL) - table->next->prev = table; - - ffi_trampoline_tables = table; - } - - /* Claim the free entry */ - ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list; - ffi_trampoline_tables->free_list = entry->next; - ffi_trampoline_tables->free_count--; - entry->next = NULL; - - pthread_mutex_unlock (&ffi_trampoline_lock); - - /* Initialize the return values */ - *code = entry->trampoline; - closure->trampoline_table = table; - closure->trampoline_table_entry = entry; - - return closure; -} - -void -ffi_closure_free (void *ptr) -{ - ffi_closure *closure = ptr; - - pthread_mutex_lock (&ffi_trampoline_lock); - - /* Fetch the table and entry references */ - ffi_trampoline_table *table = closure->trampoline_table; - ffi_trampoline_table_entry *entry = closure->trampoline_table_entry; - - /* Return the entry to the free list */ - entry->next = table->free_list; - table->free_list = entry; - table->free_count++; - - /* If all trampolines within this table are free, and at least one other table exists, deallocate - * the table */ - if (table->free_count == FFI_TRAMPOLINE_COUNT - && ffi_trampoline_tables != table) - { - /* Remove from the list */ - if (table->prev != NULL) - table->prev->next = table->next; - - if (table->next != NULL) - table->next->prev = table->prev; - - /* Deallocate pages */ - kern_return_t kt; - kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE); - if (kt != KERN_SUCCESS) - fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, - __FILE__, __LINE__); - - kt = - vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE); - if (kt != KERN_SUCCESS) - fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, - __FILE__, __LINE__); - - /* Deallocate free list */ - free (table->free_list_pool); - free (table); - } - else if (ffi_trampoline_tables != table) - { - /* Otherwise, bump this table to the top of the list */ - table->prev = NULL; - table->next = ffi_trampoline_tables; - if (ffi_trampoline_tables != NULL) - ffi_trampoline_tables->prev = table; - - ffi_trampoline_tables = table; - } - - pthread_mutex_unlock (&ffi_trampoline_lock); - - /* Free the closure */ - free (closure); -} - -#else - -extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN; - #endif /* the cif must already be prep'ed */ +#if defined(__FreeBSD__) && defined(__arm__) +#define __clear_cache(start, end) do { \ + struct arm_sync_icache_args ua; \ + \ + ua.addr = (uintptr_t)(start); \ + ua.len = (char *)(end) - (char *)start; \ + sysarch(ARM_SYNC_ICACHE, &ua); \ + } while (0); +#endif + ffi_status ffi_prep_closure_loc (ffi_closure * closure, ffi_cif * cif, @@ -796,15 +617,48 @@ ffi_prep_closure_loc (ffi_closure * closure, return FFI_BAD_ABI; #if FFI_EXEC_TRAMPOLINE_TABLE - void **config = FFI_TRAMPOLINE_CODELOC_CONFIG (codeloc); + void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE); config[0] = closure; config[1] = closure_func; #else - memcpy (closure->tramp, ffi_arm_trampoline, 8); + +#if defined(FFI_EXEC_STATIC_TRAMP) + if (ffi_tramp_is_present(closure)) + { + /* Initialize the static trampoline's parameters. */ + if (closure_func == ffi_closure_SYSV) + closure_func = ffi_closure_SYSV_alt; + else + closure_func = ffi_closure_VFP_alt; + ffi_tramp_set_parms (closure->ftramp, closure_func, closure); + goto out; + } +#endif + + /* Initialize the dynamic trampoline. */ +#ifndef _WIN32 + memcpy(closure->tramp, ffi_arm_trampoline, 8); +#else + // cast away function type so MSVC doesn't set the lower bit of the function pointer + memcpy(closure->tramp, (void*)((uintptr_t)ffi_arm_trampoline & 0xFFFFFFFE), FFI_TRAMPOLINE_CLOSURE_OFFSET); +#endif + +#if defined (__QNX__) + msync(closure->tramp, 8, 0x1000000); /* clear data map */ + msync(codeloc, 8, 0x1000000); /* clear insn map */ +#elif defined(_WIN32) + FlushInstructionCache(GetCurrentProcess(), closure->tramp, FFI_TRAMPOLINE_SIZE); +#else __clear_cache(closure->tramp, closure->tramp + 8); /* clear data map */ __clear_cache(codeloc, codeloc + 8); /* clear insn map */ +#endif +#ifdef _WIN32 + *(void(**)(void))(closure->tramp + FFI_TRAMPOLINE_CLOSURE_FUNCTION) = closure_func; +#else *(void (**)(void))(closure->tramp + 8) = closure_func; #endif +out: +#endif closure->cif = cif; closure->fun = fun; @@ -813,6 +667,7 @@ ffi_prep_closure_loc (ffi_closure * closure, return FFI_OK; } +#ifdef FFI_GO_CLOSURES ffi_status ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif, void (*fun) (ffi_cif *, void *, void **, void *)) @@ -834,6 +689,9 @@ ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif, return FFI_OK; } +#endif + +#endif /* FFI_CLOSURES */ /* Below are routines for VFP hard-float support. */ @@ -1005,7 +863,7 @@ place_vfp_arg (ffi_cif *cif, int h) } /* Found regs to allocate. */ cif->vfp_used |= new_used; - cif->vfp_args[cif->vfp_nargs++] = reg; + cif->vfp_args[cif->vfp_nargs++] = (signed char)reg; /* Update vfp_reg_free. */ if (cif->vfp_used & (1 << cif->vfp_reg_free)) @@ -1027,7 +885,7 @@ place_vfp_arg (ffi_cif *cif, int h) static void layout_vfp_args (ffi_cif * cif) { - int i; + unsigned int i; /* Init VFP fields */ cif->vfp_used = 0; cif->vfp_nargs = 0; @@ -1041,3 +899,17 @@ layout_vfp_args (ffi_cif * cif) break; } } + +#if defined(FFI_EXEC_STATIC_TRAMP) +void * +ffi_tramp_arch (size_t *tramp_size, size_t *map_size) +{ + extern void *trampoline_code_table; + + *tramp_size = ARM_TRAMP_SIZE; + *map_size = ARM_TRAMP_MAP_SIZE; + return &trampoline_code_table; +} +#endif + +#endif /* __arm__ or _M_ARM */ diff --git a/libffi/src/arm/ffitarget.h b/libffi/src/arm/ffitarget.h index 4f473f9..12d5d20 100644 --- a/libffi/src/arm/ffitarget.h +++ b/libffi/src/arm/ffitarget.h @@ -43,7 +43,7 @@ typedef enum ffi_abi { FFI_SYSV, FFI_VFP, FFI_LAST_ABI, -#ifdef __ARM_PCS_VFP +#if defined(__ARM_PCS_VFP) || defined(_WIN32) FFI_DEFAULT_ABI = FFI_VFP, #else FFI_DEFAULT_ABI = FFI_SYSV, @@ -57,13 +57,33 @@ typedef enum ffi_abi { signed char vfp_args[16] \ #define FFI_TARGET_SPECIFIC_VARIADIC +#ifndef _WIN32 #define FFI_TARGET_HAS_COMPLEX_TYPE +#endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 #define FFI_GO_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 12 #define FFI_NATIVE_RAW_API 0 +#if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE + +#ifdef __MACH__ +#define FFI_TRAMPOLINE_SIZE 12 +#define FFI_TRAMPOLINE_CLOSURE_OFFSET 8 +#else +#error "No trampoline table implementation" +#endif + +#else +#ifdef _WIN32 +#define FFI_TRAMPOLINE_SIZE 16 +#define FFI_TRAMPOLINE_CLOSURE_FUNCTION 12 +#else +#define FFI_TRAMPOLINE_SIZE 12 +#endif +#define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE +#endif + #endif diff --git a/libffi/src/arm/internal.h b/libffi/src/arm/internal.h index 6cf0b2a..fa8ab0b 100644 --- a/libffi/src/arm/internal.h +++ b/libffi/src/arm/internal.h @@ -5,3 +5,13 @@ #define ARM_TYPE_INT 4 #define ARM_TYPE_VOID 5 #define ARM_TYPE_STRUCT 6 + +#if defined(FFI_EXEC_STATIC_TRAMP) +/* + * For the trampoline table mapping, a mapping size of 4K (base page size) + * is chosen. + */ +#define ARM_TRAMP_MAP_SHIFT 12 +#define ARM_TRAMP_MAP_SIZE (1 << ARM_TRAMP_MAP_SHIFT) +#define ARM_TRAMP_SIZE 20 +#endif diff --git a/libffi/src/arm/sysv.S b/libffi/src/arm/sysv.S index fd16589..fb36213 100644 --- a/libffi/src/arm/sysv.S +++ b/libffi/src/arm/sysv.S @@ -25,7 +25,8 @@ DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ -#define LIBFFI_ASM +#ifdef __arm__ +#define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> #include <ffi_cfi.h> @@ -52,11 +53,12 @@ #endif /* Conditionally compile unwinder directives. */ -.macro UNWIND text:vararg #ifdef __ARM_EABI__ - \text -#endif -.endm +# define UNWIND(...) __VA_ARGS__ +#else +# define UNWIND(...) +#endif + #if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__ARM_EABI__) .cfi_sections .debug_frame #endif @@ -77,29 +79,52 @@ # define TYPE(X, Y) #endif -#define ARM_FUNC_START(name, gl) \ - .align 3; \ - .ifne gl; .globl CNAME(name); FFI_HIDDEN(CNAME(name)); .endif; \ - TYPE(name, %function); \ +#define ARM_FUNC_START_LOCAL(name) \ + .align 3; \ + TYPE(CNAME(name), %function); \ CNAME(name): +#define ARM_FUNC_START(name) \ + .globl CNAME(name); \ + FFI_HIDDEN(CNAME(name)); \ + ARM_FUNC_START_LOCAL(name) + #define ARM_FUNC_END(name) \ SIZE(name) -/* Aid in defining a jump table with 8 bytes between entries. */ -.macro E index - .if . - 0b - 8*\index - .error "type table out of sync" - .endif -.endm - .text .syntax unified +#if defined(_WIN32) + /* Windows on ARM is thumb-only */ + .thumb +#else + /* Keep the assembly in ARM mode in other cases, for simplicity + * (to avoid interworking issues). */ +#undef __thumb__ .arm +#endif +/* Aid in defining a jump table with 8 bytes between entries. */ +#ifdef __thumb__ +/* In thumb mode, instructions can be shorter than expected in arm mode, so + * we need to align the start of each case. */ +# define E(index) .align 3 +#elif defined(__clang__) +/* ??? The clang assembler doesn't handle .if with symbolic expressions. */ +# define E(index) +#else +# define E(index) \ + .if . - 0b - 8*index; \ + .error "type table out of sync"; \ + .endif +#endif + + +#ifndef __clang__ /* We require interworking on LDM, which implies ARMv5T, which implies the existance of BLX. */ - .arch armv5t + .arch armv5t +#endif /* Note that we use STC and LDC to encode VFP instructions, so that we do not need ".fpu vfp", nor get that added to @@ -111,25 +136,31 @@ @ r2: fn @ r3: vfp_used -ARM_FUNC_START(ffi_call_VFP, 1) - UNWIND .fnstart +ARM_FUNC_START(ffi_call_VFP) + UNWIND(.fnstart) cfi_startproc cmp r3, #3 @ load only d0 if possible - ldcle p11, cr0, [r0] @ vldrle d0, [sp] - ldcgt p11, cr0, [r0], {16} @ vldmgt sp, {d0-d7} + ite le +#ifdef __clang__ + vldrle d0, [r0] + vldmgt r0, {d0-d7} +#else + ldcle p11, cr0, [r0] @ vldrle d0, [r0] + ldcgt p11, cr0, [r0], {16} @ vldmgt r0, {d0-d7} +#endif add r0, r0, #64 @ discard the vfp register args /* FALLTHRU */ ARM_FUNC_END(ffi_call_VFP) -ARM_FUNC_START(ffi_call_SYSV, 1) +ARM_FUNC_START(ffi_call_SYSV) stm r1, {fp, lr} mov fp, r1 @ This is a bit of a lie wrt the origin of the unwind info, but @ now we've got the usual frame pointer and two saved registers. - UNWIND .save {fp,lr} - UNWIND .setfp fp, sp + UNWIND(.save {fp,lr}) + UNWIND(.setfp fp, sp) cfi_def_cfa(fp, 8) cfi_rel_offset(fp, 0) cfi_rel_offset(lr, 4) @@ -150,41 +181,61 @@ ARM_FUNC_START(ffi_call_SYSV, 1) cfi_def_cfa_register(sp) @ Store values stored in registers. +#ifndef __thumb__ .align 3 add pc, pc, r3, lsl #3 nop +#else + adr ip, 0f + add ip, ip, r3, lsl #3 + mov pc, ip + .align 3 +#endif 0: -E ARM_TYPE_VFP_S +E(ARM_TYPE_VFP_S) +#ifdef __clang__ + vstr s0, [r2] +#else stc p10, cr0, [r2] @ vstr s0, [r2] +#endif pop {fp,pc} -E ARM_TYPE_VFP_D +E(ARM_TYPE_VFP_D) +#ifdef __clang__ + vstr d0, [r2] +#else stc p11, cr0, [r2] @ vstr d0, [r2] +#endif pop {fp,pc} -E ARM_TYPE_VFP_N +E(ARM_TYPE_VFP_N) +#ifdef __clang__ + vstm r2, {d0-d3} +#else stc p11, cr0, [r2], {8} @ vstm r2, {d0-d3} +#endif pop {fp,pc} -E ARM_TYPE_INT64 +E(ARM_TYPE_INT64) str r1, [r2, #4] nop -E ARM_TYPE_INT +E(ARM_TYPE_INT) str r0, [r2] pop {fp,pc} -E ARM_TYPE_VOID +E(ARM_TYPE_VOID) pop {fp,pc} nop -E ARM_TYPE_STRUCT +E(ARM_TYPE_STRUCT) pop {fp,pc} cfi_endproc - UNWIND .fnend + UNWIND(.fnend) ARM_FUNC_END(ffi_call_SYSV) +#if FFI_CLOSURES /* int ffi_closure_inner_* (cif, fun, user_data, frame) */ -ARM_FUNC_START(ffi_go_closure_SYSV, 1) +ARM_FUNC_START(ffi_go_closure_SYSV) cfi_startproc stmdb sp!, {r0-r3} @ save argument regs cfi_adjust_cfa_offset(16) @@ -195,14 +246,21 @@ ARM_FUNC_START(ffi_go_closure_SYSV, 1) cfi_endproc ARM_FUNC_END(ffi_go_closure_SYSV) -ARM_FUNC_START(ffi_closure_SYSV, 1) - UNWIND .fnstart +ARM_FUNC_START(ffi_closure_SYSV) + UNWIND(.fnstart) cfi_startproc +#ifdef _WIN32 + ldmfd sp!, {r0, ip} @ restore fp (r0 is used for stack alignment) +#endif stmdb sp!, {r0-r3} @ save argument regs cfi_adjust_cfa_offset(16) - ldr r0, [ip, #FFI_TRAMPOLINE_SIZE] @ load cif - ldr r1, [ip, #FFI_TRAMPOLINE_SIZE+4] @ load fun - ldr r2, [ip, #FFI_TRAMPOLINE_SIZE+8] @ load user_data + +#if FFI_EXEC_TRAMPOLINE_TABLE + ldr ip, [ip] @ ip points to the config page, dereference to get the ffi_closure* +#endif + ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] @ load cif + ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] @ load fun + ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] @ load user_data 0: add ip, sp, #16 @ compute entry sp sub sp, sp, #64+32 @ allocate frame @@ -212,7 +270,7 @@ ARM_FUNC_START(ffi_closure_SYSV, 1) /* Remember that EABI unwind info only applies at call sites. We need do nothing except note the save of the stack pointer and the link registers. */ - UNWIND .save {sp,lr} + UNWIND(.save {sp,lr}) cfi_adjust_cfa_offset(8) cfi_rel_offset(lr, 4) @@ -222,12 +280,17 @@ ARM_FUNC_START(ffi_closure_SYSV, 1) @ Load values returned in registers. add r2, sp, #8+64 @ load result adr r3, CNAME(ffi_closure_ret) +#ifndef __thumb__ add pc, r3, r0, lsl #3 +#else + add r3, r3, r0, lsl #3 + mov pc, r3 +#endif cfi_endproc - UNWIND .fnend + UNWIND(.fnend) ARM_FUNC_END(ffi_closure_SYSV) -ARM_FUNC_START(ffi_go_closure_VFP, 1) +ARM_FUNC_START(ffi_go_closure_VFP) cfi_startproc stmdb sp!, {r0-r3} @ save argument regs cfi_adjust_cfa_offset(16) @@ -238,23 +301,34 @@ ARM_FUNC_START(ffi_go_closure_VFP, 1) cfi_endproc ARM_FUNC_END(ffi_go_closure_VFP) -ARM_FUNC_START(ffi_closure_VFP, 1) - UNWIND .fnstart +ARM_FUNC_START(ffi_closure_VFP) + UNWIND(.fnstart) cfi_startproc +#ifdef _WIN32 + ldmfd sp!, {r0, ip} @ restore fp (r0 is used for stack alignment) +#endif stmdb sp!, {r0-r3} @ save argument regs cfi_adjust_cfa_offset(16) - ldr r0, [ip, #FFI_TRAMPOLINE_SIZE] @ load cif - ldr r1, [ip, #FFI_TRAMPOLINE_SIZE+4] @ load fun - ldr r2, [ip, #FFI_TRAMPOLINE_SIZE+8] @ load user_data + +#if FFI_EXEC_TRAMPOLINE_TABLE + ldr ip, [ip] @ ip points to the config page, dereference to get the ffi_closure* +#endif + ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] @ load cif + ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] @ load fun + ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] @ load user_data 0: add ip, sp, #16 sub sp, sp, #64+32 @ allocate frame cfi_adjust_cfa_offset(64+32) +#ifdef __clang__ + vstm sp, {d0-d7} +#else stc p11, cr0, [sp], {16} @ vstm sp, {d0-d7} +#endif stmdb sp!, {ip,lr} /* See above. */ - UNWIND .save {sp,lr} + UNWIND(.save {sp,lr}) cfi_adjust_cfa_offset(8) cfi_rel_offset(lr, 4) @@ -264,71 +338,151 @@ ARM_FUNC_START(ffi_closure_VFP, 1) @ Load values returned in registers. add r2, sp, #8+64 @ load result adr r3, CNAME(ffi_closure_ret) +#ifndef __thumb__ add pc, r3, r0, lsl #3 +#else + add r3, r3, r0, lsl #3 + mov pc, r3 +#endif cfi_endproc - UNWIND .fnend + UNWIND(.fnend) ARM_FUNC_END(ffi_closure_VFP) /* Load values returned in registers for both closure entry points. Note that we use LDM with SP in the register set. This is deprecated by ARM, but not yet unpredictable. */ -ARM_FUNC_START(ffi_closure_ret, 0) +ARM_FUNC_START_LOCAL(ffi_closure_ret) cfi_startproc cfi_rel_offset(sp, 0) cfi_rel_offset(lr, 4) 0: -E ARM_TYPE_VFP_S +E(ARM_TYPE_VFP_S) +#ifdef __clang__ + vldr s0, [r2] +#else ldc p10, cr0, [r2] @ vldr s0, [r2] - ldm sp, {sp,pc} -E ARM_TYPE_VFP_D +#endif + b call_epilogue +E(ARM_TYPE_VFP_D) +#ifdef __clang__ + vldr d0, [r2] +#else ldc p11, cr0, [r2] @ vldr d0, [r2] - ldm sp, {sp,pc} -E ARM_TYPE_VFP_N +#endif + b call_epilogue +E(ARM_TYPE_VFP_N) +#ifdef __clang__ + vldm r2, {d0-d3} +#else ldc p11, cr0, [r2], {8} @ vldm r2, {d0-d3} - ldm sp, {sp,pc} -E ARM_TYPE_INT64 +#endif + b call_epilogue +E(ARM_TYPE_INT64) ldr r1, [r2, #4] nop -E ARM_TYPE_INT +E(ARM_TYPE_INT) ldr r0, [r2] - ldm sp, {sp,pc} -E ARM_TYPE_VOID - ldm sp, {sp,pc} + b call_epilogue +E(ARM_TYPE_VOID) + b call_epilogue nop -E ARM_TYPE_STRUCT +E(ARM_TYPE_STRUCT) + b call_epilogue +call_epilogue: +#ifndef __thumb__ ldm sp, {sp,pc} +#else + ldm sp, {ip,lr} + mov sp, ip + bx lr +#endif cfi_endproc ARM_FUNC_END(ffi_closure_ret) -#if FFI_EXEC_TRAMPOLINE_TABLE +#if defined(FFI_EXEC_STATIC_TRAMP) +ARM_FUNC_START(ffi_closure_SYSV_alt) + /* See the comments above trampoline_code_table. */ + ldr ip, [sp, #4] /* Load closure in ip */ + add sp, sp, 8 /* Restore the stack */ + b CNAME(ffi_closure_SYSV) +ARM_FUNC_END(ffi_closure_SYSV_alt) + +ARM_FUNC_START(ffi_closure_VFP_alt) + /* See the comments above trampoline_code_table. */ + ldr ip, [sp, #4] /* Load closure in ip */ + add sp, sp, 8 /* Restore the stack */ + b CNAME(ffi_closure_VFP) +ARM_FUNC_END(ffi_closure_VFP_alt) -/* ??? The iOS support should be updated. The first insn used to - be STMFD, but that's been moved into ffi_closure_SYSV. If the - writable page is put after this one we can make use of the - pc+8 feature of the architecture. We can also reduce the size - of the thunk to 8 and pack more of these into the page. +/* + * Below is the definition of the trampoline code table. Each element in + * the code table is a trampoline. + */ +/* + * The trampoline uses register ip (r12). It saves the original value of ip + * on the stack. + * + * The trampoline has two parameters - target code to jump to and data for + * the target code. The trampoline extracts the parameters from its parameter + * block (see tramp_table_map()). The trampoline saves the data address on + * the stack. Finally, it jumps to the target code. + * + * The target code can choose to: + * + * - restore the value of ip + * - load the data address in a register + * - restore the stack pointer to what it was when the trampoline was invoked. + */ + .align ARM_TRAMP_MAP_SHIFT +ARM_FUNC_START(trampoline_code_table) + .rept ARM_TRAMP_MAP_SIZE / ARM_TRAMP_SIZE + sub sp, sp, #8 /* Make space on the stack */ + str ip, [sp] /* Save ip on stack */ + ldr ip, [pc, #4080] /* Copy data into ip */ + str ip, [sp, #4] /* Save data on stack */ + ldr pc, [pc, #4076] /* Copy code into PC */ + .endr +ARM_FUNC_END(trampoline_code_table) + .align ARM_TRAMP_MAP_SHIFT +#endif /* FFI_EXEC_STATIC_TRAMP */ + +#endif /* FFI_CLOSURES */ + +#if FFI_EXEC_TRAMPOLINE_TABLE - In the meantime, simply replace the STMFD with a NOP so as to - keep all the magic numbers the same within ffi.c. */ +#ifdef __MACH__ +#include <mach/machine/vm_param.h> - .align 12 +.align PAGE_MAX_SHIFT ARM_FUNC_START(ffi_closure_trampoline_table_page) -.rept 4096 / 12 - nop - ldr ip, [pc, #-4092] - ldr pc, [pc, #-4092] +.rept PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE + adr ip, #-PAGE_MAX_SIZE @ the config page is PAGE_MAX_SIZE behind the trampoline page + sub ip, #8 @ account for pc bias + ldr pc, [ip, #4] @ jump to ffi_closure_SYSV or ffi_closure_VFP .endr +ARM_FUNC_END(ffi_closure_trampoline_table_page) +#endif + +#elif defined(_WIN32) + +ARM_FUNC_START(ffi_arm_trampoline) +0: adr ip, 0b + stmdb sp!, {r0, ip} + ldr pc, 1f +1: .long 0 +ARM_FUNC_END(ffi_arm_trampoline) #else -ARM_FUNC_START(ffi_arm_trampoline, 1) +ARM_FUNC_START(ffi_arm_trampoline) 0: adr ip, 0b ldr pc, 1f 1: .long 0 ARM_FUNC_END(ffi_arm_trampoline) #endif /* FFI_EXEC_TRAMPOLINE_TABLE */ +#endif /* __arm__ */ #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",%progbits diff --git a/libffi/src/arm/sysv_msvc_arm32.S b/libffi/src/arm/sysv_msvc_arm32.S new file mode 100644 index 0000000..5c99d02 --- /dev/null +++ b/libffi/src/arm/sysv_msvc_arm32.S @@ -0,0 +1,311 @@ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc. + Copyright (c) 2011 Plausible Labs Cooperative, Inc. + Copyright (c) 2019 Microsoft Corporation. + + ARM Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM +#include <fficonfig.h> +#include <ffi.h> +#include <ffi_cfi.h> +#include "internal.h" +#include "ksarm.h" + + + ; 8 byte aligned AREA to support 8 byte aligned jump tables + MACRO + NESTED_ENTRY_FFI $FuncName, $AreaName, $ExceptHandler + + ; compute the function's labels + __DeriveFunctionLabels $FuncName + + ; determine the area we will put the function into +__FuncArea SETS "|.text|" + IF "$AreaName" != "" +__FuncArea SETS "$AreaName" + ENDIF + + ; set up the exception handler itself +__FuncExceptionHandler SETS "" + IF "$ExceptHandler" != "" +__FuncExceptionHandler SETS "|$ExceptHandler|" + ENDIF + + ; switch to the specified area, jump tables require 8 byte alignment + AREA $__FuncArea,CODE,CODEALIGN,ALIGN=3,READONLY + + ; export the function name + __ExportProc $FuncName + + ; flush any pending literal pool stuff + ROUT + + ; reset the state of the unwind code tracking + __ResetUnwindState + + MEND + +; MACRO +; TABLE_ENTRY $Type, $Table +;$Type_$Table +; MEND + +#define E(index,table) return_##index##_##table + + ; r0: stack + ; r1: frame + ; r2: fn + ; r3: vfp_used + + ; fake entry point exists only to generate exists only to + ; generate .pdata for exception unwinding + NESTED_ENTRY_FFI ffi_call_VFP_fake + PROLOG_PUSH {r11, lr} ; save fp and lr for unwind + + ALTERNATE_ENTRY ffi_call_VFP + cmp r3, #3 ; load only d0 if possible + vldrle d0, [r0] + vldmgt r0, {d0-d7} + add r0, r0, #64 ; discard the vfp register args + b ffi_call_SYSV + NESTED_END ffi_call_VFP_fake + + ; fake entry point exists only to generate exists only to + ; generate .pdata for exception unwinding + NESTED_ENTRY_FFI ffi_call_SYSV_fake + PROLOG_PUSH {r11, lr} ; save fp and lr for unwind + + ALTERNATE_ENTRY ffi_call_SYSV + stm r1, {fp, lr} + mov fp, r1 + + mov sp, r0 ; install the stack pointer + mov lr, r2 ; move the fn pointer out of the way + ldr ip, [fp, #16] ; install the static chain + ldmia sp!, {r0-r3} ; move first 4 parameters in registers. + blx lr ; call fn + + ; Load r2 with the pointer to storage for the return value + ; Load r3 with the return type code + ldr r2, [fp, #8] + ldr r3, [fp, #12] + + ; Deallocate the stack with the arguments. + mov sp, fp + + ; Store values stored in registers. + ALIGN 8 + lsl r3, #3 + add r3, r3, pc + add r3, #8 + mov pc, r3 + + +E(ARM_TYPE_VFP_S, ffi_call) + ALIGN 8 + vstr s0, [r2] + pop {fp,pc} +E(ARM_TYPE_VFP_D, ffi_call) + ALIGN 8 + vstr d0, [r2] + pop {fp,pc} +E(ARM_TYPE_VFP_N, ffi_call) + ALIGN 8 + vstm r2, {d0-d3} + pop {fp,pc} +E(ARM_TYPE_INT64, ffi_call) + ALIGN 8 + str r1, [r2, #4] + nop +E(ARM_TYPE_INT, ffi_call) + ALIGN 8 + str r0, [r2] + pop {fp,pc} +E(ARM_TYPE_VOID, ffi_call) + ALIGN 8 + pop {fp,pc} + nop +E(ARM_TYPE_STRUCT, ffi_call) + ALIGN 8 + cmp r3, #ARM_TYPE_STRUCT + pop {fp,pc} + NESTED_END ffi_call_SYSV_fake + + IMPORT |ffi_closure_inner_SYSV| + /* + int ffi_closure_inner_SYSV + ( + cif, ; r0 + fun, ; r1 + user_data, ; r2 + frame ; r3 + ) + */ + + NESTED_ENTRY_FFI ffi_go_closure_SYSV + stmdb sp!, {r0-r3} ; save argument regs + ldr r0, [ip, #4] ; load cif + ldr r1, [ip, #8] ; load fun + mov r2, ip ; load user_data + b ffi_go_closure_SYSV_0 + NESTED_END ffi_go_closure_SYSV + + ; r3: ffi_closure + + ; fake entry point exists only to generate exists only to + ; generate .pdata for exception unwinding + NESTED_ENTRY_FFI ffi_closure_SYSV_fake + PROLOG_PUSH {r11, lr} ; save fp and lr for unwind + ALTERNATE_ENTRY ffi_closure_SYSV + ldmfd sp!, {ip,r0} ; restore fp (r0 is used for stack alignment) + stmdb sp!, {r0-r3} ; save argument regs + + ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] ; ffi_closure->cif + ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] ; ffi_closure->fun + ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] ; ffi_closure->user_data + + ALTERNATE_ENTRY ffi_go_closure_SYSV_0 + add ip, sp, #16 ; compute entry sp + + sub sp, sp, #64+32 ; allocate frame parameter (sizeof(vfp_space) = 64, sizeof(result) = 32) + mov r3, sp ; set frame parameter + stmdb sp!, {ip,lr} + + bl ffi_closure_inner_SYSV ; call the Python closure + + ; Load values returned in registers. + add r2, sp, #64+8 ; address of closure_frame->result + bl ffi_closure_ret ; move result to correct register or memory for type + + ldmfd sp!, {ip,lr} + mov sp, ip ; restore stack pointer + mov pc, lr + NESTED_END ffi_closure_SYSV_fake + + IMPORT |ffi_closure_inner_VFP| + /* + int ffi_closure_inner_VFP + ( + cif, ; r0 + fun, ; r1 + user_data, ; r2 + frame ; r3 + ) + */ + + NESTED_ENTRY_FFI ffi_go_closure_VFP + stmdb sp!, {r0-r3} ; save argument regs + ldr r0, [ip, #4] ; load cif + ldr r1, [ip, #8] ; load fun + mov r2, ip ; load user_data + b ffi_go_closure_VFP_0 + NESTED_END ffi_go_closure_VFP + + ; fake entry point exists only to generate exists only to + ; generate .pdata for exception unwinding + ; r3: closure + NESTED_ENTRY_FFI ffi_closure_VFP_fake + PROLOG_PUSH {r11, lr} ; save fp and lr for unwind + + ALTERNATE_ENTRY ffi_closure_VFP + ldmfd sp!, {ip,r0} ; restore fp (r0 is used for stack alignment) + stmdb sp!, {r0-r3} ; save argument regs + + ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] ; load cif + ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] ; load fun + ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] ; load user_data + + ALTERNATE_ENTRY ffi_go_closure_VFP_0 + add ip, sp, #16 ; compute entry sp + sub sp, sp, #32 ; save space for closure_frame->result + vstmdb sp!, {d0-d7} ; push closure_frame->vfp_space + + mov r3, sp ; save closure_frame + stmdb sp!, {ip,lr} + + bl ffi_closure_inner_VFP + + ; Load values returned in registers. + add r2, sp, #64+8 ; load result + bl ffi_closure_ret + ldmfd sp!, {ip,lr} + mov sp, ip ; restore stack pointer + mov pc, lr + NESTED_END ffi_closure_VFP_fake + +/* Load values returned in registers for both closure entry points. + Note that we use LDM with SP in the register set. This is deprecated + by ARM, but not yet unpredictable. */ + + NESTED_ENTRY_FFI ffi_closure_ret + stmdb sp!, {fp,lr} + + ALIGN 8 + lsl r0, #3 + add r0, r0, pc + add r0, #8 + mov pc, r0 + +E(ARM_TYPE_VFP_S, ffi_closure) + ALIGN 8 + vldr s0, [r2] + b call_epilogue +E(ARM_TYPE_VFP_D, ffi_closure) + ALIGN 8 + vldr d0, [r2] + b call_epilogue +E(ARM_TYPE_VFP_N, ffi_closure) + ALIGN 8 + vldm r2, {d0-d3} + b call_epilogue +E(ARM_TYPE_INT64, ffi_closure) + ALIGN 8 + ldr r1, [r2, #4] + nop +E(ARM_TYPE_INT, ffi_closure) + ALIGN 8 + ldr r0, [r2] + b call_epilogue +E(ARM_TYPE_VOID, ffi_closure) + ALIGN 8 + b call_epilogue + nop +E(ARM_TYPE_STRUCT, ffi_closure) + ALIGN 8 + b call_epilogue +call_epilogue + ldmfd sp!, {fp,pc} + NESTED_END ffi_closure_ret + + AREA |.trampoline|, DATA, THUMB, READONLY + EXPORT |ffi_arm_trampoline| +|ffi_arm_trampoline| DATA +thisproc adr ip, thisproc + stmdb sp!, {ip, r0} + ldr pc, [pc, #0] + DCD 0 + ;ENDP + + END
\ No newline at end of file diff --git a/libffi/src/closures.c b/libffi/src/closures.c index 721ff00..f7bead6 100644 --- a/libffi/src/closures.c +++ b/libffi/src/closures.c @@ -1,5 +1,6 @@ /* ----------------------------------------------------------------------- - closures.c - Copyright (c) 2007, 2009, 2010 Red Hat, Inc. + closures.c - Copyright (c) 2019 Anthony Green + Copyright (c) 2007, 2009, 2010 Red Hat, Inc. Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc Copyright (c) 2011 Plausible Labs Cooperative, Inc. @@ -30,11 +31,98 @@ #define _GNU_SOURCE 1 #endif +#include <fficonfig.h> #include <ffi.h> #include <ffi_common.h> +#include <tramp.h> + +#ifdef __NetBSD__ +#include <sys/param.h> +#endif + +#if __NetBSD_Version__ - 0 >= 799007200 +/* NetBSD with PROT_MPROTECT */ +#include <sys/mman.h> + +#include <stddef.h> +#include <unistd.h> +#ifdef HAVE_SYS_MEMFD_H +#include <sys/memfd.h> +#endif + +static const size_t overhead = + (sizeof(max_align_t) > sizeof(void *) + sizeof(size_t)) ? + sizeof(max_align_t) + : sizeof(void *) + sizeof(size_t); + +#define ADD_TO_POINTER(p, d) ((void *)((uintptr_t)(p) + (d))) + +void * +ffi_closure_alloc (size_t size, void **code) +{ + static size_t page_size; + size_t rounded_size; + void *codeseg, *dataseg; + int prot; + + /* Expect that PAX mprotect is active and a separate code mapping is necessary. */ + if (!code) + return NULL; + + /* Obtain system page size. */ + if (!page_size) + page_size = sysconf(_SC_PAGESIZE); + + /* Round allocation size up to the next page, keeping in mind the size field and pointer to code map. */ + rounded_size = (size + overhead + page_size - 1) & ~(page_size - 1); + + /* Primary mapping is RW, but request permission to switch to PROT_EXEC later. */ + prot = PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC); + dataseg = mmap(NULL, rounded_size, prot, MAP_ANON | MAP_PRIVATE, -1, 0); + if (dataseg == MAP_FAILED) + return NULL; + + /* Create secondary mapping and switch it to RX. */ + codeseg = mremap(dataseg, rounded_size, NULL, rounded_size, MAP_REMAPDUP); + if (codeseg == MAP_FAILED) { + munmap(dataseg, rounded_size); + return NULL; + } + if (mprotect(codeseg, rounded_size, PROT_READ | PROT_EXEC) == -1) { + munmap(codeseg, rounded_size); + munmap(dataseg, rounded_size); + return NULL; + } + + /* Remember allocation size and location of the secondary mapping for ffi_closure_free. */ + memcpy(dataseg, &rounded_size, sizeof(rounded_size)); + memcpy(ADD_TO_POINTER(dataseg, sizeof(size_t)), &codeseg, sizeof(void *)); + *code = ADD_TO_POINTER(codeseg, overhead); + return ADD_TO_POINTER(dataseg, overhead); +} + +void +ffi_closure_free (void *ptr) +{ + void *codeseg, *dataseg; + size_t rounded_size; + + dataseg = ADD_TO_POINTER(ptr, -overhead); + memcpy(&rounded_size, dataseg, sizeof(rounded_size)); + memcpy(&codeseg, ADD_TO_POINTER(dataseg, sizeof(size_t)), sizeof(void *)); + munmap(dataseg, rounded_size); + munmap(codeseg, rounded_size); +} + +int +ffi_tramp_is_present (__attribute__((unused)) void *ptr) +{ + return 0; +} +#else /* !NetBSD with PROT_MPROTECT */ #if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE -# if __gnu_linux__ && !defined(__ANDROID__) +# if __linux__ && !defined(__ANDROID__) /* This macro indicates it may be forbidden to map anonymous memory with both write and execute permission. Code compiled when this option is defined will attempt to map such pages once, but if it @@ -45,7 +133,7 @@ # define FFI_MMAP_EXEC_WRIT 1 # define HAVE_MNTENT 1 # endif -# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__) +# if defined(_WIN32) || defined(__OS2__) /* Windows systems may have Data Execution Protection (DEP) enabled, which requires the use of VirtualMalloc/VirtualFree to alloc/free executable memory. */ @@ -54,7 +142,7 @@ #endif #if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX -# ifdef __linux__ +# if defined(__linux__) && !defined(__ANDROID__) /* When defined to 1 check for SELinux and if SELinux is active, don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that might cause audit messages. */ @@ -64,11 +152,226 @@ #if FFI_CLOSURES -# if FFI_EXEC_TRAMPOLINE_TABLE +#if FFI_EXEC_TRAMPOLINE_TABLE + +#ifdef __MACH__ + +#include <mach/mach.h> +#include <pthread.h> +#ifdef HAVE_PTRAUTH +#include <ptrauth.h> +#endif +#include <stdio.h> +#include <stdlib.h> + +extern void *ffi_closure_trampoline_table_page; + +typedef struct ffi_trampoline_table ffi_trampoline_table; +typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry; + +struct ffi_trampoline_table +{ + /* contiguous writable and executable pages */ + vm_address_t config_page; + + /* free list tracking */ + uint16_t free_count; + ffi_trampoline_table_entry *free_list; + ffi_trampoline_table_entry *free_list_pool; + + ffi_trampoline_table *prev; + ffi_trampoline_table *next; +}; + +struct ffi_trampoline_table_entry +{ + void *(*trampoline) (void); + ffi_trampoline_table_entry *next; +}; + +/* Total number of trampolines that fit in one trampoline table */ +#define FFI_TRAMPOLINE_COUNT (PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE) + +static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER; +static ffi_trampoline_table *ffi_trampoline_tables = NULL; + +static ffi_trampoline_table * +ffi_trampoline_table_alloc (void) +{ + ffi_trampoline_table *table; + vm_address_t config_page; + vm_address_t trampoline_page; + vm_address_t trampoline_page_template; + vm_prot_t cur_prot; + vm_prot_t max_prot; + kern_return_t kt; + uint16_t i; + + /* Allocate two pages -- a config page and a placeholder page */ + config_page = 0x0; + kt = vm_allocate (mach_task_self (), &config_page, PAGE_MAX_SIZE * 2, + VM_FLAGS_ANYWHERE); + if (kt != KERN_SUCCESS) + return NULL; + + /* Remap the trampoline table on top of the placeholder page */ + trampoline_page = config_page + PAGE_MAX_SIZE; + +#ifdef HAVE_PTRAUTH + trampoline_page_template = (vm_address_t)(uintptr_t)ptrauth_auth_data((void *)&ffi_closure_trampoline_table_page, ptrauth_key_function_pointer, 0); +#else + trampoline_page_template = (vm_address_t)&ffi_closure_trampoline_table_page; +#endif + +#ifdef __arm__ + /* ffi_closure_trampoline_table_page can be thumb-biased on some ARM archs */ + trampoline_page_template &= ~1UL; +#endif + kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_MAX_SIZE, 0x0, + VM_FLAGS_OVERWRITE, mach_task_self (), trampoline_page_template, + FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE); + if (kt != KERN_SUCCESS || !(cur_prot & VM_PROT_EXECUTE)) + { + vm_deallocate (mach_task_self (), config_page, PAGE_MAX_SIZE * 2); + return NULL; + } + + /* We have valid trampoline and config pages */ + table = calloc (1, sizeof (ffi_trampoline_table)); + table->free_count = FFI_TRAMPOLINE_COUNT; + table->config_page = config_page; + + /* Create and initialize the free list */ + table->free_list_pool = + calloc (FFI_TRAMPOLINE_COUNT, sizeof (ffi_trampoline_table_entry)); + + for (i = 0; i < table->free_count; i++) + { + ffi_trampoline_table_entry *entry = &table->free_list_pool[i]; + entry->trampoline = + (void *) (trampoline_page + (i * FFI_TRAMPOLINE_SIZE)); +#ifdef HAVE_PTRAUTH + entry->trampoline = ptrauth_sign_unauthenticated(entry->trampoline, ptrauth_key_function_pointer, 0); +#endif + + if (i < table->free_count - 1) + entry->next = &table->free_list_pool[i + 1]; + } + + table->free_list = table->free_list_pool; + + return table; +} + +static void +ffi_trampoline_table_free (ffi_trampoline_table *table) +{ + /* Remove from the list */ + if (table->prev != NULL) + table->prev->next = table->next; + + if (table->next != NULL) + table->next->prev = table->prev; + + /* Deallocate pages */ + vm_deallocate (mach_task_self (), table->config_page, PAGE_MAX_SIZE * 2); + + /* Deallocate free list */ + free (table->free_list_pool); + free (table); +} + +void * +ffi_closure_alloc (size_t size, void **code) +{ + /* Create the closure */ + ffi_closure *closure = malloc (size); + if (closure == NULL) + return NULL; + + pthread_mutex_lock (&ffi_trampoline_lock); + + /* Check for an active trampoline table with available entries. */ + ffi_trampoline_table *table = ffi_trampoline_tables; + if (table == NULL || table->free_list == NULL) + { + table = ffi_trampoline_table_alloc (); + if (table == NULL) + { + pthread_mutex_unlock (&ffi_trampoline_lock); + free (closure); + return NULL; + } + + /* Insert the new table at the top of the list */ + table->next = ffi_trampoline_tables; + if (table->next != NULL) + table->next->prev = table; + + ffi_trampoline_tables = table; + } + + /* Claim the free entry */ + ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list; + ffi_trampoline_tables->free_list = entry->next; + ffi_trampoline_tables->free_count--; + entry->next = NULL; + + pthread_mutex_unlock (&ffi_trampoline_lock); + + /* Initialize the return values */ + *code = entry->trampoline; + closure->trampoline_table = table; + closure->trampoline_table_entry = entry; + + return closure; +} + +void +ffi_closure_free (void *ptr) +{ + ffi_closure *closure = ptr; + + pthread_mutex_lock (&ffi_trampoline_lock); + + /* Fetch the table and entry references */ + ffi_trampoline_table *table = closure->trampoline_table; + ffi_trampoline_table_entry *entry = closure->trampoline_table_entry; + + /* Return the entry to the free list */ + entry->next = table->free_list; + table->free_list = entry; + table->free_count++; + + /* If all trampolines within this table are free, and at least one other table exists, deallocate + * the table */ + if (table->free_count == FFI_TRAMPOLINE_COUNT + && ffi_trampoline_tables != table) + { + ffi_trampoline_table_free (table); + } + else if (ffi_trampoline_tables != table) + { + /* Otherwise, bump this table to the top of the list */ + table->prev = NULL; + table->next = ffi_trampoline_tables; + if (ffi_trampoline_tables != NULL) + ffi_trampoline_tables->prev = table; + + ffi_trampoline_tables = table; + } + + pthread_mutex_unlock (&ffi_trampoline_lock); + + /* Free the closure */ + free (closure); +} + +#endif // Per-target implementation; It's unclear what can reasonable be shared between two OS/architecture implementations. -# elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */ +#elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */ #define USE_LOCKS 1 #define USE_DL_PREFIX 1 @@ -94,14 +397,6 @@ /* Don't allocate more than a page unless needed. */ #define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize) -#if FFI_CLOSURE_TEST -/* Don't release single pages, to avoid a worst-case scenario of - continuously allocating and releasing single pages, but release - pairs of pages, which should do just as well given that allocations - are likely to be small. */ -#define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize) -#endif - #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -111,7 +406,7 @@ #endif #include <string.h> #include <stdio.h> -#if !defined(X86_WIN32) && !defined(X86_WIN64) +#if !defined(_WIN32) #ifdef HAVE_MNTENT #include <mntent.h> #endif /* HAVE_MNTENT */ @@ -237,11 +532,11 @@ static int dlmalloc_trim(size_t) MAYBE_UNUSED; static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED; static void dlmalloc_stats(void) MAYBE_UNUSED; -#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) +#if !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) /* Use these for mmap and munmap within dlmalloc.c. */ static void *dlmmap(void *, size_t, int, int, int, off_t); static int dlmunmap(void *, size_t); -#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */ +#endif /* !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */ #define mmap dlmmap #define munmap dlmunmap @@ -251,7 +546,7 @@ static int dlmunmap(void *, size_t); #undef mmap #undef munmap -#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) +#if !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) /* A mutex used to synchronize access to *exec* variables in this file. */ static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -263,6 +558,17 @@ static int execfd = -1; /* The amount of space already allocated from the temporary file. */ static size_t execsize = 0; +#ifdef HAVE_MEMFD_CREATE +/* Open a temporary file name, and immediately unlink it. */ +static int +open_temp_exec_file_memfd (const char *name) +{ + int fd; + fd = memfd_create (name, MFD_CLOEXEC); + return fd; +} +#endif + /* Open a temporary file name, and immediately unlink it. */ static int open_temp_exec_file_name (char *name, int flags) @@ -308,7 +614,7 @@ open_temp_exec_file_dir (const char *dir) } #endif - lendir = strlen (dir); + lendir = (int) strlen (dir); tempname = __builtin_alloca (lendir + sizeof (suffix)); if (!tempname) @@ -390,6 +696,10 @@ static struct const char *arg; int repeat; } open_temp_exec_file_opts[] = { +#ifdef HAVE_MEMFD_CREATE + { open_temp_exec_file_memfd, "libffi", 0 }, +#endif + { open_temp_exec_file_env, "LIBFFI_TMPDIR", 0 }, { open_temp_exec_file_env, "TMPDIR", 0 }, { open_temp_exec_file_dir, "/tmp", 0 }, { open_temp_exec_file_dir, "/var/tmp", 0 }, @@ -449,6 +759,36 @@ open_temp_exec_file (void) return fd; } +/* We need to allocate space in a file that will be backing a writable + mapping. Several problems exist with the usual approaches: + - fallocate() is Linux-only + - posix_fallocate() is not available on all platforms + - ftruncate() does not allocate space on filesystems with sparse files + Failure to allocate the space will cause SIGBUS to be thrown when + the mapping is subsequently written to. */ +static int +allocate_space (int fd, off_t offset, off_t len) +{ + static size_t page_size; + + /* Obtain system page size. */ + if (!page_size) + page_size = sysconf(_SC_PAGESIZE); + + unsigned char buf[page_size]; + memset (buf, 0, page_size); + + while (len > 0) + { + off_t to_write = (len < page_size) ? len : page_size; + if (write (fd, buf, to_write) < to_write) + return -1; + len -= to_write; + } + + return 0; +} + /* Map in a chunk of memory from the temporary exec file into separate locations in the virtual memory address space, one writable and one executable. Returns the address of the writable portion, after @@ -470,7 +810,7 @@ dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset) offset = execsize; - if (ftruncate (execfd, offset + length)) + if (allocate_space (execfd, offset, length)) return MFAIL; flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS); @@ -485,7 +825,13 @@ dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset) close (execfd); goto retry_open; } - ftruncate (execfd, offset); + if (ftruncate (execfd, offset) != 0) + { + /* Fixme : Error logs can be added here. Returning an error for + * ftruncte() will not add any advantage as it is being + * validating in the error case. */ + } + return MFAIL; } else if (!offset @@ -497,7 +843,12 @@ dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset) if (start == MFAIL) { munmap (ptr, length); - ftruncate (execfd, offset); + if (ftruncate (execfd, offset) != 0) + { + /* Fixme : Error logs can be added here. Returning an error for + * ftruncte() will not add any advantage as it is being + * validating in the error case. */ + } return start; } @@ -521,9 +872,11 @@ dlmmap (void *start, size_t length, int prot, && flags == (MAP_PRIVATE | MAP_ANONYMOUS) && fd == -1 && offset == 0); -#if FFI_CLOSURE_TEST - printf ("mapping in %zi\n", length); -#endif + if (execfd == -1 && ffi_tramp_is_supported ()) + { + ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset); + return ptr; + } if (execfd == -1 && is_emutramp_enabled ()) { @@ -570,10 +923,6 @@ dlmunmap (void *start, size_t length) msegmentptr seg = segment_holding (gm, start); void *code; -#if FFI_CLOSURE_TEST - printf ("unmapping %zi\n", length); -#endif - if (seg && (code = add_segment_exec_offset (start, seg)) != start) { int ret = munmap (code, length); @@ -600,7 +949,7 @@ segment_holding_code (mstate m, char* addr) } #endif -#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */ +#endif /* !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */ /* Allocate a chunk of memory with the given size. Returns a pointer to the writable address, and sets *CODE to the executable @@ -608,23 +957,52 @@ segment_holding_code (mstate m, char* addr) void * ffi_closure_alloc (size_t size, void **code) { - void *ptr; + void *ptr, *ftramp; if (!code) return NULL; - ptr = dlmalloc (size); + ptr = FFI_CLOSURE_PTR (dlmalloc (size)); if (ptr) { msegmentptr seg = segment_holding (gm, ptr); *code = add_segment_exec_offset (ptr, seg); + if (!ffi_tramp_is_supported ()) + return ptr; + + ftramp = ffi_tramp_alloc (0); + if (ftramp == NULL) + { + dlfree (FFI_RESTORE_PTR (ptr)); + return NULL; + } + *code = ffi_tramp_get_addr (ftramp); + ((ffi_closure *) ptr)->ftramp = ftramp; } return ptr; } +void * +ffi_data_to_code_pointer (void *data) +{ + msegmentptr seg = segment_holding (gm, data); + /* We expect closures to be allocated with ffi_closure_alloc(), in + which case seg will be non-NULL. However, some users take on the + burden of managing this memory themselves, in which case this + we'll just return data. */ + if (seg) + { + if (!ffi_tramp_is_supported ()) + return add_segment_exec_offset (data, seg); + return ffi_tramp_get_addr (((ffi_closure *) data)->ftramp); + } + else + return data; +} + /* Release a chunk of memory allocated with ffi_closure_alloc. If FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the writable or the executable address given. Otherwise, only the @@ -638,30 +1016,19 @@ ffi_closure_free (void *ptr) if (seg) ptr = sub_segment_exec_offset (ptr, seg); #endif + if (ffi_tramp_is_supported ()) + ffi_tramp_free (((ffi_closure *) ptr)->ftramp); - dlfree (ptr); + dlfree (FFI_RESTORE_PTR (ptr)); } - -#if FFI_CLOSURE_TEST -/* Do some internal sanity testing to make sure allocation and - deallocation of pages are working as intended. */ -int main () -{ - void *p[3]; -#define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0) -#define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0) - GET (0, malloc_getpagesize / 2); - GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*)); - PUT (1); - GET (1, 2 * malloc_getpagesize); - GET (2, malloc_getpagesize / 2); - PUT (1); - PUT (0); - PUT (2); - return 0; +int +ffi_tramp_is_present (void *ptr) +{ + msegmentptr seg = segment_holding (gm, ptr); + return seg != NULL && ffi_tramp_is_supported(); } -#endif /* FFI_CLOSURE_TEST */ + # else /* ! FFI_MMAP_EXEC_WRIT */ /* On many systems, memory returned by malloc is writable and @@ -675,14 +1042,28 @@ ffi_closure_alloc (size_t size, void **code) if (!code) return NULL; - return *code = malloc (size); + return *code = FFI_CLOSURE_PTR (malloc (size)); } void ffi_closure_free (void *ptr) { - free (ptr); + free (FFI_RESTORE_PTR (ptr)); +} + +void * +ffi_data_to_code_pointer (void *data) +{ + return data; +} + +int +ffi_tramp_is_present (__attribute__((unused)) void *ptr) +{ + return 0; } # endif /* ! FFI_MMAP_EXEC_WRIT */ #endif /* FFI_CLOSURES */ + +#endif /* NetBSD with PROT_MPROTECT */ diff --git a/libffi/src/cris/ffi.c b/libffi/src/cris/ffi.c index aaca5b1..9011fde 100644 --- a/libffi/src/cris/ffi.c +++ b/libffi/src/cris/ffi.c @@ -29,7 +29,7 @@ #include <ffi.h> #include <ffi_common.h> -#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) +#define STACK_ARG_SIZE(x) FFI_ALIGN(x, FFI_SIZEOF_ARG) static ffi_status initialize_aggregate_packed_struct (ffi_type * arg) @@ -190,7 +190,7 @@ ffi_prep_cif_core (ffi_cif * cif, FFI_ASSERT_VALID_TYPE (*ptr); if (((*ptr)->alignment - 1) & bytes) - bytes = ALIGN (bytes, (*ptr)->alignment); + bytes = FFI_ALIGN (bytes, (*ptr)->alignment); if ((*ptr)->type == FFI_TYPE_STRUCT) { if ((*ptr)->size > 8) diff --git a/libffi/src/csky/ffi.c b/libffi/src/csky/ffi.c new file mode 100644 index 0000000..af50b7c --- /dev/null +++ b/libffi/src/csky/ffi.c @@ -0,0 +1,395 @@ +/* ----------------------------------------------------------------------- + ffi.c + + CSKY Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include <ffi.h> +#include <ffi_common.h> + +#include <stdlib.h> + +/* ffi_prep_args is called by the assembly routine once stack space + has been allocated for the function's arguments +*/ +void ffi_prep_args(char *stack, extended_cif *ecif) +{ + register unsigned int i; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + + argp = stack; + + if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { + *(void **) argp = ecif->rvalue; + argp += 4; + } + + p_argv = ecif->avalue; + + for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; + (i != 0); + i--, p_arg++) + { + size_t z; + size_t alignment; + + /* Align if necessary */ + alignment = (*p_arg)->alignment; +#ifdef __CSKYABIV1__ + /* + * Adapt ABIV1 bug. + * If struct's size is larger than 8 bytes, then it always alignment as 4 bytes. + */ + if (((*p_arg)->type == FFI_TYPE_STRUCT) && ((*p_arg)->size > 8) && (alignment == 8)) { + alignment = 4; + } +#endif + + if ((alignment - 1) & (unsigned) argp) { + argp = (char *) FFI_ALIGN(argp, alignment); + } + + if ((*p_arg)->type == FFI_TYPE_STRUCT) + argp = (char *) FFI_ALIGN(argp, 4); + + z = (*p_arg)->size; + if (z < sizeof(int)) + { + z = sizeof(int); + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); + break; + + case FFI_TYPE_UINT8: + *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); + break; + + case FFI_TYPE_SINT16: + *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); + break; + + case FFI_TYPE_UINT16: + *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); + break; + + case FFI_TYPE_STRUCT: +#ifdef __CSKYBE__ + memcpy((argp + 4 - (*p_arg)->size), *p_argv, (*p_arg)->size); +#else + memcpy(argp, *p_argv, (*p_arg)->size); +#endif + break; + + default: + FFI_ASSERT(0); + } + } + else if (z == sizeof(int)) + { + *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); + } + else + { + memcpy(argp, *p_argv, z); + } + p_argv++; + argp += z; + } + + return; +} + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + /* Round the stack up to a multiple of 8 bytes. This isn't needed + everywhere, but it is on some platforms, and it doesn't hcsky anything + when it isn't needed. */ + cif->bytes = (cif->bytes + 7) & ~7; + + /* Set the return type flag */ + switch (cif->rtype->type) + { + + case FFI_TYPE_DOUBLE: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + cif->flags = (unsigned) FFI_TYPE_SINT64; + break; + + case FFI_TYPE_STRUCT: + if (cif->rtype->size <= 4) + /* A Composite Type not larger than 4 bytes is returned in r0. */ + cif->flags = (unsigned)FFI_TYPE_INT; + else if (cif->rtype->size <= 8) + /* A Composite Type not larger than 8 bytes is returned in r0, r1. */ + cif->flags = (unsigned)FFI_TYPE_SINT64; + else + /* A Composite Type larger than 8 bytes, or whose size cannot + be determined statically ... is stored in memory at an + address passed [in r0]. */ + cif->flags = (unsigned)FFI_TYPE_STRUCT; + break; + + default: + cif->flags = FFI_TYPE_INT; + break; + } + + return FFI_OK; +} + +/* Perform machine dependent cif processing for variadic calls */ +ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, + unsigned int nfixedargs, + unsigned int ntotalargs) +{ + return ffi_prep_cif_machdep(cif); +} + +/* Prototypes for assembly functions, in sysv.S */ +extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *); + +void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + extended_cif ecif; + + int small_struct = (cif->flags == FFI_TYPE_INT + && cif->rtype->type == FFI_TYPE_STRUCT); + + ecif.cif = cif; + ecif.avalue = avalue; + + unsigned int temp; + + /* If the return value is a struct and we don't have a return */ + /* value address then we need to make one */ + + if ((rvalue == NULL) && + (cif->flags == FFI_TYPE_STRUCT)) + { + ecif.rvalue = alloca(cif->rtype->size); + } + else if (small_struct) + ecif.rvalue = &temp; + else + ecif.rvalue = rvalue; + + switch (cif->abi) + { + case FFI_SYSV: + ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue); + break; + + default: + FFI_ASSERT(0); + break; + } + if (small_struct) +#ifdef __CSKYBE__ + memcpy (rvalue, ((unsigned char *)&temp + (4 - cif->rtype->size)), cif->rtype->size); +#else + memcpy (rvalue, &temp, cif->rtype->size); +#endif +} + +/** private members **/ + +static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, + void** args, ffi_cif* cif); + +void ffi_closure_SYSV (ffi_closure *); + +/* This function is jumped to by the trampoline */ + +unsigned int +ffi_closure_SYSV_inner (closure, respp, args) + ffi_closure *closure; + void **respp; + void *args; +{ + // our various things... + ffi_cif *cif; + void **arg_area; + + cif = closure->cif; + arg_area = (void**) alloca (cif->nargs * sizeof (void*)); + + /* this call will initialize ARG_AREA, such that each + * element in that array points to the corresponding + * value on the stack; and if the function returns + * a structure, it will re-set RESP to point to the + * structure return address. */ + + ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif); + + (closure->fun) (cif, *respp, arg_area, closure->user_data); + +#ifdef __CSKYBE__ + if (cif->flags == FFI_TYPE_INT && cif->rtype->type == FFI_TYPE_STRUCT) { + unsigned int tmp = 0; + tmp = *(unsigned int *)(*respp); + *(unsigned int *)(*respp) = (tmp >> ((4 - cif->rtype->size) * 8)); + } +#endif + + return cif->flags; +} + + +static void +ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, + void **avalue, ffi_cif *cif) +{ + register unsigned int i; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + + argp = stack; + + if ( cif->flags == FFI_TYPE_STRUCT ) { + *rvalue = *(void **) argp; + argp += 4; + } + + p_argv = avalue; + + for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) + { + size_t z; + size_t alignment; + + alignment = (*p_arg)->alignment; + if (alignment < 4) + alignment = 4; + +#ifdef __CSKYABIV1__ + /* + * Adapt ABIV1 bug. + * If struct's size is larger than 8 bytes, then it always alignment as 4 bytes. + */ + if (((*p_arg)->type == FFI_TYPE_STRUCT) && ((*p_arg)->size > 8) && (alignment == 8)) { + alignment = 4; + } +#endif + + /* Align if necessary */ + if ((alignment - 1) & (unsigned) argp) { + argp = (char *) FFI_ALIGN(argp, alignment); + } + + z = (*p_arg)->size; + +#ifdef __CSKYBE__ + unsigned int tmp = 0; + if ((*p_arg)->size < 4) { + tmp = *(unsigned int *)argp; + memcpy(argp, ((unsigned char *)&tmp + (4 - (*p_arg)->size)), (*p_arg)->size); + } +#else + /* because we're little endian, this is what it turns into. */ +#endif + *p_argv = (void*) argp; + + p_argv++; + argp += z; + } + + return; +} + +/* How to make a trampoline. */ + +extern unsigned char ffi_csky_trampoline[TRAMPOLINE_SIZE]; + +/* + * Since there is no __clear_cache in libgcc in csky toolchain. + * define ffi_csky_cacheflush in sysv.S. + * void ffi_csky_cacheflush(uint32 start_addr, uint32 size, int cache) + */ +#define CACHEFLUSH_IN_FFI 1 +#if CACHEFLUSH_IN_FFI +extern void ffi_csky_cacheflush(unsigned char *__tramp, unsigned int k, + int i); +#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ +({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ + unsigned int __fun = (unsigned int)(FUN); \ + unsigned int __ctx = (unsigned int)(CTX); \ + unsigned char *insns = (unsigned char *)(CTX); \ + memcpy (__tramp, ffi_csky_trampoline, TRAMPOLINE_SIZE); \ + *(unsigned int*) &__tramp[TRAMPOLINE_SIZE] = __ctx; \ + *(unsigned int*) &__tramp[TRAMPOLINE_SIZE + 4] = __fun; \ + ffi_csky_cacheflush(&__tramp[0], TRAMPOLINE_SIZE, 3); /* Clear data mapping. */ \ + ffi_csky_cacheflush(insns, TRAMPOLINE_SIZE, 3); \ + /* Clear instruction \ + mapping. */ \ + }) +#else +#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ +({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ + unsigned int __fun = (unsigned int)(FUN); \ + unsigned int __ctx = (unsigned int)(CTX); \ + unsigned char *insns = (unsigned char *)(CTX); \ + memcpy (__tramp, ffi_csky_trampoline, TRAMPOLINE_SIZE); \ + *(unsigned int*) &__tramp[TRAMPOLINE_SIZE] = __ctx; \ + *(unsigned int*) &__tramp[TRAMPOLINE_SIZE + 4] = __fun; \ + __clear_cache((&__tramp[0]), (&__tramp[TRAMPOLINE_SIZE-1])); /* Clear data mapping. */ \ + __clear_cache(insns, insns + TRAMPOLINE_SIZE); \ + /* Clear instruction \ + mapping. */ \ + }) +#endif + +/* the cif must already be prep'ed */ + +ffi_status +ffi_prep_closure_loc (ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data, + void *codeloc) +{ + void (*closure_func)(ffi_closure*) = NULL; + + if (cif->abi == FFI_SYSV) + closure_func = &ffi_closure_SYSV; + else + return FFI_BAD_ABI; + + FFI_INIT_TRAMPOLINE (&closure->tramp[0], \ + closure_func, \ + codeloc); + + closure->cif = cif; + closure->user_data = user_data; + closure->fun = fun; + + return FFI_OK; +} + + diff --git a/libffi/src/csky/ffitarget.h b/libffi/src/csky/ffitarget.h new file mode 100644 index 0000000..f770aac --- /dev/null +++ b/libffi/src/csky/ffitarget.h @@ -0,0 +1,63 @@ +/* -----------------------------------------------------------------*-C-*- + ffitarget.h - Copyright (c) 2012 Anthony Green + Copyright (c) 2010 CodeSourcery + Copyright (c) 1996-2003 Red Hat, Inc. + + Target configuration macros for CSKY. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + ----------------------------------------------------------------------- */ + +#ifndef LIBFFI_TARGET_H +#define LIBFFI_TARGET_H + +#ifndef LIBFFI_H +#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." +#endif + +#ifndef LIBFFI_ASM +typedef unsigned long ffi_arg; +typedef signed long ffi_sarg; + +typedef enum ffi_abi { + FFI_FIRST_ABI = 0, + FFI_SYSV, + FFI_LAST_ABI, + FFI_DEFAULT_ABI = FFI_SYSV, +} ffi_abi; +#endif + +#ifdef __CSKYABIV2__ +#define FFI_ASM_ARGREG_SIZE 16 +#define TRAMPOLINE_SIZE 16 +#define FFI_TRAMPOLINE_SIZE 24 +#else +#define FFI_ASM_ARGREG_SIZE 24 +#define TRAMPOLINE_SIZE 20 +#define FFI_TRAMPOLINE_SIZE 28 +#endif + +/* ---- Definitions for closures ----------------------------------------- */ + +#define FFI_CLOSURES 1 +#define FFI_NATIVE_RAW_API 0 +#endif diff --git a/libffi/src/csky/sysv.S b/libffi/src/csky/sysv.S new file mode 100644 index 0000000..21670bf --- /dev/null +++ b/libffi/src/csky/sysv.S @@ -0,0 +1,371 @@ +/* ----------------------------------------------------------------------- + sysv.S + + CSKY Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM +#include <fficonfig.h> +#include <ffi.h> + +.macro CSKY_FUNC_START name + .text + .align 2 + .globl \name + .type \name, @function + \name: +.endm + +#ifdef __CSKYABIV2__ + + /* + * a0: fn + * a1: &ecif + * a2: cif->bytes + * a3: fig->flags + * sp+0: ecif.rvalue + */ +CSKY_FUNC_START ffi_call_SYSV + /* Save registers */ + .cfi_startproc + subi sp, 28 + .cfi_def_cfa_offset 28 + stw a0, (sp, 0x0) + .cfi_offset 0, -28 + stw a1, (sp, 0x4) + .cfi_offset 1, -24 + stw a2, (sp, 0x8) + .cfi_offset 2, -20 + stw a3, (sp, 0xC) + .cfi_offset 3, -16 + stw l0, (sp, 0x10) + .cfi_offset 4, -12 + stw l1, (sp, 0x14) + .cfi_offset 5, -8 + stw lr, (sp, 0x18) + .cfi_offset 15, -4 + + mov l0, sp + .cfi_def_cfa_register 4 + + /* Make room for all of the new args. */ + subu sp, sp, a2 + + /* Place all of the ffi_prep_args in position */ + mov a0, sp + /* a1 already set */ + + /* Call ffi_prep_args(stack, &ecif) */ + jsri ffi_prep_args + + /* move first 4 parameters in registers */ + ldw a0, (sp, 0x0) + ldw a1, (sp, 0x4) + ldw a2, (sp, 0x8) + ldw a3, (sp, 0xC) + + /* and adjust stack */ + subu lr, l0, sp /* cif->bytes == l0 - sp */ + cmphsi lr, 16 + movi l1, 16 + movt lr, l1 + addu sp, sp, lr + + ldw l1, (l0, 0) /* load fn() in advance */ + + /* call (fn) (...) */ + jsr l1 + + /* Remove the space we pushed for the args */ + mov sp, l0 + + /* Load r2 with the pointer to storage for the return value */ + ldw a2, (sp, 0x1C) + + /* Load r3 with the return type code */ + ldw a3, (sp, 0xC) + + /* If the return value pointer is NULL, assume no return value. */ + cmpnei a2, 0 + bf .Lepilogue + + cmpnei a3, FFI_TYPE_STRUCT + bf .Lepilogue + + /* return INT64 */ + cmpnei a3, FFI_TYPE_SINT64 + bt .Lretint + /* stw a0, (a2, 0x0) at .Lretint */ + stw a1, (a2, 0x4) + +.Lretint: + /* return INT */ + stw a0, (a2, 0x0) + +.Lepilogue: + ldw a0, (sp, 0x0) + ldw a1, (sp, 0x4) + ldw a2, (sp, 0x8) + ldw a3, (sp, 0xC) + ldw l0, (sp, 0x10) + ldw l1, (sp, 0x14) + ldw lr, (sp, 0x18) + addi sp, sp, 28 + rts + .cfi_endproc + .size ffi_call_SYSV, .-ffi_call_SYSV + + + /* + * unsigned int FFI_HIDDEN + * ffi_closure_SYSV_inner (closure, respp, args) + * ffi_closure *closure; + * void **respp; + * void *args; + */ +CSKY_FUNC_START ffi_closure_SYSV + .cfi_startproc + mov a2, sp + addi a1, sp, 16 + subi sp, sp, 24 + .cfi_def_cfa_offset 40 + stw a1, (sp, 0x10) + .cfi_offset 1, -24 + stw lr, (sp, 0x14) + .cfi_offset 15, -20 + stw sp, (sp, 0x8) + addi a1, sp, 8 + jsri ffi_closure_SYSV_inner + ldw a0, (sp, 0x0) + /* + * if FFI_TYPE_SINT64, need a1. + * if FFI_TYPE_INT, ignore a1. + */ + ldw a1, (sp, 0x4) + + ldw lr, (sp, 0x14) + addi sp, sp, 40 + rts + .cfi_endproc + .size ffi_closure_SYSV, .-ffi_closure_SYSV + +CSKY_FUNC_START ffi_csky_trampoline + subi sp, sp, 16 + stw a0, (sp, 0x0) + stw a1, (sp, 0x4) + stw a2, (sp, 0x8) + stw a3, (sp, 0xC) + lrw a0, [.Lctx] + lrw a1, [.Lfun] + jmp a1 +.Lctx: + mov a0, a0 + mov a0, a0 +.Lfun: + + .size ffi_csky_trampoline, .-ffi_csky_trampoline + +CSKY_FUNC_START ffi_csky_cacheflush + mov t0, r7 + movi r7, 123 + trap 0 + mov r7, t0 + rts + + .size ffi_csky_cacheflush, .-ffi_csky_cacheflush + +#else /* !__CSKYABIV2__ */ + + /* + * a0: fn + * a1: &ecif + * a2: cif->bytes + * a3: fig->flags + * a4: ecif.rvalue + */ +CSKY_FUNC_START ffi_call_SYSV + /* Save registers */ + .cfi_startproc + subi sp, 32 + subi sp, 8 + .cfi_def_cfa_offset 40 + stw a0, (sp, 0x0) + .cfi_offset 2, -40 + stw a1, (sp, 0x4) + .cfi_offset 3, -36 + stw a2, (sp, 0x8) + .cfi_offset 4, -32 + stw a3, (sp, 0xC) + .cfi_offset 5, -28 + stw a4, (sp, 0x10) + .cfi_offset 6, -24 + stw a5, (sp, 0x14) + .cfi_offset 7, -20 + stw l0, (sp, 0x18) + .cfi_offset 8, -16 + stw l1, (sp, 0x1C) + .cfi_offset 9, -12 + stw lr, (sp, 0x20) + .cfi_offset 15, -8 + + mov l0, sp + .cfi_def_cfa_register 8 + + /* Make room for all of the new args. */ + subu sp, sp, a2 + + /* Place all of the ffi_prep_args in position */ + mov a0, sp + /* a1 already set */ + + /* Call ffi_prep_args(stack, &ecif) */ + jsri ffi_prep_args + + /* move first 4 parameters in registers */ + ldw a0, (sp, 0x0) + ldw a1, (sp, 0x4) + ldw a2, (sp, 0x8) + ldw a3, (sp, 0xC) + ldw a4, (sp, 0x10) + ldw a5, (sp, 0x14) + + /* and adjust stack */ + mov lr, l0 + subu lr, sp /* cif->bytes == l0 - sp */ + movi l1, 24 + cmphs lr, l1 + movt lr, l1 + addu sp, sp, lr + + ldw l1, (l0, 0) /* load fn() in advance */ + + /* call (fn) (...) */ + jsr l1 + + /* Remove the space we pushed for the args */ + mov sp, l0 + + /* Load r2 with the pointer to storage for the return value */ + ldw a2, (sp, 0x10) + + /* Load r3 with the return type code */ + ldw a3, (sp, 0xC) + + /* If the return value pointer is NULL, assume no return value. */ + cmpnei a2, 0 + bf .Lepilogue + + cmpnei a3, FFI_TYPE_STRUCT + bf .Lepilogue + + /* return INT64 */ + cmpnei a3, FFI_TYPE_SINT64 + bt .Lretint + /* stw a0, (a2, 0x0) at .Lretint */ + stw a1, (a2, 0x4) + +.Lretint: + /* return INT */ + stw a0, (a2, 0x0) + +.Lepilogue: + ldw a0, (sp, 0x0) + ldw a1, (sp, 0x4) + ldw a2, (sp, 0x8) + ldw a3, (sp, 0xC) + ldw a4, (sp, 0x10) + ldw a5, (sp, 0x14) + ldw l0, (sp, 0x18) + ldw l1, (sp, 0x1C) + ldw lr, (sp, 0x20) + addi sp, sp, 32 + addi sp, sp, 8 + rts + .cfi_endproc + + .size ffi_call_SYSV, .-ffi_call_SYSV + + + /* + * unsigned int FFI_HIDDEN + * ffi_closure_SYSV_inner (closure, respp, args) + * ffi_closure *closure; + * void **respp; + * void *args; + */ +CSKY_FUNC_START ffi_closure_SYSV + .cfi_startproc + mov a2, sp + mov a1, sp + addi a1, 24 + subi sp, sp, 24 + .cfi_def_cfa_offset 48 + stw a1, (sp, 0x10) + .cfi_offset 3, -32 + stw lr, (sp, 0x14) + .cfi_offset 15, -28 + stw sp, (sp, 0x8) + mov a1, sp + addi a1, 8 + jsri ffi_closure_SYSV_inner + ldw a0, (sp, 0x0) + /* + * if FFI_TYPE_SINT64, need a1. + * if FFI_TYPE_INT, ignore a1. + */ + ldw a1, (sp, 0x4) + + ldw lr, (sp, 0x14) + addi sp, sp, 24 + addi sp, sp, 24 + rts + .cfi_endproc + + .size ffi_closure_SYSV, .-ffi_closure_SYSV + +CSKY_FUNC_START ffi_csky_trampoline + subi sp, 24 + stw a0, (sp, 0x0) + stw a1, (sp, 0x4) + stw a2, (sp, 0x8) + stw a3, (sp, 0xC) + stw a4, (sp, 0x10) + stw a5, (sp, 0x14) + lrw a0, [.Lctx] + lrw a1, [.Lfun] + jmp a1 +.Lctx: + mov a0, a0 + mov a0, a0 +.Lfun: + + .size ffi_csky_trampoline, .-ffi_csky_trampoline + +CSKY_FUNC_START ffi_csky_cacheflush + lrw r1, 123 + trap 0 + rts + + .size ffi_csky_cacheflush, .-ffi_csky_cacheflush + +#endif /* __CSKYABIV2__ */ diff --git a/libffi/src/dlmalloc.c b/libffi/src/dlmalloc.c index 7e4ea83..1aba657 100644 --- a/libffi/src/dlmalloc.c +++ b/libffi/src/dlmalloc.c @@ -438,6 +438,11 @@ DEFAULT_MMAP_THRESHOLD default: 256K */ +#if defined __linux__ && !defined _GNU_SOURCE +/* mremap() on Linux requires this via sys/mman.h */ +#define _GNU_SOURCE 1 +#endif + #ifndef WIN32 #ifdef _WIN32 #define WIN32 1 @@ -2366,7 +2371,7 @@ static size_t traverse_and_check(mstate m); #else /* GNUC */ #if USE_BUILTIN_FFS -#define compute_bit2idx(X, I) I = ffs(X)-1 +#define compute_bit2idx(X, I) I = __builtin_ffs(X)-1 #else /* USE_BUILTIN_FFS */ #define compute_bit2idx(X, I)\ diff --git a/libffi/src/frv/ffi.c b/libffi/src/frv/ffi.c index 5698c89..ed1c65a 100644 --- a/libffi/src/frv/ffi.c +++ b/libffi/src/frv/ffi.c @@ -107,7 +107,7 @@ void *ffi_prep_args(char *stack, extended_cif *ecif) count += z; } - return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8))); + return (stack + ((count > 24) ? 24 : FFI_ALIGN_DOWN(count, 8))); } /* Perform machine dependent cif processing */ @@ -118,7 +118,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) else cif->flags = cif->rtype->size; - cif->bytes = ALIGN (cif->bytes, 8); + cif->bytes = FFI_ALIGN (cif->bytes, 8); return FFI_OK; } diff --git a/libffi/src/ia64/ffi.c b/libffi/src/ia64/ffi.c index b77a836..b1d04c3 100644 --- a/libffi/src/ia64/ffi.c +++ b/libffi/src/ia64/ffi.c @@ -220,8 +220,8 @@ hfa_element_type (ffi_type *type, int nested) /* Perform machine dependent cif processing. */ -ffi_status -ffi_prep_cif_machdep(ffi_cif *cif) +static ffi_status +ffi_prep_cif_machdep_core(ffi_cif *cif) { int flags; @@ -271,6 +271,22 @@ ffi_prep_cif_machdep(ffi_cif *cif) return FFI_OK; } +ffi_status +ffi_prep_cif_machdep(ffi_cif *cif) +{ + cif->nfixedargs = cif->nargs; + return ffi_prep_cif_machdep_core(cif); +} + +ffi_status +ffi_prep_cif_machdep_var(ffi_cif *cif, + unsigned int nfixedargs, + unsigned int ntotalargs MAYBE_UNUSED) +{ + cif->nfixedargs = nfixedargs; + return ffi_prep_cif_machdep_core(cif); +} + extern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(void), UINT64); void @@ -454,10 +470,11 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, ffi_cif *cif; void **avalue; ffi_type **p_arg; - long i, avn, gpcount, fpcount; + long i, avn, gpcount, fpcount, nfixedargs; cif = closure->cif; avn = cif->nargs; + nfixedargs = cif->nfixedargs; avalue = alloca (avn * sizeof (void *)); /* If the structure return value is passed in memory get that location @@ -468,6 +485,7 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, gpcount = fpcount = 0; for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) { + int named = i < nfixedargs; switch ((*p_arg)->type) { case FFI_TYPE_SINT8: @@ -491,7 +509,7 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, break; case FFI_TYPE_FLOAT: - if (gpcount < 8 && fpcount < 8) + if (named && gpcount < 8 && fpcount < 8) { fpreg *addr = &stack->fp_regs[fpcount++]; float result; @@ -505,7 +523,7 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, break; case FFI_TYPE_DOUBLE: - if (gpcount < 8 && fpcount < 8) + if (named && gpcount < 8 && fpcount < 8) { fpreg *addr = &stack->fp_regs[fpcount++]; double result; @@ -521,7 +539,7 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, case FFI_TYPE_LONGDOUBLE: if (gpcount & 1) gpcount++; - if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8) + if (LDBL_MANT_DIG == 64 && named && gpcount < 8 && fpcount < 8) { fpreg *addr = &stack->fp_regs[fpcount++]; __float80 result; diff --git a/libffi/src/ia64/ffitarget.h b/libffi/src/ia64/ffitarget.h index e68cea6..fd5b9a0 100644 --- a/libffi/src/ia64/ffitarget.h +++ b/libffi/src/ia64/ffitarget.h @@ -50,6 +50,7 @@ typedef enum ffi_abi { #define FFI_TRAMPOLINE_SIZE 24 /* Really the following struct, which */ /* can be interpreted as a C function */ /* descriptor: */ +#define FFI_TARGET_SPECIFIC_VARIADIC 1 +#define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs #endif - diff --git a/libffi/src/ia64/unix.S b/libffi/src/ia64/unix.S index 4d2a86d..e2547e0 100644 --- a/libffi/src/ia64/unix.S +++ b/libffi/src/ia64/unix.S @@ -175,7 +175,6 @@ ffi_call_unix: ;; .Lst_small_struct: - add sp = -16, sp cmp.lt p6, p0 = 8, in3 cmp.lt p7, p0 = 16, in3 cmp.lt p8, p0 = 24, in3 @@ -191,6 +190,12 @@ ffi_call_unix: (p8) st8 [r18] = r11 mov out1 = sp mov out2 = in3 + ;; + // ia64 software calling convention requires + // top 16 bytes of stack to be scratch space + // PLT resolver uses that scratch space at + // 'memcpy' symbol reolution time + add sp = -16, sp br.call.sptk.many b0 = memcpy# ;; mov ar.pfs = loc0 @@ -529,6 +534,7 @@ ffi_closure_unix: data8 @pcrel(.Lst_int64) // FFI_TYPE_SINT64 data8 @pcrel(.Lst_void) // FFI_TYPE_STRUCT data8 @pcrel(.Lst_int64) // FFI_TYPE_POINTER + data8 @pcrel(.Lst_void) // FFI_TYPE_COMPLEX (not implemented) data8 @pcrel(.Lst_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT data8 @pcrel(.Lst_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT data8 @pcrel(.Lst_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE @@ -550,6 +556,7 @@ ffi_closure_unix: data8 @pcrel(.Lld_int) // FFI_TYPE_SINT64 data8 @pcrel(.Lld_void) // FFI_TYPE_STRUCT data8 @pcrel(.Lld_int) // FFI_TYPE_POINTER + data8 @pcrel(.Lld_void) // FFI_TYPE_COMPLEX (not implemented) data8 @pcrel(.Lld_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT data8 @pcrel(.Lld_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT data8 @pcrel(.Lld_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE diff --git a/libffi/src/java_raw_api.c b/libffi/src/java_raw_api.c index 127123d..114d3e4 100644 --- a/libffi/src/java_raw_api.c +++ b/libffi/src/java_raw_api.c @@ -114,7 +114,7 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args) default: *args = raw; raw += - ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); + FFI_ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); } } @@ -142,7 +142,7 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args) #else /* FFI_SIZEOF_JAVA_RAW != 8 */ *args = (void*) raw; raw += - ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); + FFI_ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); #endif /* FFI_SIZEOF_JAVA_RAW == 8 */ } @@ -234,7 +234,7 @@ ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw) #else memcpy ((void*) raw->data, (void*)*args, (*tp)->size); raw += - ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); + FFI_ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); #endif } } diff --git a/libffi/src/kvx/asm.h b/libffi/src/kvx/asm.h new file mode 100644 index 0000000..4edba41 --- /dev/null +++ b/libffi/src/kvx/asm.h @@ -0,0 +1,5 @@ +/* args are passed on registers from r0 up to r11 => 12*8 bytes */ +#define REG_ARGS_SIZE (12*8) +#define KVX_REGISTER_SIZE (8) +#define KVX_ABI_SLOT_SIZE (KVX_REGISTER_SIZE) +#define KVX_ABI_MAX_AGGREGATE_IN_REG_SIZE (4*KVX_ABI_SLOT_SIZE) diff --git a/libffi/src/kvx/ffi.c b/libffi/src/kvx/ffi.c new file mode 100644 index 0000000..58f6aef --- /dev/null +++ b/libffi/src/kvx/ffi.c @@ -0,0 +1,273 @@ +/* Copyright (c) 2020 Kalray + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#if defined(__kvx__) +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <fficonfig.h> +#include <ffi.h> +#include "ffi_common.h" +#include "asm.h" + +#define ALIGN(x, a) ALIGN_MASK(x, (typeof(x))(a) - 1) +#define ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define KVX_ABI_STACK_ALIGNMENT (32) +#define KVX_ABI_STACK_ARG_ALIGNMENT (8) +#define max(a,b) ((a) > (b) ? (a) : (b)) + +#ifdef FFI_DEBUG +#define DEBUG_PRINT(...) do{ fprintf( stderr, __VA_ARGS__ ); } while(0) +#else +#define DEBUG_PRINT(...) +#endif + +struct ret_value { + unsigned long int r0; + unsigned long int r1; + unsigned long int r2; + unsigned long int r3; +}; + +extern struct ret_value ffi_call_SYSV(unsigned total_size, + unsigned size, + extended_cif *ecif, + unsigned *rvalue_addr, + void *fn, + unsigned int_ext_method); + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + cif->flags = cif->rtype->size; + return FFI_OK; +} + +/* ffi_prep_args is called by the assembly routine once stack space + has been allocated for the function's arguments */ + +void *ffi_prep_args(char *stack, unsigned int arg_slots_size, extended_cif *ecif) +{ + char *stacktemp = stack; + char *current_arg_passed_by_value = stack + arg_slots_size; + int i, s; + ffi_type **arg; + int count = 0; + ffi_cif *cif = ecif->cif; + void **argv = ecif->avalue; + + arg = cif->arg_types; + + DEBUG_PRINT("stack: %p\n", stack); + DEBUG_PRINT("arg_slots_size: %u\n", arg_slots_size); + DEBUG_PRINT("current_arg_passed_by_value: %p\n", current_arg_passed_by_value); + DEBUG_PRINT("ecif: %p\n", ecif); + DEBUG_PRINT("ecif->avalue: %p\n", ecif->avalue); + + for (i = 0; i < cif->nargs; i++) { + + s = KVX_ABI_SLOT_SIZE; + switch((*arg)->type) { + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + case FFI_TYPE_POINTER: + DEBUG_PRINT("INT64/32/16/8/FLOAT/DOUBLE or POINTER @%p\n", stack); + *(uint64_t *) stack = *(uint64_t *)(* argv); + break; + + case FFI_TYPE_COMPLEX: + if ((*arg)->size == 8) + *(_Complex float *) stack = *(_Complex float *)(* argv); + else if ((*arg)->size == 16) { + *(_Complex double *) stack = *(_Complex double *)(* argv); + s = 16; + } else + abort(); + break; + case FFI_TYPE_STRUCT: { + char *value; + unsigned int written_size = 0; + DEBUG_PRINT("struct by value @%p\n", stack); + if ((*arg)->size > KVX_ABI_MAX_AGGREGATE_IN_REG_SIZE) { + DEBUG_PRINT("big struct\n"); + *(uint64_t *) stack = (uintptr_t)current_arg_passed_by_value; + value = current_arg_passed_by_value; + current_arg_passed_by_value += (*arg)->size; + written_size = KVX_ABI_SLOT_SIZE; + } else { + value = stack; + written_size = (*arg)->size; + } + memcpy(value, *argv, (*arg)->size); + s = ALIGN(written_size, KVX_ABI_STACK_ARG_ALIGNMENT); + break; + } + default: + printf("Error: unsupported arg type %d\n", (*arg)->type); + abort(); + break; + + } + stack += s; + count += s; + argv++; + arg++; + } +#ifdef FFI_DEBUG + FFI_ASSERT(((intptr_t)(stacktemp + REG_ARGS_SIZE) & (KVX_ABI_STACK_ALIGNMENT-1)) == 0); +#endif + return stacktemp + REG_ARGS_SIZE; +} + +/* Perform machine dependent cif processing when we have a variadic function */ + +ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, + unsigned int ntotalargs) +{ + cif->flags = cif->rtype->size; + return FFI_OK; +} + +static unsigned long handle_small_int_ext(kvx_intext_method *int_ext_method, + const ffi_type *rtype) +{ + switch (rtype->type) { + case FFI_TYPE_SINT8: + *int_ext_method = KVX_RET_SXBD; + return KVX_REGISTER_SIZE; + + case FFI_TYPE_SINT16: + *int_ext_method = KVX_RET_SXHD; + return KVX_REGISTER_SIZE; + + case FFI_TYPE_SINT32: + *int_ext_method = KVX_RET_SXWD; + return KVX_REGISTER_SIZE; + + case FFI_TYPE_UINT8: + *int_ext_method = KVX_RET_ZXBD; + return KVX_REGISTER_SIZE; + + case FFI_TYPE_UINT16: + *int_ext_method = KVX_RET_ZXHD; + return KVX_REGISTER_SIZE; + + case FFI_TYPE_UINT32: + *int_ext_method = KVX_RET_ZXWD; + return KVX_REGISTER_SIZE; + + default: + *int_ext_method = KVX_RET_NONE; + return rtype->size; + } +} + +void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + int i; + unsigned long int slot_fitting_args_size = 0; + unsigned long int total_size = 0; + unsigned long int big_struct_size = 0; + kvx_intext_method int_extension_method; + ffi_type **arg; + struct ret_value local_rvalue = {0}; + size_t wb_size; + + + /* Calculate size to allocate on stack */ + for (i = 0, arg = cif->arg_types; i < cif->nargs; i++, arg++) { + DEBUG_PRINT("argument %d, type %d, size %lu\n", i, (*arg)->type, (*arg)->size); + if (((*arg)->type == FFI_TYPE_STRUCT) || ((*arg)->type == FFI_TYPE_COMPLEX)) { + if ((*arg)->size <= KVX_ABI_MAX_AGGREGATE_IN_REG_SIZE) { + slot_fitting_args_size += ALIGN((*arg)->size, KVX_ABI_SLOT_SIZE); + } else { + slot_fitting_args_size += KVX_ABI_SLOT_SIZE; /* aggregate passed by reference */ + big_struct_size += ALIGN((*arg)->size, KVX_ABI_SLOT_SIZE); + } + } else if ((*arg)->size <= KVX_ABI_SLOT_SIZE) { + slot_fitting_args_size += KVX_ABI_SLOT_SIZE; + } else { + printf("Error: unsupported arg size %ld arg type %d\n", (*arg)->size, (*arg)->type); + abort(); /* should never happen? */ + } + } + + extended_cif ecif; + ecif.cif = cif; + ecif.avalue = avalue; + ecif.rvalue = rvalue; + + /* This implementation allocates anyway for all register based args */ + slot_fitting_args_size = max(slot_fitting_args_size, REG_ARGS_SIZE); + total_size = slot_fitting_args_size + big_struct_size; + total_size = ALIGN(total_size, KVX_ABI_STACK_ALIGNMENT); + + /* wb_size: write back size, the size we will need to write back to user + * provided buffer. In theory it should always be cif->flags which is + * cif->rtype->size. But libffi API mandates that for integral types + * of size <= system register size, then we *MUST* write back + * the size of system register size. + * in our case, if size <= 8 bytes we must write back 8 bytes. + * floats, complex and structs are not affected, only integrals. + */ + wb_size = handle_small_int_ext(&int_extension_method, cif->rtype); + + switch (cif->abi) { + case FFI_SYSV: + DEBUG_PRINT("total_size: %lu\n", total_size); + DEBUG_PRINT("slot fitting args size: %lu\n", slot_fitting_args_size); + DEBUG_PRINT("rvalue: %p\n", rvalue); + DEBUG_PRINT("fn: %p\n", fn); + DEBUG_PRINT("rsize: %u\n", cif->flags); + DEBUG_PRINT("wb_size: %u\n", wb_size); + DEBUG_PRINT("int_extension_method: %u\n", int_extension_method); + local_rvalue = ffi_call_SYSV(total_size, slot_fitting_args_size, + &ecif, rvalue, fn, int_extension_method); + if ((cif->flags <= KVX_ABI_MAX_AGGREGATE_IN_REG_SIZE) + && (cif->rtype->type != FFI_TYPE_VOID)) + memcpy(rvalue, &local_rvalue, wb_size); + break; + default: + abort(); + break; + } +} + +/* Closures not supported yet */ +ffi_status +ffi_prep_closure_loc (ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data, + void *codeloc) +{ + return FFI_BAD_ABI; +} + +#endif /* (__kvx__) */ diff --git a/libffi/src/kvx/ffitarget.h b/libffi/src/kvx/ffitarget.h new file mode 100644 index 0000000..8df8735 --- /dev/null +++ b/libffi/src/kvx/ffitarget.h @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------- + ffitarget.h - Copyright (c) 2020 Kalray + + KVX Target configuration macros + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#ifndef LIBFFI_TARGET_H +#define LIBFFI_TARGET_H + +#ifndef LIBFFI_H +#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." +#endif + +/* ---- System specific configurations ----------------------------------- */ + +#ifndef LIBFFI_ASM +typedef unsigned long ffi_arg; +typedef signed long ffi_sarg; + +typedef enum ffi_abi { + FFI_FIRST_ABI = 0, + FFI_SYSV, + FFI_LAST_ABI, + FFI_DEFAULT_ABI = FFI_SYSV +} ffi_abi; + +/* Those values are set depending on return type + * they are used in the assembly code in sysv.S + */ +typedef enum kvx_intext_method { + KVX_RET_NONE = 0, + KVX_RET_SXBD = 1, + KVX_RET_SXHD = 2, + KVX_RET_SXWD = 3, + KVX_RET_ZXBD = 4, + KVX_RET_ZXHD = 5, + KVX_RET_ZXWD = 6 +} kvx_intext_method; + +#endif + +/* ---- Definitions for closures ----------------------------------------- */ + +/* This is only to allow Python to compile + * but closures are not supported yet + */ +#define FFI_CLOSURES 1 +#define FFI_TRAMPOLINE_SIZE 0 + +#define FFI_NATIVE_RAW_API 0 +#define FFI_TARGET_SPECIFIC_VARIADIC 1 +#define FFI_TARGET_HAS_COMPLEX_TYPE + +#endif + diff --git a/libffi/src/kvx/sysv.S b/libffi/src/kvx/sysv.S new file mode 100644 index 0000000..952afc7 --- /dev/null +++ b/libffi/src/kvx/sysv.S @@ -0,0 +1,127 @@ +/* Copyright (c) 2020 Kalray + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#if defined(__kvx__) +#define LIBFFI_ASM +#include <fficonfig.h> +#include <ffi.h> +#include <ffi_cfi.h> +#include <kvx/asm.h> + +.text +.global ffi_call_SYSV +.type ffi_call_SYSV, @function +.type ffi_prep_args, @function +.align 8 + +/* ffi_call_SYSV + + r0: total size to allocate on stack + r1: size of arg slots + r2: extended cif structure, DO NOT REMOVE: it is used by ffi_prep_args() + r3: return value address + r4: function to call + r5: integer sign extension method to be used +*/ +ffi_call_SYSV: + addd $r12 = $r12, -64 + so (-32)[$r12] = $r20r21r22r23 + ;; + sd (0)[$r12] = $r24 + ;; + get $r23 = $ra + copyd $r20 = $r12 + sbfd $r12 = $r0, $r12 + ;; + copyd $r0 = $r12 + copyd $r21 = $r3 + copyd $r22 = $r4 + copyd $r24 = $r5 + call ffi_prep_args + ;; + lo $r8r9r10r11 = (64)[$r12] + ;; + lo $r4r5r6r7 = (32)[$r12] + ;; + lo $r0r1r2r3 = (0)[$r12] + copyd $r12 = $r0 + /* $r15 is the register used by the ABI to return big (>32 bytes) + * structs by value. + * It is also referred to as the "struct register" in the ABI. + */ + copyd $r15 = $r21 + icall $r22 + ;; + pcrel $r4 = @pcrel(.Ltable) + cb.deqz $r24 ? .Lend + ;; + addx8d $r24 = $r24, $r4 + ;; + igoto $r24 + ;; +.Ltable: +0: /* we should never arrive here */ + goto .Lerror + nop + ;; +1: /* Sign extend byte to double */ + sxbd $r0 = $r0 + goto .Lend + ;; +2: /* Sign extend half to double */ + sxhd $r0 = $r0 + goto .Lend + ;; +3: /* Sign extend word to double */ + sxwd $r0 = $r0 + goto .Lend + ;; +4: /* Zero extend byte to double */ + zxbd $r0 = $r0 + goto .Lend + ;; +5: /* Zero extend half to double */ + zxhd $r0 = $r0 + goto .Lend + ;; +6: /* Zero extend word to double */ + zxwd $r0 = $r0 + /* Fallthrough to .Lend */ + ;; +.Lend: + ld $r24 = (0)[$r12] + ;; + set $ra = $r23 + lo $r20r21r22r23 = (32)[$r20] + addd $r12 = $r20, 64 + ;; + ret + ;; +.Lerror: + errop + ;; + +#endif /* __kvx__ */ + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",%progbits +#endif + diff --git a/libffi/src/m32r/ffi.c b/libffi/src/m32r/ffi.c index 3000063..ab8fc4e 100644 --- a/libffi/src/m32r/ffi.c +++ b/libffi/src/m32r/ffi.c @@ -61,7 +61,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif) /* Align if necessary. */ if (((*p_arg)->alignment - 1) & (unsigned) argp) - argp = (char *) ALIGN (argp, (*p_arg)->alignment); + argp = (char *) FFI_ALIGN (argp, (*p_arg)->alignment); if (avn != 0) { diff --git a/libffi/src/m68k/ffi.c b/libffi/src/m68k/ffi.c index 0dee938..0330184 100644 --- a/libffi/src/m68k/ffi.c +++ b/libffi/src/m68k/ffi.c @@ -105,7 +105,7 @@ ffi_prep_args (void *stack, extended_cif *ecif) /* Align if necessary. */ if ((sizeof(int) - 1) & z) - z = ALIGN(z, sizeof(int)); + z = FFI_ALIGN(z, sizeof(int)); } p_argv++; @@ -297,7 +297,7 @@ ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif) /* Align if necessary */ if ((sizeof(int) - 1) & z) - z = ALIGN(z, sizeof(int)); + z = FFI_ALIGN(z, sizeof(int)); } p_argv++; diff --git a/libffi/src/m68k/sysv.S b/libffi/src/m68k/sysv.S index ec2b14f..ea40f11 100644 --- a/libffi/src/m68k/sysv.S +++ b/libffi/src/m68k/sysv.S @@ -3,7 +3,7 @@ sysv.S - Copyright (c) 2012 Alan Hourihane Copyright (c) 1998, 2012 Andreas Schwab Copyright (c) 2008 Red Hat, Inc. - Copyright (c) 2012 Thorsten Glaser + Copyright (c) 2012, 2016 Thorsten Glaser m68k Foreign Function Interface @@ -72,6 +72,15 @@ CALLFUNC(ffi_call_SYSV): pea 4(%sp) #if !defined __PIC__ jsr CALLFUNC(ffi_prep_args) +#elif defined(__uClinux__) && defined(__ID_SHARED_LIBRARY__) + move.l _current_shared_library_a5_offset_(%a5),%a0 + move.l CALLFUNC(ffi_prep_args@GOT)(%a0),%a0 + jsr (%a0) +#elif defined(__mcoldfire__) && !defined(__mcfisab__) && !defined(__mcfisac__) + move.l #_GLOBAL_OFFSET_TABLE_@GOTPC,%a0 + lea (-6,%pc,%a0),%a0 + move.l CALLFUNC(ffi_prep_args@GOT)(%a0),%a0 + jsr (%a0) #else bsr.l CALLFUNC(ffi_prep_args@PLTPC) #endif @@ -215,6 +224,15 @@ CALLFUNC(ffi_closure_SYSV): move.l %a0,-(%sp) #if !defined __PIC__ jsr CALLFUNC(ffi_closure_SYSV_inner) +#elif defined(__uClinux__) && defined(__ID_SHARED_LIBRARY__) + move.l _current_shared_library_a5_offset_(%a5),%a0 + move.l CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0 + jsr (%a0) +#elif defined(__mcoldfire__) && !defined(__mcfisab__) && !defined(__mcfisac__) + move.l #_GLOBAL_OFFSET_TABLE_@GOTPC,%a0 + lea (-6,%pc,%a0),%a0 + move.l CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0 + jsr (%a0) #else bsr.l CALLFUNC(ffi_closure_SYSV_inner@PLTPC) #endif @@ -317,6 +335,15 @@ CALLFUNC(ffi_closure_struct_SYSV): move.l %a0,-(%sp) #if !defined __PIC__ jsr CALLFUNC(ffi_closure_SYSV_inner) +#elif defined(__uClinux__) && defined(__ID_SHARED_LIBRARY__) + move.l _current_shared_library_a5_offset_(%a5),%a0 + move.l CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0 + jsr (%a0) +#elif defined(__mcoldfire__) && !defined(__mcfisab__) && !defined(__mcfisac__) + move.l #_GLOBAL_OFFSET_TABLE_@GOTPC,%a0 + lea (-6,%pc,%a0),%a0 + move.l CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0 + jsr (%a0) #else bsr.l CALLFUNC(ffi_closure_SYSV_inner@PLTPC) #endif diff --git a/libffi/src/m88k/ffi.c b/libffi/src/m88k/ffi.c index 68df494..57b344f 100644 --- a/libffi/src/m88k/ffi.c +++ b/libffi/src/m88k/ffi.c @@ -134,7 +134,7 @@ ffi_prep_args (void *stack, extended_cif *ecif) /* Enforce proper stack alignment of 64-bit types */ if (argp == stackp && a > sizeof (int)) { - stackp = (char *) ALIGN(stackp, a); + stackp = (char *) FFI_ALIGN(stackp, a); argp = stackp; } @@ -177,7 +177,7 @@ ffi_prep_args (void *stack, extended_cif *ecif) /* Align if necessary. */ if ((sizeof (int) - 1) & z) - z = ALIGN(z, sizeof (int)); + z = FFI_ALIGN(z, sizeof (int)); p_argv++; @@ -320,7 +320,7 @@ ffi_prep_closure_args_OBSD (ffi_cif *cif, void **avalue, unsigned int *regp, /* Enforce proper stack alignment of 64-bit types */ if (argp == stackp && a > sizeof (int)) { - stackp = (char *) ALIGN(stackp, a); + stackp = (char *) FFI_ALIGN(stackp, a); argp = stackp; } @@ -331,7 +331,7 @@ ffi_prep_closure_args_OBSD (ffi_cif *cif, void **avalue, unsigned int *regp, /* Align if necessary */ if ((sizeof (int) - 1) & z) - z = ALIGN(z, sizeof (int)); + z = FFI_ALIGN(z, sizeof (int)); p_argv++; diff --git a/libffi/src/metag/ffi.c b/libffi/src/metag/ffi.c index 46b383e..3aecb0b 100644 --- a/libffi/src/metag/ffi.c +++ b/libffi/src/metag/ffi.c @@ -61,7 +61,7 @@ unsigned int ffi_prep_args(char *stack, extended_cif *ecif) argp -= z; /* Align if necessary */ - argp = (char *) ALIGN_DOWN(ALIGN_DOWN(argp, (*p_arg)->alignment), 4); + argp = (char *) FFI_ALIGN_DOWN(FFI_ALIGN_DOWN(argp, (*p_arg)->alignment), 4); if (z < sizeof(int)) { z = sizeof(int); @@ -93,7 +93,7 @@ unsigned int ffi_prep_args(char *stack, extended_cif *ecif) /* return the size of the arguments to be passed in registers, padded to an 8 byte boundary to preserve stack alignment */ - return ALIGN(MIN(stack - argp, 6*4), 8); + return FFI_ALIGN(MIN(stack - argp, 6*4), 8); } /* Perform machine dependent cif processing */ @@ -112,20 +112,20 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) /* Add any padding if necessary */ if (((*ptr)->alignment - 1) & bytes) - bytes = ALIGN(bytes, (*ptr)->alignment); + bytes = FFI_ALIGN(bytes, (*ptr)->alignment); - bytes += ALIGN((*ptr)->size, 4); + bytes += FFI_ALIGN((*ptr)->size, 4); } /* Ensure arg space is aligned to an 8-byte boundary */ - bytes = ALIGN(bytes, 8); + bytes = FFI_ALIGN(bytes, 8); /* Make space for the return structure pointer */ if (cif->rtype->type == FFI_TYPE_STRUCT) { bytes += sizeof(void*); /* Ensure stack is aligned to an 8-byte boundary */ - bytes = ALIGN(bytes, 8); + bytes = FFI_ALIGN(bytes, 8); } cif->bytes = bytes; @@ -319,7 +319,7 @@ static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, if (alignment < 4) alignment = 4; if ((alignment - 1) & (unsigned)argp) - argp = (char *) ALIGN(argp, alignment); + argp = (char *) FFI_ALIGN(argp, alignment); z = (*p_arg)->size; *p_argv = (void*) argp; diff --git a/libffi/src/microblaze/ffi.c b/libffi/src/microblaze/ffi.c index ea962ea..df6e33c 100644 --- a/libffi/src/microblaze/ffi.c +++ b/libffi/src/microblaze/ffi.c @@ -35,7 +35,7 @@ extern void ffi_closure_SYSV(void); #define WORD_SIZE sizeof(unsigned int) #define ARGS_REGISTER_SIZE (WORD_SIZE * 6) -#define WORD_ALIGN(x) ALIGN(x, WORD_SIZE) +#define WORD_FFI_ALIGN(x) FFI_ALIGN(x, WORD_SIZE) /* ffi_prep_args is called by the assembly routine once stack space has been allocated for the function's arguments */ @@ -46,12 +46,12 @@ void ffi_prep_args(void* stack, extended_cif* ecif) void** p_argv; void* stack_args_p = stack; - p_argv = ecif->avalue; - if (ecif == NULL || ecif->cif == NULL) { return; /* no description to prepare */ } + p_argv = ecif->avalue; + if ((ecif->cif->rtype != NULL) && (ecif->cif->rtype->type == FFI_TYPE_STRUCT)) { @@ -74,7 +74,7 @@ void ffi_prep_args(void* stack, extended_cif* ecif) int type = (*p_arg)->type; void* value = p_argv[i]; char* addr = stack_args_p; - int aligned_size = WORD_ALIGN(size); + int aligned_size = WORD_FFI_ALIGN(size); /* force word alignment on the stack */ stack_args_p += aligned_size; @@ -259,7 +259,7 @@ void ffi_closure_call_SYSV(void* register_args, void* stack_args, avalue[i] = ptr; break; } - ptr += WORD_ALIGN(arg_types[i]->size); + ptr += WORD_FFI_ALIGN(arg_types[i]->size); } /* set the return type info passed back to the wrapper */ diff --git a/libffi/src/mips/ffi.c b/libffi/src/mips/ffi.c index ecd783a..979ca49 100644 --- a/libffi/src/mips/ffi.c +++ b/libffi/src/mips/ffi.c @@ -29,6 +29,7 @@ #include <ffi.h> #include <ffi_common.h> +#include <stdint.h> #include <stdlib.h> #ifdef __GNUC__ @@ -38,7 +39,9 @@ #endif #ifndef USE__BUILTIN___CLEAR_CACHE -# if defined(__OpenBSD__) +# if defined(__FreeBSD__) +# include <machine/sysarch.h> +# elif defined(__OpenBSD__) # include <mips64/sysarch.h> # else # include <sys/cachectl.h> @@ -116,7 +119,7 @@ static void ffi_prep_args(char *stack, if ((a - 1) & (unsigned long) argp) { - argp = (char *) ALIGN(argp, a); + argp = (char *) FFI_ALIGN(argp, a); FIX_ARGP; } @@ -247,7 +250,7 @@ calc_n32_struct_flags(int soft_float, ffi_type *arg, while ((e = arg->elements[index])) { /* Align this object. */ - *loc = ALIGN(*loc, e->alignment); + *loc = FFI_ALIGN(*loc, e->alignment); if (e->type == FFI_TYPE_DOUBLE) { /* Already aligned to FFI_SIZEOF_ARG. */ @@ -262,7 +265,7 @@ calc_n32_struct_flags(int soft_float, ffi_type *arg, index++; } /* Next Argument register at alignment of FFI_SIZEOF_ARG. */ - *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + *arg_reg = FFI_ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; return flags; } @@ -322,9 +325,10 @@ calc_n32_return_struct_flags(int soft_float, ffi_type *arg) #endif /* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs) { cif->flags = 0; + cif->mips_nfixedargs = nfixedargs; #ifdef FFI_MIPS_O32 /* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT @@ -333,7 +337,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32) { - if (cif->nargs > 0) + if (cif->nargs > 0 && cif->nargs == nfixedargs) { switch ((cif->arg_types)[0]->type) { @@ -450,7 +454,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) while (count-- > 0 && arg_reg < 8) { type = (cif->arg_types)[index]->type; - if (soft_float) + + // Pass variadic arguments in integer registers even if they're floats + if (soft_float || index >= nfixedargs) { switch (type) { @@ -474,9 +480,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) break; case FFI_TYPE_LONGDOUBLE: /* Align it. */ - arg_reg = ALIGN(arg_reg, 2); + arg_reg = FFI_ALIGN(arg_reg, 2); /* Treat it as two adjacent doubles. */ - if (soft_float) + if (soft_float || index >= nfixedargs) { arg_reg += 2; } @@ -493,7 +499,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) case FFI_TYPE_STRUCT: loc = arg_reg * FFI_SIZEOF_ARG; - cif->flags += calc_n32_struct_flags(soft_float, + cif->flags += calc_n32_struct_flags(soft_float || index >= nfixedargs, (cif->arg_types)[index], &loc, &arg_reg); break; @@ -578,17 +584,30 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) return FFI_OK; } +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + return ffi_prep_cif_machdep_int(cif, cif->nargs); +} + +ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, + unsigned nfixedargs, + unsigned ntotalargs MAYBE_UNUSED) +{ + return ffi_prep_cif_machdep_int(cif, nfixedargs); +} + /* Low level routine for calling O32 functions */ extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int), extended_cif *, unsigned, - unsigned, unsigned *, void (*)(void)); + unsigned, unsigned *, void (*)(void), void *closure); /* Low level routine for calling N32 functions */ extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), extended_cif *, unsigned, - unsigned, void *, void (*)(void)); + unsigned, void *, void (*)(void), void *closure); -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +void ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) { extended_cif ecif; @@ -610,7 +629,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) case FFI_O32: case FFI_O32_SOFT_FLOAT: ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); + cif->flags, ecif.rvalue, fn, closure); break; #endif @@ -642,7 +661,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) #endif } ffi_call_N32(ffi_prep_args, &ecif, cif->bytes, - cif->flags, rvalue_copy, fn); + cif->flags, rvalue_copy, fn, closure); if (copy_rvalue) memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size); } @@ -655,11 +674,27 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) } } +void +ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + ffi_call_int (cif, fn, rvalue, avalue, NULL); +} + +void +ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) +{ + ffi_call_int (cif, fn, rvalue, avalue, closure); +} + + #if FFI_CLOSURES #if defined(FFI_MIPS_O32) extern void ffi_closure_O32(void); +extern void ffi_go_closure_O32(void); #else extern void ffi_closure_N32(void); +extern void ffi_go_closure_N32(void); #endif /* FFI_MIPS_O32 */ ffi_status @@ -744,11 +779,13 @@ ffi_prep_closure_loc (ffi_closure *closure, closure->fun = fun; closure->user_data = user_data; +#if !defined(__FreeBSD__) #ifdef USE__BUILTIN___CLEAR_CACHE __builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE); #else cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE); #endif +#endif /* ! __FreeBSD__ */ return FFI_OK; } @@ -770,27 +807,28 @@ ffi_prep_closure_loc (ffi_closure *closure, * Based on the similar routine for sparc. */ int -ffi_closure_mips_inner_O32 (ffi_closure *closure, +ffi_closure_mips_inner_O32 (ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, void *rvalue, ffi_arg *ar, double *fpr) { - ffi_cif *cif; void **avaluep; ffi_arg *avalue; ffi_type **arg_types; int i, avn, argn, seen_int; - cif = closure->cif; avalue = alloca (cif->nargs * sizeof (ffi_arg)); avaluep = alloca (cif->nargs * sizeof (ffi_arg)); - seen_int = (cif->abi == FFI_O32_SOFT_FLOAT); + seen_int = (cif->abi == FFI_O32_SOFT_FLOAT) || (cif->mips_nfixedargs != cif->nargs); argn = 0; if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT) { - rvalue = (void *)(UINT32)ar[0]; + rvalue = (void *)(uintptr_t)ar[0]; argn = 1; + seen_int = 1; } i = 0; @@ -799,6 +837,8 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure, while (i < avn) { + if (arg_types[i]->alignment == 8 && (argn & 0x1)) + argn++; if (i < 2 && !seen_int && (arg_types[i]->type == FFI_TYPE_FLOAT || arg_types[i]->type == FFI_TYPE_DOUBLE || @@ -813,8 +853,6 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure, } else { - if (arg_types[i]->alignment == 8 && (argn & 0x1)) - argn++; switch (arg_types[i]->type) { case FFI_TYPE_SINT8: @@ -843,12 +881,12 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure, } seen_int = 1; } - argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + argn += FFI_ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; i++; } /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avaluep, closure->user_data); + fun(cif, rvalue, avaluep, user_data); if (cif->abi == FFI_O32_SOFT_FLOAT) { @@ -884,7 +922,7 @@ copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type, char *argp; char *fpp; - o = ALIGN(offset, elt_type->alignment); + o = FFI_ALIGN(offset, elt_type->alignment); arg_offset += o - offset; offset = o; argn += arg_offset / sizeof(ffi_arg); @@ -924,11 +962,12 @@ copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type, * */ int -ffi_closure_mips_inner_N32 (ffi_closure *closure, +ffi_closure_mips_inner_N32 (ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, void *rvalue, ffi_arg *ar, ffi_arg *fpr) { - ffi_cif *cif; void **avaluep; ffi_arg *avalue; ffi_type **arg_types; @@ -936,7 +975,6 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure, int soft_float; ffi_arg *argp; - cif = closure->cif; soft_float = cif->abi == FFI_N64_SOFT_FLOAT || cif->abi == FFI_N32_SOFT_FLOAT; avalue = alloca (cif->nargs * sizeof (ffi_arg)); @@ -964,10 +1002,10 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure, || arg_types[i]->type == FFI_TYPE_DOUBLE || arg_types[i]->type == FFI_TYPE_LONGDOUBLE) { - argp = (argn >= 8 || soft_float) ? ar + argn : fpr + argn; - if ((arg_types[i]->type == FFI_TYPE_LONGDOUBLE) && ((unsigned)argp & (arg_types[i]->alignment-1))) + argp = (argn >= 8 || i >= cif->mips_nfixedargs || soft_float) ? ar + argn : fpr + argn; + if ((arg_types[i]->type == FFI_TYPE_LONGDOUBLE) && ((uintptr_t)argp & (arg_types[i]->alignment-1))) { - argp=(ffi_arg*)ALIGN(argp,arg_types[i]->alignment); + argp=(ffi_arg*)FFI_ALIGN(argp,arg_types[i]->alignment); argn++; } #if defined(__MIPSEB__) || defined(_MIPSEB) @@ -982,7 +1020,7 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure, unsigned type = arg_types[i]->type; if (arg_types[i]->alignment > sizeof(ffi_arg)) - argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg)); + argn = FFI_ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg)); argp = ar + argn; @@ -1033,7 +1071,7 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure, it was passed in registers. */ avaluep[i] = alloca(arg_types[i]->size); copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i], - argn, 0, ar, fpr, soft_float); + argn, 0, ar, fpr, i >= cif->mips_nfixedargs || soft_float); break; } @@ -1043,16 +1081,54 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure, break; } } - argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg); + argn += FFI_ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg); i++; } /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avaluep, closure->user_data); + fun (cif, rvalue, avaluep, user_data); return cif->flags >> (FFI_FLAG_BITS * 8); } #endif /* FFI_MIPS_N32 */ +#if defined(FFI_MIPS_O32) +extern void ffi_closure_O32(void); +extern void ffi_go_closure_O32(void); +#else +extern void ffi_closure_N32(void); +extern void ffi_go_closure_N32(void); +#endif /* FFI_MIPS_O32 */ + +ffi_status +ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*)) +{ + void * fn; + +#if defined(FFI_MIPS_O32) + if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT) + return FFI_BAD_ABI; + fn = ffi_go_closure_O32; +#else +#if _MIPS_SIM ==_ABIN32 + if (cif->abi != FFI_N32 + && cif->abi != FFI_N32_SOFT_FLOAT) + return FFI_BAD_ABI; +#else + if (cif->abi != FFI_N64 + && cif->abi != FFI_N64_SOFT_FLOAT) + return FFI_BAD_ABI; +#endif + fn = ffi_go_closure_N32; +#endif /* FFI_MIPS_O32 */ + + closure->tramp = (void *)fn; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} + #endif /* FFI_CLOSURES */ diff --git a/libffi/src/mips/ffitarget.h b/libffi/src/mips/ffitarget.h index 717d659..fdd5ca9 100644 --- a/libffi/src/mips/ffitarget.h +++ b/libffi/src/mips/ffitarget.h @@ -32,7 +32,7 @@ #error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." #endif -#ifdef linux +#ifdef __linux__ # include <asm/sgidefs.h> #elif defined(__rtems__) /* @@ -41,7 +41,7 @@ #define _MIPS_SIM_ABI32 1 #define _MIPS_SIM_NABI32 2 #define _MIPS_SIM_ABI64 3 -#elif !defined(__OpenBSD__) +#elif !defined(__OpenBSD__) && !defined(__FreeBSD__) # include <sgidefs.h> #endif @@ -224,24 +224,21 @@ typedef enum ffi_abi { #endif } ffi_abi; -#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag +#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag; unsigned mips_nfixedargs +#define FFI_TARGET_SPECIFIC_VARIADIC #endif /* !LIBFFI_ASM */ /* ---- Definitions for closures ----------------------------------------- */ -#if defined(FFI_MIPS_O32) #define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 20 -#else -/* N32/N64. */ -# define FFI_CLOSURES 1 -#if _MIPS_SIM==_ABI64 -#define FFI_TRAMPOLINE_SIZE 52 +#define FFI_GO_CLOSURES 1 +#define FFI_NATIVE_RAW_API 0 + +#if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32) +# define FFI_TRAMPOLINE_SIZE 20 #else -#define FFI_TRAMPOLINE_SIZE 20 +# define FFI_TRAMPOLINE_SIZE 56 #endif -#endif /* FFI_MIPS_O32 */ -#define FFI_NATIVE_RAW_API 0 #endif diff --git a/libffi/src/mips/n32.S b/libffi/src/mips/n32.S index 06e6c46..23b77fd 100644 --- a/libffi/src/mips/n32.S +++ b/libffi/src/mips/n32.S @@ -37,8 +37,12 @@ #define flags a3 #define raddr a4 #define fn a5 +#define closure a6 -#define SIZEOF_FRAME ( 8 * FFI_SIZEOF_ARG ) +/* Note: to keep stack 16 byte aligned we need even number slots + used 9 slots here +*/ +#define SIZEOF_FRAME ( 10 * FFI_SIZEOF_ARG ) #ifdef __GNUC__ .abicalls @@ -51,24 +55,25 @@ .globl ffi_call_N32 .ent ffi_call_N32 ffi_call_N32: -.LFB3: +.LFB0: .frame $fp, SIZEOF_FRAME, ra .mask 0xc0000000,-FFI_SIZEOF_ARG .fmask 0x00000000,0 # Prologue SUBU $sp, SIZEOF_FRAME # Frame size -.LCFI0: +.LCFI00: REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address -.LCFI1: +.LCFI01: move $fp, $sp -.LCFI3: +.LCFI02: move t9, callback # callback function pointer REG_S bytes, 2*FFI_SIZEOF_ARG($fp) # bytes REG_S flags, 3*FFI_SIZEOF_ARG($fp) # flags REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn + REG_S closure, 6*FFI_SIZEOF_ARG($fp) # closure # Allocate at least 4 words in the argstack move v0, bytes @@ -109,6 +114,16 @@ loadregs: REG_L t6, 3*FFI_SIZEOF_ARG($fp) # load the flags word into t6. +#ifdef __mips_soft_float + REG_L a0, 0*FFI_SIZEOF_ARG(t9) + REG_L a1, 1*FFI_SIZEOF_ARG(t9) + REG_L a2, 2*FFI_SIZEOF_ARG(t9) + REG_L a3, 3*FFI_SIZEOF_ARG(t9) + REG_L a4, 4*FFI_SIZEOF_ARG(t9) + REG_L a5, 5*FFI_SIZEOF_ARG(t9) + REG_L a6, 6*FFI_SIZEOF_ARG(t9) + REG_L a7, 7*FFI_SIZEOF_ARG(t9) +#else and t4, t6, ((1<<FFI_FLAG_BITS)-1) REG_L a0, 0*FFI_SIZEOF_ARG(t9) beqz t4, arg1_next @@ -195,11 +210,15 @@ arg7_next: arg8_doublep: l.d $f19, 7*FFI_SIZEOF_ARG(t9) arg8_next: +#endif callit: # Load the function pointer REG_L t9, 5*FFI_SIZEOF_ARG($fp) + # install the static chain(t7=$15) + REG_L t7, 6*FFI_SIZEOF_ARG($fp) + # If the return value pointer is NULL, assume no return value. REG_L t5, 4*FFI_SIZEOF_ARG($fp) beqz t5, noretval @@ -216,6 +235,7 @@ retint: b epilogue retfloat: +#ifndef __mips_soft_float bne t6, FFI_TYPE_FLOAT, retdouble jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) @@ -274,6 +294,7 @@ retstruct_f_d: s.s $f0, 0(t4) s.d $f2, 8(t4) b epilogue +#endif retstruct_d_soft: bne t6, FFI_TYPE_STRUCT_D_SOFT, retstruct_f_soft @@ -348,7 +369,7 @@ epilogue: ADDU $sp, SIZEOF_FRAME # Fix stack pointer j ra -.LFE3: +.LFE0: .end ffi_call_N32 /* ffi_closure_N32. Expects address of the passed-in ffi_closure in t0 @@ -408,6 +429,41 @@ epilogue: #define GP_OFF2 (0 * FFI_SIZEOF_ARG) .align 2 + .globl ffi_go_closure_N32 + .ent ffi_go_closure_N32 +ffi_go_closure_N32: +.LFB1: + .frame $sp, SIZEOF_FRAME2, ra + .mask 0x90000000,-(SIZEOF_FRAME2 - RA_OFF2) + .fmask 0x00000000,0 + SUBU $sp, SIZEOF_FRAME2 +.LCFI10: + .cpsetup t9, GP_OFF2, ffi_go_closure_N32 + REG_S ra, RA_OFF2($sp) # Save return address +.LCFI11: + + REG_S a0, A0_OFF2($sp) + REG_S a1, A1_OFF2($sp) + REG_S a2, A2_OFF2($sp) + REG_S a3, A3_OFF2($sp) + REG_S a4, A4_OFF2($sp) + REG_S a5, A5_OFF2($sp) + + # Call ffi_closure_mips_inner_N32 to do the real work. + LA t9, ffi_closure_mips_inner_N32 + REG_L a0, 8($15) # cif + REG_L a1, 16($15) # fun + move a2, t7 # userdata=closure + ADDU a3, $sp, V0_OFF2 # rvalue + ADDU a4, $sp, A0_OFF2 # ar + ADDU a5, $sp, F12_OFF2 # fpr + + b $do_closure + +.LFE1: + .end ffi_go_closure_N32 + + .align 2 .globl ffi_closure_N32 .ent ffi_closure_N32 ffi_closure_N32: @@ -416,21 +472,33 @@ ffi_closure_N32: .mask 0x90000000,-(SIZEOF_FRAME2 - RA_OFF2) .fmask 0x00000000,0 SUBU $sp, SIZEOF_FRAME2 -.LCFI5: +.LCFI20: .cpsetup t9, GP_OFF2, ffi_closure_N32 REG_S ra, RA_OFF2($sp) # Save return address -.LCFI6: - # Store all possible argument registers. If there are more than - # fit in registers, then they were stored on the stack. +.LCFI21: REG_S a0, A0_OFF2($sp) REG_S a1, A1_OFF2($sp) REG_S a2, A2_OFF2($sp) REG_S a3, A3_OFF2($sp) REG_S a4, A4_OFF2($sp) REG_S a5, A5_OFF2($sp) + + # Call ffi_closure_mips_inner_N32 to do the real work. + LA t9, ffi_closure_mips_inner_N32 + REG_L a0, 56($12) # cif + REG_L a1, 64($12) # fun + REG_L a2, 72($12) # user_data + ADDU a3, $sp, V0_OFF2 + ADDU a4, $sp, A0_OFF2 + ADDU a5, $sp, F12_OFF2 + +$do_closure: + # Store all possible argument registers. If there are more than + # fit in registers, then they were stored on the stack. REG_S a6, A6_OFF2($sp) REG_S a7, A7_OFF2($sp) +#ifndef __mips_soft_float # Store all possible float/double registers. s.d $f12, F12_OFF2($sp) s.d $f13, F13_OFF2($sp) @@ -440,13 +508,8 @@ ffi_closure_N32: s.d $f17, F17_OFF2($sp) s.d $f18, F18_OFF2($sp) s.d $f19, F19_OFF2($sp) +#endif - # Call ffi_closure_mips_inner_N32 to do the real work. - LA t9, ffi_closure_mips_inner_N32 - move a0, $12 # Pointer to the ffi_closure - ADDU a1, $sp, V0_OFF2 - ADDU a2, $sp, A0_OFF2 - ADDU a3, $sp, F12_OFF2 jalr t9 # Return flags are in v0 @@ -460,6 +523,7 @@ cls_retint: b cls_epilogue cls_retfloat: +#ifndef __mips_soft_float bne v0, FFI_TYPE_FLOAT, cls_retdouble l.s $f0, V0_OFF2($sp) b cls_epilogue @@ -502,6 +566,7 @@ cls_retstruct_f_d: l.s $f0, V0_OFF2($sp) l.d $f2, V1_OFF2($sp) b cls_epilogue +#endif cls_retstruct_small2: REG_L v0, V0_OFF2($sp) @@ -517,7 +582,7 @@ cls_epilogue: .end ffi_closure_N32 #ifdef __GNUC__ - .section .eh_frame,"aw",@progbits + .section .eh_frame,EH_FRAME_FLAGS,@progbits .Lframe1: .4byte .LECIE1-.LSCIE1 # length .LSCIE1: @@ -533,46 +598,66 @@ cls_epilogue: .align EH_FRAME_ALIGN .LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 # length. -.LASFDE1: - .4byte .LASFDE1-.Lframe1 # CIE_pointer. - FDE_ADDR_BYTES .LFB3 # initial_location. - FDE_ADDR_BYTES .LFE3-.LFB3 # address_range. +.LSFDE0: + .4byte .LEFDE0-.LASFDE0 # length. +.LASFDE0: + .4byte .LASFDE0-.Lframe1 # CIE_pointer. + FDE_ADDR_BYTES .LFB0 # initial_location. + FDE_ADDR_BYTES .LFE0-.LFB0 # address_range. .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI0-.LFB3 # to .LCFI0 + .4byte .LCFI00-.LFB0 # to .LCFI00 .byte 0xe # DW_CFA_def_cfa_offset .uleb128 SIZEOF_FRAME # adjust stack.by SIZEOF_FRAME .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI1-.LCFI0 # to .LCFI1 + .4byte .LCFI01-.LCFI00 # to .LCFI01 .byte 0x9e # DW_CFA_offset of $fp .uleb128 2*FFI_SIZEOF_ARG/4 # .byte 0x9f # DW_CFA_offset of ra .uleb128 1*FFI_SIZEOF_ARG/4 # .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI3-.LCFI1 # to .LCFI3 + .4byte .LCFI02-.LCFI01 # to .LCFI02 .byte 0xd # DW_CFA_def_cfa_register .uleb128 0x1e # in $fp .align EH_FRAME_ALIGN +.LEFDE0: + +.LSFDE1: + .4byte .LEFDE1-.LASFDE1 # length +.LASFDE1: + .4byte .LASFDE1-.Lframe1 # CIE_pointer. + FDE_ADDR_BYTES .LFB1 # initial_location. + FDE_ADDR_BYTES .LFE1-.LFB1 # address_range. + .byte 0x4 # DW_CFA_advance_loc4 + .4byte .LCFI10-.LFB1 # to .LCFI10 + .byte 0xe # DW_CFA_def_cfa_offset + .uleb128 SIZEOF_FRAME2 # adjust stack.by SIZEOF_FRAME + .byte 0x4 # DW_CFA_advance_loc4 + .4byte .LCFI11-.LCFI10 # to .LCFI11 + .byte 0x9c # DW_CFA_offset of $gp ($28) + .uleb128 (SIZEOF_FRAME2 - GP_OFF2)/4 + .byte 0x9f # DW_CFA_offset of ra ($31) + .uleb128 (SIZEOF_FRAME2 - RA_OFF2)/4 + .align EH_FRAME_ALIGN .LEFDE1: -.LSFDE3: - .4byte .LEFDE3-.LASFDE3 # length -.LASFDE3: - .4byte .LASFDE3-.Lframe1 # CIE_pointer. + +.LSFDE2: + .4byte .LEFDE2-.LASFDE2 # length +.LASFDE2: + .4byte .LASFDE2-.Lframe1 # CIE_pointer. FDE_ADDR_BYTES .LFB2 # initial_location. FDE_ADDR_BYTES .LFE2-.LFB2 # address_range. .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI5-.LFB2 # to .LCFI5 + .4byte .LCFI20-.LFB2 # to .LCFI20 .byte 0xe # DW_CFA_def_cfa_offset .uleb128 SIZEOF_FRAME2 # adjust stack.by SIZEOF_FRAME .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI6-.LCFI5 # to .LCFI6 + .4byte .LCFI21-.LCFI20 # to .LCFI21 .byte 0x9c # DW_CFA_offset of $gp ($28) .uleb128 (SIZEOF_FRAME2 - GP_OFF2)/4 .byte 0x9f # DW_CFA_offset of ra ($31) .uleb128 (SIZEOF_FRAME2 - RA_OFF2)/4 .align EH_FRAME_ALIGN -.LEFDE3: +.LEFDE2: #endif /* __GNUC__ */ #endif diff --git a/libffi/src/mips/o32.S b/libffi/src/mips/o32.S index eb27981..799139b 100644 --- a/libffi/src/mips/o32.S +++ b/libffi/src/mips/o32.S @@ -50,14 +50,14 @@ ffi_call_O32: $LFB0: # Prologue SUBU $sp, SIZEOF_FRAME # Frame size -$LCFI0: +$LCFI00: REG_S $fp, FP_OFF($sp) # Save frame pointer -$LCFI1: +$LCFI01: REG_S ra, RA_OFF($sp) # Save return address -$LCFI2: +$LCFI02: move $fp, $sp -$LCFI3: +$LCFI03: move t9, callback # callback function pointer REG_S flags, A3_OFF($fp) # flags @@ -82,13 +82,16 @@ sixteen: ADDU $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args +#ifndef __mips_soft_float bnez t0, pass_d # make it quick for int +#endif REG_L a0, 0*FFI_SIZEOF_ARG($sp) # just go ahead and load the REG_L a1, 1*FFI_SIZEOF_ARG($sp) # four regs. REG_L a2, 2*FFI_SIZEOF_ARG($sp) REG_L a3, 3*FFI_SIZEOF_ARG($sp) b call_it +#ifndef __mips_soft_float pass_d: bne t0, FFI_ARGS_D, pass_f l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args @@ -130,8 +133,12 @@ pass_f_d: # bne t0, FFI_ARGS_F_D, call_it l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float +#endif call_it: + # Load the static chain pointer + REG_L t7, SIZEOF_FRAME + 6*FFI_SIZEOF_ARG($fp) + # Load the function pointer REG_L t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp) @@ -158,14 +165,23 @@ retfloat: bne t2, FFI_TYPE_FLOAT, retdouble jalr t9 REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) +#ifndef __mips_soft_float s.s $f0, 0(t0) +#else + REG_S v0, 0(t0) +#endif b epilogue retdouble: bne t2, FFI_TYPE_DOUBLE, noretval jalr t9 REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) +#ifndef __mips_soft_float s.d $f0, 0(t0) +#else + REG_S v1, 4(t0) + REG_S v0, 0(t0) +#endif b epilogue noretval: @@ -204,13 +220,15 @@ $LFE0: -8 - f14 (le low, be high) -9 - f12 (le high, be low) -10 - f12 (le low, be high) - -11 - Called function a3 save - -12 - Called function a2 save - -13 - Called function a1 save - -14 - Called function a0 save, our sp and fp point here + -11 - Called function a5 save + -12 - Called function a4 save + -13 - Called function a3 save + -14 - Called function a2 save + -15 - Called function a1 save + -16 - Called function a0 save, our sp and fp point here */ -#define SIZEOF_FRAME2 (14 * FFI_SIZEOF_ARG) +#define SIZEOF_FRAME2 (16 * FFI_SIZEOF_ARG) #define A3_OFF2 (SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG) #define A2_OFF2 (SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG) #define A1_OFF2 (SIZEOF_FRAME2 + 1 * FFI_SIZEOF_ARG) @@ -225,13 +243,73 @@ $LFE0: #define FA_1_0_OFF2 (SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG) #define FA_0_1_OFF2 (SIZEOF_FRAME2 - 9 * FFI_SIZEOF_ARG) #define FA_0_0_OFF2 (SIZEOF_FRAME2 - 10 * FFI_SIZEOF_ARG) +#define CALLED_A5_OFF2 (SIZEOF_FRAME2 - 11 * FFI_SIZEOF_ARG) +#define CALLED_A4_OFF2 (SIZEOF_FRAME2 - 12 * FFI_SIZEOF_ARG) .text + + .align 2 + .globl ffi_go_closure_O32 + .ent ffi_go_closure_O32 +ffi_go_closure_O32: +$LFB1: + # Prologue + .frame $fp, SIZEOF_FRAME2, ra + .set noreorder + .cpload t9 + .set reorder + SUBU $sp, SIZEOF_FRAME2 + .cprestore GP_OFF2 +$LCFI10: + + REG_S $16, S0_OFF2($sp) # Save s0 + REG_S $fp, FP_OFF2($sp) # Save frame pointer + REG_S ra, RA_OFF2($sp) # Save return address +$LCFI11: + + move $fp, $sp +$LCFI12: + + REG_S a0, A0_OFF2($fp) + REG_S a1, A1_OFF2($fp) + REG_S a2, A2_OFF2($fp) + REG_S a3, A3_OFF2($fp) + + # Load ABI enum to s0 + REG_L $16, 4($15) # cif + REG_L $16, 0($16) # abi is first member. + + li $13, 1 # FFI_O32 + bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT + +#ifndef __mips_soft_float + # Store all possible float/double registers. + s.d $f12, FA_0_0_OFF2($fp) + s.d $f14, FA_1_0_OFF2($fp) +#endif +1: + # prepare arguments for ffi_closure_mips_inner_O32 + REG_L a0, 4($15) # cif + REG_L a1, 8($15) # fun + move a2, $15 # user_data = go closure + addu a3, $fp, V0_OFF2 # rvalue + + addu t9, $fp, A0_OFF2 # ar + REG_S t9, CALLED_A4_OFF2($fp) + + addu t9, $fp, FA_0_0_OFF2 #fpr + REG_S t9, CALLED_A5_OFF2($fp) + + b $do_closure + +$LFE1: + .end ffi_go_closure_O32 + .align 2 .globl ffi_closure_O32 .ent ffi_closure_O32 ffi_closure_O32: -$LFB1: +$LFB2: # Prologue .frame $fp, SIZEOF_FRAME2, ra .set noreorder @@ -239,14 +317,14 @@ $LFB1: .set reorder SUBU $sp, SIZEOF_FRAME2 .cprestore GP_OFF2 -$LCFI4: +$LCFI20: REG_S $16, S0_OFF2($sp) # Save s0 REG_S $fp, FP_OFF2($sp) # Save frame pointer REG_S ra, RA_OFF2($sp) # Save return address -$LCFI6: +$LCFI21: move $fp, $sp -$LCFI7: +$LCFI22: # Store all possible argument registers. If there are more than # four arguments, then they are stored above where we put a3. REG_S a0, A0_OFF2($fp) @@ -261,16 +339,27 @@ $LCFI7: li $13, 1 # FFI_O32 bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT +#ifndef __mips_soft_float # Store all possible float/double registers. s.d $f12, FA_0_0_OFF2($fp) s.d $f14, FA_1_0_OFF2($fp) +#endif 1: - # Call ffi_closure_mips_inner_O32 to do the work. + # prepare arguments for ffi_closure_mips_inner_O32 + REG_L a0, 20($12) # cif pointer follows tramp. + REG_L a1, 24($12) # fun + REG_L a2, 28($12) # user_data + addu a3, $fp, V0_OFF2 # rvalue + + addu t9, $fp, A0_OFF2 # ar + REG_S t9, CALLED_A4_OFF2($fp) + + addu t9, $fp, FA_0_0_OFF2 #fpr + REG_S t9, CALLED_A5_OFF2($fp) + +$do_closure: la t9, ffi_closure_mips_inner_O32 - move a0, $12 # Pointer to the ffi_closure - addu a1, $fp, V0_OFF2 - addu a2, $fp, A0_OFF2 - addu a3, $fp, FA_0_0_OFF2 + # Call ffi_closure_mips_inner_O32 to do the work. jalr t9 # Load the return value into the appropriate register. @@ -281,6 +370,7 @@ $LCFI7: li $13, 1 # FFI_O32 bne $16, $13, 1f # Skip fp restore if FFI_O32_SOFT_FLOAT +#ifndef __mips_soft_float li $9, FFI_TYPE_FLOAT l.s $f0, V0_OFF2($fp) beq $8, $9, closure_done @@ -288,6 +378,7 @@ $LCFI7: li $9, FFI_TYPE_DOUBLE l.d $f0, V0_OFF2($fp) beq $8, $9, closure_done +#endif 1: REG_L $3, V1_OFF2($fp) REG_L $2, V0_OFF2($fp) @@ -300,7 +391,7 @@ closure_done: REG_L ra, RA_OFF2($sp) # Restore return address ADDU $sp, SIZEOF_FRAME2 j ra -$LFE1: +$LFE2: .end ffi_closure_O32 /* DWARF-2 unwind info. */ @@ -322,6 +413,7 @@ $LSCIE0: .uleb128 0x0 .align 2 $LECIE0: + $LSFDE0: .4byte $LEFDE0-$LASFDE0 # FDE Length $LASFDE0: @@ -330,11 +422,11 @@ $LASFDE0: .4byte $LFE0-$LFB0 # FDE address range .uleb128 0x0 # Augmentation size .byte 0x4 # DW_CFA_advance_loc4 - .4byte $LCFI0-$LFB0 + .4byte $LCFI00-$LFB0 .byte 0xe # DW_CFA_def_cfa_offset .uleb128 0x18 .byte 0x4 # DW_CFA_advance_loc4 - .4byte $LCFI2-$LCFI0 + .4byte $LCFI01-$LCFI00 .byte 0x11 # DW_CFA_offset_extended_sf .uleb128 0x1e # $fp .sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) @@ -342,12 +434,13 @@ $LASFDE0: .uleb128 0x1f # $ra .sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) .byte 0x4 # DW_CFA_advance_loc4 - .4byte $LCFI3-$LCFI2 + .4byte $LCFI02-$LCFI01 .byte 0xc # DW_CFA_def_cfa .uleb128 0x1e .uleb128 0x18 .align 2 $LEFDE0: + $LSFDE1: .4byte $LEFDE1-$LASFDE1 # FDE Length $LASFDE1: @@ -356,11 +449,11 @@ $LASFDE1: .4byte $LFE1-$LFB1 # FDE address range .uleb128 0x0 # Augmentation size .byte 0x4 # DW_CFA_advance_loc4 - .4byte $LCFI4-$LFB1 + .4byte $LCFI10-$LFB1 .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 0x38 + .uleb128 SIZEOF_FRAME2 .byte 0x4 # DW_CFA_advance_loc4 - .4byte $LCFI6-$LCFI4 + .4byte $LCFI11-$LCFI10 .byte 0x11 # DW_CFA_offset_extended_sf .uleb128 0x10 # $16 .sleb128 -3 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) @@ -371,11 +464,41 @@ $LASFDE1: .uleb128 0x1f # $ra .sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) .byte 0x4 # DW_CFA_advance_loc4 - .4byte $LCFI7-$LCFI6 + .4byte $LCFI12-$LCFI11 .byte 0xc # DW_CFA_def_cfa .uleb128 0x1e - .uleb128 0x38 + .uleb128 SIZEOF_FRAME2 .align 2 $LEFDE1: +$LSFDE2: + .4byte $LEFDE2-$LASFDE2 # FDE Length +$LASFDE2: + .4byte $LASFDE2-$Lframe0 # FDE CIE offset + .4byte $LFB2 # FDE initial location + .4byte $LFE2-$LFB2 # FDE address range + .uleb128 0x0 # Augmentation size + .byte 0x4 # DW_CFA_advance_loc4 + .4byte $LCFI20-$LFB2 + .byte 0xe # DW_CFA_def_cfa_offset + .uleb128 SIZEOF_FRAME2 + .byte 0x4 # DW_CFA_advance_loc4 + .4byte $LCFI21-$LCFI20 + .byte 0x11 # DW_CFA_offset_extended_sf + .uleb128 0x10 # $16 + .sleb128 -3 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) + .byte 0x11 # DW_CFA_offset_extended_sf + .uleb128 0x1e # $fp + .sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) + .byte 0x11 # DW_CFA_offset_extended_sf + .uleb128 0x1f # $ra + .sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) + .byte 0x4 # DW_CFA_advance_loc4 + .4byte $LCFI22-$LCFI21 + .byte 0xc # DW_CFA_def_cfa + .uleb128 0x1e + .uleb128 SIZEOF_FRAME2 + .align 2 +$LEFDE2: + #endif diff --git a/libffi/src/moxie/eabi.S b/libffi/src/moxie/eabi.S index ac7aceb..10cfb04 100644 --- a/libffi/src/moxie/eabi.S +++ b/libffi/src/moxie/eabi.S @@ -59,7 +59,7 @@ ffi_call_EABI: mov $r6, $r4 /* Save result buffer */ mov $r7, $r5 /* Save the target fn */ mov $r8, $r3 /* Save the flags */ - sub.l $sp, $r2 /* Allocate stack space */ + sub $sp, $r2 /* Allocate stack space */ mov $r0, $sp /* We can stomp over $r0 */ /* $r1 is already set up */ jsra ffi_prep_args diff --git a/libffi/src/moxie/ffi.c b/libffi/src/moxie/ffi.c index 540a042..16d2bb3 100644 --- a/libffi/src/moxie/ffi.c +++ b/libffi/src/moxie/ffi.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------- - ffi.c - Copyright (C) 2012, 2013 Anthony Green + ffi.c - Copyright (C) 2012, 2013, 2018 Anthony Green Moxie Foreign Function Interface @@ -100,7 +100,7 @@ void *ffi_prep_args(char *stack, extended_cif *ecif) count += z; } - return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8))); + return (stack + ((count > 24) ? 24 : FFI_ALIGN_DOWN(count, 8))); } /* Perform machine dependent cif processing */ @@ -111,7 +111,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) else cif->flags = cif->rtype->size; - cif->bytes = ALIGN (cif->bytes, 8); + cif->bytes = FFI_ALIGN (cif->bytes, 8); return FFI_OK; } @@ -159,7 +159,7 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, unsigned arg4, unsigned arg5, unsigned arg6) { /* This function is called by a trampoline. The trampoline stows a - pointer to the ffi_closure object in $r7. We must save this + pointer to the ffi_closure object in $r12. We must save this pointer in a place that will persist while we do our work. */ register ffi_closure *creg __asm__ ("$r12"); ffi_closure *closure = creg; @@ -215,7 +215,18 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, break; default: /* This is an 8-byte value. */ - avalue[i] = ptr; + if (ptr == (char *) ®ister_args[5]) + { + /* The value is split across two locations */ + unsigned *ip = alloca(8); + avalue[i] = ip; + ip[0] = *(unsigned *) ptr; + ip[1] = *(unsigned *) stack_args; + } + else + { + avalue[i] = ptr; + } ptr += 4; break; } @@ -223,8 +234,10 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, /* If we've handled more arguments than fit in registers, start looking at the those passed on the stack. */ - if (ptr == ®ister_args[6]) + if (ptr == (char *) ®ister_args[6]) ptr = stack_args; + else if (ptr == (char *) ®ister_args[7]) + ptr = stack_args + 4; } /* Invoke the closure. */ @@ -257,7 +270,7 @@ ffi_prep_closure_loc (ffi_closure* closure, fn = (unsigned long) ffi_closure_eabi; - tramp[0] = 0x01e0; /* ldi.l $r7, .... */ + tramp[0] = 0x01e0; /* ldi.l $r12, .... */ tramp[1] = cls >> 16; tramp[2] = cls & 0xffff; tramp[3] = 0x1a00; /* jmpa .... */ diff --git a/libffi/src/nios2/ffi.c b/libffi/src/nios2/ffi.c index 2efa033..721080d 100644 --- a/libffi/src/nios2/ffi.c +++ b/libffi/src/nios2/ffi.c @@ -101,7 +101,7 @@ void ffi_prep_args (char *stack, extended_cif *ecif) /* Align argp as appropriate for the argument type. */ if ((alignment - 1) & (unsigned) argp) - argp = (char *) ALIGN (argp, alignment); + argp = (char *) FFI_ALIGN (argp, alignment); /* Copy the argument, promoting integral types smaller than a word to word size. */ @@ -230,7 +230,7 @@ ffi_closure_helper (unsigned char *args, /* Align argp as appropriate for the argument type. */ if ((alignment - 1) & (unsigned) argp) - argp = (char *) ALIGN (argp, alignment); + argp = (char *) FFI_ALIGN (argp, alignment); /* Arguments smaller than an int are promoted to int. */ if (size < sizeof (int)) diff --git a/libffi/src/pa/ffi.c b/libffi/src/pa/ffi.c index 0da8184..95e6694 100644 --- a/libffi/src/pa/ffi.c +++ b/libffi/src/pa/ffi.c @@ -1,6 +1,5 @@ /* ----------------------------------------------------------------------- - ffi.c - (c) 2016 John David Anglin - (c) 2011 Anthony Green + ffi.c - (c) 2011 Anthony Green (c) 2008 Red Hat, Inc. (c) 2006 Free Software Foundation, Inc. (c) 2003-2004 Randolph Chung <tausq@debian.org> @@ -52,8 +51,7 @@ #define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0) -static inline int -ffi_struct_type (ffi_type *t) +static inline int ffi_struct_type(ffi_type *t) { size_t sz = t->size; @@ -141,8 +139,7 @@ ffi_struct_type (ffi_type *t) NOTE: We load floating point args in this function... that means we assume gcc will not mess with fp regs in here. */ -void -ffi_prep_args_pa32 (UINT32 *stack, extended_cif *ecif, unsigned bytes) +void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes) { register unsigned int i; register ffi_type **p_arg; @@ -278,8 +275,7 @@ ffi_prep_args_pa32 (UINT32 *stack, extended_cif *ecif, unsigned bytes) return; } -static void -ffi_size_stack_pa32 (ffi_cif *cif) +static void ffi_size_stack_pa32(ffi_cif *cif) { ffi_type **ptr; int i; @@ -320,8 +316,7 @@ ffi_size_stack_pa32 (ffi_cif *cif) } /* Perform machine dependent cif processing. */ -ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { /* Set the return type flag */ switch (cif->rtype->type) @@ -374,13 +369,11 @@ ffi_prep_cif_machdep (ffi_cif *cif) return FFI_OK; } -extern void ffi_call_pa32 (void (*)(UINT32 *, extended_cif *, unsigned), - extended_cif *, unsigned, unsigned, unsigned *, - void (*fn)(void), void *closure); +extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned), + extended_cif *, unsigned, unsigned, unsigned *, + void (*fn)(void)); -static void -ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, - void *closure) +void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { extended_cif ecif; @@ -408,8 +401,8 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, { case FFI_PA32: debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn); - ffi_call_pa32 (ffi_prep_args_pa32, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn, closure); + ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); break; default: @@ -418,60 +411,35 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, } } -void -ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - ffi_call_int (cif, fn, rvalue, avalue, NULL); -} - -void -ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, - void *closure) -{ - ffi_call_int (cif, fn, rvalue, avalue, closure); -} - #if FFI_CLOSURES /* This is more-or-less an inverse of ffi_call -- we have arguments on the stack, and we need to fill them into a cif structure and invoke the user function. This really ought to be in asm to make sure the compiler doesn't do things we don't expect. */ -ffi_status -ffi_closure_inner_pa32 (void *closure, UINT32 *stack, int closure_type) +ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) { ffi_cif *cif; - void (*fun)(ffi_cif *,void *,void **,void *); - void *user_data; void **avalue; void *rvalue; - UINT32 ret[2]; /* function can return up to 64-bits in registers */ + /* Functions can return up to 64-bits in registers. Return address + must be double word aligned. */ + union { double rd; UINT32 ret[2]; } u; ffi_type **p_arg; char *tmp; int i, avn; unsigned int slot = FIRST_ARG_SLOT; register UINT32 r28 asm("r28"); + ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure); - /* A non-zero closure type indicates a go closure. */ - if (closure_type) - { - cif = ((ffi_go_closure *)closure)->cif; - fun = ((ffi_go_closure *)closure)->fun; - user_data = closure; - } - else - { - cif = ((ffi_closure *)closure)->cif; - fun = ((ffi_closure *)closure)->fun; - user_data = ((ffi_closure *)closure)->user_data; - } + cif = closure->cif; /* If returning via structure, callee will write to our pointer. */ if (cif->flags == FFI_TYPE_STRUCT) rvalue = (void *)r28; else - rvalue = &ret[0]; + rvalue = &u; - avalue = (void **) alloca (cif->nargs * FFI_SIZEOF_ARG); + avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG); avn = cif->nargs; p_arg = cif->arg_types; @@ -564,35 +532,35 @@ ffi_closure_inner_pa32 (void *closure, UINT32 *stack, int closure_type) } /* Invoke the closure. */ - fun (cif, rvalue, avalue, user_data); + (c->fun) (cif, rvalue, avalue, c->user_data); - debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0], - ret[1]); + debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", u.ret[0], + u.ret[1]); /* Store the result using the lower 2 bytes of the flags. */ switch (cif->flags) { case FFI_TYPE_UINT8: - *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24); + *(stack - FIRST_ARG_SLOT) = (UINT8)(u.ret[0] >> 24); break; case FFI_TYPE_SINT8: - *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24); + *(stack - FIRST_ARG_SLOT) = (SINT8)(u.ret[0] >> 24); break; case FFI_TYPE_UINT16: - *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16); + *(stack - FIRST_ARG_SLOT) = (UINT16)(u.ret[0] >> 16); break; case FFI_TYPE_SINT16: - *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16); + *(stack - FIRST_ARG_SLOT) = (SINT16)(u.ret[0] >> 16); break; case FFI_TYPE_INT: case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: - *(stack - FIRST_ARG_SLOT) = ret[0]; + *(stack - FIRST_ARG_SLOT) = u.ret[0]; break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: - *(stack - FIRST_ARG_SLOT) = ret[0]; - *(stack - FIRST_ARG_SLOT - 1) = ret[1]; + *(stack - FIRST_ARG_SLOT) = u.ret[0]; + *(stack - FIRST_ARG_SLOT - 1) = u.ret[1]; break; case FFI_TYPE_DOUBLE: @@ -612,7 +580,7 @@ ffi_closure_inner_pa32 (void *closure, UINT32 *stack, int closure_type) case FFI_TYPE_SMALL_STRUCT4: tmp = (void*)(stack - FIRST_ARG_SLOT); tmp += 4 - cif->rtype->size; - memcpy((void*)tmp, &ret[0], cif->rtype->size); + memcpy((void*)tmp, &u, cif->rtype->size); break; case FFI_TYPE_SMALL_STRUCT5: @@ -633,7 +601,7 @@ ffi_closure_inner_pa32 (void *closure, UINT32 *stack, int closure_type) } memset (ret2, 0, sizeof (ret2)); - memcpy ((char *)ret2 + off, ret, 8 - off); + memcpy ((char *)ret2 + off, &u, 8 - off); *(stack - FIRST_ARG_SLOT) = ret2[0]; *(stack - FIRST_ARG_SLOT - 1) = ret2[1]; @@ -656,7 +624,6 @@ ffi_closure_inner_pa32 (void *closure, UINT32 *stack, int closure_type) cif specifies the argument and result types for fun. The cif must already be prep'ed. */ -extern void ffi_go_closure_pa32(void); extern void ffi_closure_pa32(void); ffi_status @@ -666,107 +633,42 @@ ffi_prep_closure_loc (ffi_closure* closure, void *user_data, void *codeloc) { - UINT32 *tramp = (UINT32 *)(closure->tramp); -#ifdef PA_HPUX - UINT32 *tmp; -#endif - - if (cif->abi != FFI_PA32) - return FFI_BAD_ABI; - - /* Make a small trampoline that will branch to our - handler function. Use PC-relative addressing. */ - -#ifdef PA_LINUX - tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */ - tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */ - tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */ - tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */ - tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */ - tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */ - tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */ - tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2); - - /* Flush d/icache -- have to flush up 2 two lines because of - alignment. */ - __asm__ volatile( - "fdc 0(%0)\n\t" - "fdc %1(%0)\n\t" - "fic 0(%%sr4, %0)\n\t" - "fic %1(%%sr4, %0)\n\t" - "sync\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n" - : - : "r"((unsigned long)tramp & ~31), - "r"(32 /* stride */) - : "memory"); -#endif + ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure); -#ifdef PA_HPUX - tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */ - tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */ - tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */ - tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */ - tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */ - tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */ - tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */ - tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */ - tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */ - tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2); - - /* Flush d/icache -- have to flush three lines because of alignment. */ - __asm__ volatile( - "copy %1,%0\n\t" - "fdc,m %2(%0)\n\t" - "fdc,m %2(%0)\n\t" - "fdc,m %2(%0)\n\t" - "ldsid (%1),%0\n\t" - "mtsp %0,%%sr0\n\t" - "copy %1,%0\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "sync\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n" - : "=&r" ((unsigned long)tmp) - : "r" ((unsigned long)tramp & ~31), - "r" (32/* stride */) - : "memory"); -#endif + /* The layout of a function descriptor. A function pointer with the PLABEL + bit set points to a function descriptor. */ + struct pa32_fd + { + UINT32 code_pointer; + UINT32 gp; + }; - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; + struct ffi_pa32_trampoline_struct + { + UINT32 code_pointer; /* Pointer to ffi_closure_unix. */ + UINT32 fake_gp; /* Pointer to closure, installed as gp. */ + UINT32 real_gp; /* Real gp value. */ + }; - return FFI_OK; -} + struct ffi_pa32_trampoline_struct *tramp; + struct pa32_fd *fd; -#ifdef FFI_GO_CLOSURES -ffi_status -ffi_prep_go_closure (ffi_go_closure *closure, - ffi_cif *cif, - void (*fun)(ffi_cif *, void *, void **, void *)) -{ if (cif->abi != FFI_PA32) return FFI_BAD_ABI; - closure->tramp = &ffi_go_closure_pa32; - closure->cif = cif; - closure->fun = fun; + /* Get function descriptor address for ffi_closure_pa32. */ + fd = (struct pa32_fd *)((UINT32)ffi_closure_pa32 & ~3); + + /* Setup trampoline. */ + tramp = (struct ffi_pa32_trampoline_struct *)c->tramp; + tramp->code_pointer = fd->code_pointer; + tramp->fake_gp = (UINT32)codeloc & ~3; + tramp->real_gp = fd->gp; + + c->cif = cif; + c->user_data = user_data; + c->fun = fun; return FFI_OK; } -#endif /* FFI_GO_CLOSURES */ #endif diff --git a/libffi/src/pa/ffitarget.h b/libffi/src/pa/ffitarget.h index 024ac81..df1209e 100644 --- a/libffi/src/pa/ffitarget.h +++ b/libffi/src/pa/ffitarget.h @@ -1,6 +1,5 @@ /* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2016 John David Anglin - Copyright (c) 2012 Anthony Green + ffitarget.h - Copyright (c) 2012 Anthony Green Copyright (c) 1996-2003 Red Hat, Inc. Target configuration macros for hppa. @@ -68,14 +67,8 @@ typedef enum ffi_abi { /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 -#define FFI_GO_CLOSURES 1 #define FFI_NATIVE_RAW_API 0 - -#ifdef PA_LINUX -#define FFI_TRAMPOLINE_SIZE 32 -#else -#define FFI_TRAMPOLINE_SIZE 40 -#endif +#define FFI_TRAMPOLINE_SIZE 12 #define FFI_TYPE_SMALL_STRUCT2 -1 #define FFI_TYPE_SMALL_STRUCT3 -2 diff --git a/libffi/src/pa/hpux32.S b/libffi/src/pa/hpux32.S index 4a47da3..d0e5f69 100644 --- a/libffi/src/pa/hpux32.S +++ b/libffi/src/pa/hpux32.S @@ -1,7 +1,6 @@ /* ----------------------------------------------------------------------- hpux32.S - Copyright (c) 2006 Free Software Foundation, Inc. (c) 2008 Red Hat, Inc. - (c) 2016 John David Anglin based on src/pa/linux.S HP-UX PA Foreign Function Interface @@ -42,8 +41,7 @@ unsigned bytes, unsigned flags, unsigned *rvalue, - void (*fn)(void), - ffi_go_closure *closure); + void (*fn)(void)); */ .export ffi_call_pa32,ENTRY,PRIV_LEV=3 @@ -106,7 +104,6 @@ L$CFI13 we need to give it a place to put the result. */ ldw -52(%r3), %ret0 ; %ret0 <- rvalue ldw -56(%r3), %r22 ; %r22 <- function to call - ldw -60(%r3), %ret1 ; %ret1 <- closure bl $$dyncall, %r31 ; Call the user function copy %r31, %rp @@ -262,7 +259,7 @@ L$done L$FE1 /* void ffi_closure_pa32(void); - Called with closure argument in %r21 */ + Called with closure argument in %r19 */ .SPACE $TEXT$ .SUBSPA $CODE$ @@ -288,9 +285,9 @@ L$CFI22 stw %arg2, -44(%r3) stw %arg3, -48(%r3) - /* Closure type 0. */ - copy %r21, %arg0 - copy %r0, %arg2 + /* Retrieve closure pointer and real gp. */ + copy %r19, %arg0 + ldw 8(%r19), %r19 bl ffi_closure_inner_pa32, %r2 copy %r3, %arg1 ldwm -64(%sp), %r3 @@ -302,47 +299,6 @@ L$CFI22 .procend L$FE2: - /* void ffi_go_closure_pa32(void); - Called with closure argument in %ret1 */ - - .SPACE $TEXT$ - .SUBSPA $CODE$ - .export ffi_go_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR - .import ffi_closure_inner_pa32,CODE - .align 4 -L$FB3 -ffi_go_closure_pa32 - .proc - .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3 - .entry - - stw %rp, -20(%sp) - copy %r3, %r1 -L$CFI31 - copy %sp, %r3 -L$CFI32 - stwm %r1, 64(%sp) - - /* Put arguments onto the stack and call ffi_closure_inner. */ - stw %arg0, -36(%r3) - stw %arg1, -40(%r3) - stw %arg2, -44(%r3) - stw %arg3, -48(%r3) - - /* Closure type 1. */ - copy %ret1, %arg0 - ldi 1, %arg2 - bl ffi_closure_inner_pa32, %r2 - copy %r3, %arg1 - ldwm -64(%sp), %r3 - ldw -20(%sp), %rp - ldw -36(%sp), %ret0 - bv %r0(%rp) - ldw -40(%sp), %ret1 - .exit - .procend -L$FE3: - .SPACE $PRIVATE$ .SUBSPA $DATA$ @@ -412,25 +368,3 @@ L$ASFDE2: .align 4 L$EFDE2: - -L$SFDE3: - .word L$EFDE3-L$ASFDE3 ;# FDE Length -L$ASFDE3: - .word L$ASFDE3-L$frame1 ;# FDE CIE offset - .word L$FB3 ;# FDE initial location - .word L$FE3-L$FB3 ;# FDE address range - .byte 0x4 ;# DW_CFA_advance_loc4 - .word L$CFI31-L$FB3 - .byte 0x83 ;# DW_CFA_offset, column 0x3 - .uleb128 0x0 - .byte 0x11 ;# DW_CFA_offset_extended_sf - .uleb128 0x2 - .sleb128 -5 - - .byte 0x4 ;# DW_CFA_advance_loc4 - .word L$CFI32-L$CFI31 - .byte 0xd ;# DW_CFA_def_cfa_register = r3 - .uleb128 0x3 - - .align 4 -L$EFDE3: diff --git a/libffi/src/pa/linux.S b/libffi/src/pa/linux.S index 6026904..33ef0b1 100644 --- a/libffi/src/pa/linux.S +++ b/libffi/src/pa/linux.S @@ -1,7 +1,6 @@ /* ----------------------------------------------------------------------- linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org> (c) 2008 Red Hat, Inc. - (c) 2016 John David Anglin HPPA Foreign Function Interface @@ -38,26 +37,24 @@ unsigned bytes, unsigned flags, unsigned *rvalue, - void (*fn)(void), - ffi_go_closure *closure); + void (*fn)(void)); */ .export ffi_call_pa32,code .import ffi_prep_args_pa32,code .type ffi_call_pa32, @function - .cfi_startproc +.LFB1: ffi_call_pa32: .proc .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4 .entry stw %rp, -20(%sp) copy %r3, %r1 - .cfi_offset 2, -20 - .cfi_register 3, 1 +.LCFI11: copy %sp, %r3 - .cfi_def_cfa_register 3 +.LCFI12: /* Setup the stack for calling prep_args... We want the stack to look like this: @@ -73,8 +70,8 @@ ffi_call_pa32: */ stwm %r1, 64(%sp) - .cfi_offset 3, 0 stw %r4, 12(%r3) +.LCFI13: copy %sp, %r4 addl %arg2, %r4, %arg0 /* arg stack */ @@ -101,7 +98,6 @@ ffi_call_pa32: we need to give it a place to put the result. */ ldw -52(%r3), %ret0 /* %ret0 <- rvalue */ ldw -56(%r3), %r22 /* %r22 <- function to call */ - ldw -60(%r3), %ret1 /* %ret1 <- closure */ bl $$dyncall, %r31 /* Call the user function */ copy %r31, %rp @@ -253,27 +249,27 @@ ffi_call_pa32: nop .exit .procend - .cfi_endproc +.LFE1: /* void ffi_closure_pa32(void); - Called with ffi_closure argument in %r21. */ + Called with closure argument in %r19 */ .export ffi_closure_pa32,code .import ffi_closure_inner_pa32,code + .type ffi_closure_pa32, @function - .cfi_startproc +.LFB2: ffi_closure_pa32: .proc .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3 .entry stw %rp, -20(%sp) +.LCFI20: copy %r3, %r1 - .cfi_offset 2, -20 - .cfi_register 3, 1 +.LCFI21: copy %sp, %r3 - .cfi_def_cfa_register 3 +.LCFI22: stwm %r1, 64(%sp) - .cfi_offset 3, 0 /* Put arguments onto the stack and call ffi_closure_inner. */ stw %arg0, -36(%r3) @@ -281,9 +277,9 @@ ffi_closure_pa32: stw %arg2, -44(%r3) stw %arg3, -48(%r3) - /* Closure type 0. */ - copy %r21, %arg0 - copy %r0, %arg2 + /* Retrieve closure pointer and real gp. */ + copy %r19, %arg0 + ldw 8(%r19), %r19 bl ffi_closure_inner_pa32, %r2 copy %r3, %arg1 @@ -295,46 +291,90 @@ ffi_closure_pa32: .exit .procend - .cfi_endproc - - /* void ffi_go_closure_pa32(void); - Called with ffi_go_closure argument in %ret1. */ - .export ffi_go_closure_pa32,code - .import ffi_closure_inner_pa32,code - .type ffi_go_closure_pa32, @function - .cfi_startproc -ffi_go_closure_pa32: - .proc - .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3 - .entry - - stw %rp, -20(%sp) - copy %r3, %r1 - .cfi_offset 2, -20 - .cfi_register 3, 1 - copy %sp, %r3 - .cfi_def_cfa_register 3 - stwm %r1, 64(%sp) - .cfi_offset 3, 0 - - /* Put arguments onto the stack and call ffi_closure_inner. */ - stw %arg0, -36(%r3) - stw %arg1, -40(%r3) - stw %arg2, -44(%r3) - stw %arg3, -48(%r3) - - /* Closure type 1. */ - copy %ret1, %arg0 - ldi 1, %arg2 - bl ffi_closure_inner_pa32, %r2 - copy %r3, %arg1 +.LFE2: + + .section ".eh_frame",EH_FRAME_FLAGS,@progbits +.Lframe1: + .word .LECIE1-.LSCIE1 ;# Length of Common Information Entry +.LSCIE1: + .word 0x0 ;# CIE Identifier Tag + .byte 0x1 ;# CIE Version +#ifdef __PIC__ + .ascii "zR\0" ;# CIE Augmentation: 'z' - data, 'R' - DW_EH_PE_... data +#else + .ascii "\0" ;# CIE Augmentation +#endif + .uleb128 0x1 ;# CIE Code Alignment Factor + .sleb128 4 ;# CIE Data Alignment Factor + .byte 0x2 ;# CIE RA Column +#ifdef __PIC__ + .uleb128 0x1 ;# Augmentation size + .byte 0x1b ;# FDE Encoding (DW_EH_PE_pcrel|DW_EH_PE_sdata4) +#endif + .byte 0xc ;# DW_CFA_def_cfa + .uleb128 0x1e + .uleb128 0x0 + .align 4 +.LECIE1: +.LSFDE1: + .word .LEFDE1-.LASFDE1 ;# FDE Length +.LASFDE1: + .word .LASFDE1-.Lframe1 ;# FDE CIE offset +#ifdef __PIC__ + .word .LFB1-. ;# FDE initial location +#else + .word .LFB1 ;# FDE initial location +#endif + .word .LFE1-.LFB1 ;# FDE address range +#ifdef __PIC__ + .uleb128 0x0 ;# Augmentation size: no data +#endif + .byte 0x4 ;# DW_CFA_advance_loc4 + .word .LCFI11-.LFB1 + .byte 0x83 ;# DW_CFA_offset, column 0x3 + .uleb128 0x0 + .byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20] + .uleb128 0x2 + .sleb128 -5 + + .byte 0x4 ;# DW_CFA_advance_loc4 + .word .LCFI12-.LCFI11 + .byte 0xd ;# DW_CFA_def_cfa_register = r3 + .uleb128 0x3 + + .byte 0x4 ;# DW_CFA_advance_loc4 + .word .LCFI13-.LCFI12 + .byte 0x84 ;# DW_CFA_offset, column 0x4 + .uleb128 0x3 - ldwm -64(%sp), %r3 - ldw -20(%sp), %rp - ldw -36(%sp), %ret0 - bv %r0(%r2) - ldw -40(%sp), %ret1 + .align 4 +.LEFDE1: + +.LSFDE2: + .word .LEFDE2-.LASFDE2 ;# FDE Length +.LASFDE2: + .word .LASFDE2-.Lframe1 ;# FDE CIE offset +#ifdef __PIC__ + .word .LFB2-. ;# FDE initial location +#else + .word .LFB2 ;# FDE initial location +#endif + .word .LFE2-.LFB2 ;# FDE address range +#ifdef __PIC__ + .uleb128 0x0 ;# Augmentation size: no data +#endif + .byte 0x4 ;# DW_CFA_advance_loc4 + .word .LCFI21-.LFB2 + .byte 0x83 ;# DW_CFA_offset, column 0x3 + .uleb128 0x0 + .byte 0x11 ;# DW_CFA_offset_extended_sf + .uleb128 0x2 + .sleb128 -5 + + .byte 0x4 ;# DW_CFA_advance_loc4 + .word .LCFI22-.LCFI21 + .byte 0xd ;# DW_CFA_def_cfa_register = r3 + .uleb128 0x3 - .exit - .procend - .cfi_endproc + .align 4 +.LEFDE2: diff --git a/libffi/src/powerpc/asm.h b/libffi/src/powerpc/asm.h index 994f62d..27b22f6 100644 --- a/libffi/src/powerpc/asm.h +++ b/libffi/src/powerpc/asm.h @@ -93,7 +93,7 @@ /* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes past a 2^align boundary. */ #ifdef PROF -#define EALIGN(name, alignt, words) \ +#define EFFI_ALIGN(name, alignt, words) \ ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ .align ALIGNARG(2); \ @@ -104,7 +104,7 @@ EALIGN_W_##words; \ 0: #else /* PROF */ -#define EALIGN(name, alignt, words) \ +#define EFFI_ALIGN(name, alignt, words) \ ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ .align ALIGNARG(alignt); \ diff --git a/libffi/src/powerpc/darwin_closure.S b/libffi/src/powerpc/darwin_closure.S index c7734d4..3121e6a 100644 --- a/libffi/src/powerpc/darwin_closure.S +++ b/libffi/src/powerpc/darwin_closure.S @@ -353,7 +353,7 @@ Lret_type13: bgt Lstructend ; not a special small case b Lsmallstruct ; see if we need more. #else - cmpi 0,r0,4 + cmpwi 0,r0,4 bgt Lfinish ; not by value lg r3,0(r5) b Lfinish @@ -494,8 +494,8 @@ LSFDE1: LASFDE1: .long LASFDE1-EH_frame1 ; FDE CIE offset .g_long Lstartcode-. ; FDE initial location - .set L$set$3,LFE1-Lstartcode - .g_long L$set$3 ; FDE address range + .set L$set$2,LFE1-Lstartcode + .g_long L$set$2 ; FDE address range .byte 0x0 ; uleb128 0x0; Augmentation size .byte 0x4 ; DW_CFA_advance_loc4 .set L$set$3,LCFI1-LCFI0 diff --git a/libffi/src/powerpc/ffi.c b/libffi/src/powerpc/ffi.c index 7eb543e..a19bcbb 100644 --- a/libffi/src/powerpc/ffi.c +++ b/libffi/src/powerpc/ffi.c @@ -85,8 +85,9 @@ ffi_call_int (ffi_cif *cif, can write r3 and r4 to memory without worrying about struct size. For ELFv2 ABI, use a bounce buffer for homogeneous structs too, - for similar reasons. */ - unsigned long smst_buffer[8]; + for similar reasons. This bounce buffer must be aligned to 16 + bytes for use with homogeneous structs of vectors (float128). */ + float128 smst_buffer[8]; extended_cif ecif; ecif.cif = cif; @@ -121,8 +122,9 @@ ffi_call_int (ffi_cif *cif, # endif /* The SYSV ABI returns a structure of up to 8 bytes in size left-padded in r3/r4, and the ELFv2 ABI similarly returns a - structure of up to 8 bytes in size left-padded in r3. */ - if (rsize <= 8) + structure of up to 8 bytes in size left-padded in r3. But + note that a structure of a single float is not paddded. */ + if (rsize <= 8 && (cif->flags & FLAG_RETURNS_FP) == 0) memcpy (rvalue, (char *) smst_buffer + 8 - rsize, rsize); else #endif diff --git a/libffi/src/powerpc/ffi_darwin.c b/libffi/src/powerpc/ffi_darwin.c index 6588e3c..64bb94df 100644 --- a/libffi/src/powerpc/ffi_darwin.c +++ b/libffi/src/powerpc/ffi_darwin.c @@ -33,7 +33,10 @@ #include <stdlib.h> extern void ffi_closure_ASM (void); + +#if defined (FFI_GO_CLOSURES) extern void ffi_go_closure_ASM (void); +#endif enum { /* The assembly depends on these exact flags. @@ -256,7 +259,7 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack) case FFI_TYPE_STRUCT: size_al = (*ptr)->size; #if defined(POWERPC_DARWIN64) - next_arg = (unsigned long *)ALIGN((char *)next_arg, (*ptr)->alignment); + next_arg = (unsigned long *)FFI_ALIGN((char *)next_arg, (*ptr)->alignment); darwin64_pass_struct_by_value (*ptr, (char *) *p_argv, (unsigned) size_al, (unsigned int *) &fparg_count, @@ -267,7 +270,7 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack) /* If the first member of the struct is a double, then include enough padding in the struct size to align it to double-word. */ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) - size_al = ALIGN((*ptr)->size, 8); + size_al = FFI_ALIGN((*ptr)->size, 8); # if defined(POWERPC64) FFI_ASSERT (abi != FFI_DARWIN); @@ -353,7 +356,7 @@ darwin64_struct_size_exceeds_gprs_p (ffi_type *s, char *src, unsigned *nfpr) ffi_type *p = s->elements[i]; /* Find the start of this item (0 for the first one). */ if (i > 0) - struct_offset = ALIGN(struct_offset, p->alignment); + struct_offset = FFI_ALIGN(struct_offset, p->alignment); item_base = src + struct_offset; @@ -437,7 +440,7 @@ darwin64_pass_struct_floats (ffi_type *s, char *src, ffi_type *p = s->elements[i]; /* Find the start of this item (0 for the first one). */ if (i > 0) - struct_offset = ALIGN(struct_offset, p->alignment); + struct_offset = FFI_ALIGN(struct_offset, p->alignment); item_base = src + struct_offset; switch (p->type) @@ -528,7 +531,7 @@ darwin64_struct_floats_to_mem (ffi_type *s, char *dest, double *fprs, unsigned * ffi_type *p = s->elements[i]; /* Find the start of this item (0 for the first one). */ if (i > 0) - struct_offset = ALIGN(struct_offset, p->alignment); + struct_offset = FFI_ALIGN(struct_offset, p->alignment); item_base = dest + struct_offset; switch (p->type) @@ -605,10 +608,10 @@ darwin_adjust_aggregate_sizes (ffi_type *s) align = 4; #endif /* Pad, if necessary, before adding the current item. */ - s->size = ALIGN(s->size, align) + p->size; + s->size = FFI_ALIGN(s->size, align) + p->size; } - s->size = ALIGN(s->size, s->alignment); + s->size = FFI_ALIGN(s->size, s->alignment); /* This should not be necessary on m64, but harmless. */ if (s->elements[0]->type == FFI_TYPE_UINT64 @@ -641,10 +644,10 @@ aix_adjust_aggregate_sizes (ffi_type *s) align = p->alignment; if (i != 0 && p->type == FFI_TYPE_DOUBLE) align = 4; - s->size = ALIGN(s->size, align) + p->size; + s->size = FFI_ALIGN(s->size, align) + p->size; } - s->size = ALIGN(s->size, s->alignment); + s->size = FFI_ALIGN(s->size, s->alignment); if (s->elements[0]->type == FFI_TYPE_UINT64 || s->elements[0]->type == FFI_TYPE_SINT64 @@ -810,9 +813,9 @@ ffi_prep_cif_machdep (ffi_cif *cif) 16-byte-aligned. */ if (fparg_count >= NUM_FPR_ARG_REGISTERS) #if defined (POWERPC64) - intarg_count = ALIGN(intarg_count, 2); + intarg_count = FFI_ALIGN(intarg_count, 2); #else - intarg_count = ALIGN(intarg_count, 4); + intarg_count = FFI_ALIGN(intarg_count, 4); #endif break; #endif @@ -839,7 +842,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) #if defined(POWERPC_DARWIN64) align_words = (*ptr)->alignment >> 3; if (align_words) - intarg_count = ALIGN(intarg_count, align_words); + intarg_count = FFI_ALIGN(intarg_count, align_words); /* Base size of the struct. */ intarg_count += (size_al + 7) / 8; /* If 16 bytes then don't worry about floats. */ @@ -849,11 +852,11 @@ ffi_prep_cif_machdep (ffi_cif *cif) #else align_words = (*ptr)->alignment >> 2; if (align_words) - intarg_count = ALIGN(intarg_count, align_words); + intarg_count = FFI_ALIGN(intarg_count, align_words); /* If the first member of the struct is a double, then align the struct to double-word. if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) - size_al = ALIGN((*ptr)->size, 8); */ + size_al = FFI_ALIGN((*ptr)->size, 8); */ # ifdef POWERPC64 intarg_count += (size_al + 7) / 8; # else @@ -898,7 +901,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); /* The stack space allocated needs to be a multiple of 16 bytes. */ - bytes = ALIGN(bytes, 16) ; + bytes = FFI_ALIGN(bytes, 16) ; cif->flags = flags; cif->bytes = bytes; @@ -909,8 +912,10 @@ ffi_prep_cif_machdep (ffi_cif *cif) extern void ffi_call_AIX(extended_cif *, long, unsigned, unsigned *, void (*fn)(void), void (*fn2)(void)); +#if defined (FFI_GO_CLOSURES) extern void ffi_call_go_AIX(extended_cif *, long, unsigned, unsigned *, void (*fn)(void), void (*fn2)(void), void *closure); +#endif extern void ffi_call_DARWIN(extended_cif *, long, unsigned, unsigned *, void (*fn)(void), void (*fn2)(void), ffi_type*); @@ -950,6 +955,7 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) } } +#if defined (FFI_GO_CLOSURES) void ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue, void *closure) @@ -981,6 +987,7 @@ ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue, break; } } +#endif static void flush_icache(char *); static void flush_range(char *, int); @@ -1110,6 +1117,7 @@ ffi_prep_closure_loc (ffi_closure* closure, return FFI_OK; } +#if defined (FFI_GO_CLOSURES) ffi_status ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, @@ -1133,6 +1141,7 @@ ffi_prep_go_closure (ffi_go_closure* closure, } return FFI_OK; } +#endif static void flush_icache(char *addr) @@ -1168,9 +1177,11 @@ ffi_type * ffi_closure_helper_DARWIN (ffi_closure *, void *, unsigned long *, ffi_dblfl *); +#if defined (FFI_GO_CLOSURES) ffi_type * ffi_go_closure_helper_DARWIN (ffi_go_closure*, void *, unsigned long *, ffi_dblfl *); +#endif /* Basically the trampoline invokes ffi_closure_ASM, and on entry, r11 holds the address of the closure. @@ -1272,7 +1283,7 @@ ffi_closure_helper_common (ffi_cif* cif, case FFI_TYPE_STRUCT: size_al = arg_types[i]->size; #if defined(POWERPC_DARWIN64) - pgr = (unsigned long *)ALIGN((char *)pgr, arg_types[i]->alignment); + pgr = (unsigned long *)FFI_ALIGN((char *)pgr, arg_types[i]->alignment); if (size_al < 3 || size_al == 4) { avalue[i] = ((char *)pgr)+8-size_al; @@ -1297,7 +1308,7 @@ ffi_closure_helper_common (ffi_cif* cif, /* If the first member of the struct is a double, then align the struct to double-word. */ if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) - size_al = ALIGN(arg_types[i]->size, 8); + size_al = FFI_ALIGN(arg_types[i]->size, 8); # if defined(POWERPC64) FFI_ASSERT (cif->abi != FFI_DARWIN); avalue[i] = pgr; @@ -1430,6 +1441,7 @@ ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue, closure->user_data, rvalue, pgr, pfr); } +#if defined (FFI_GO_CLOSURES) ffi_type * ffi_go_closure_helper_DARWIN (ffi_go_closure *closure, void *rvalue, unsigned long *pgr, ffi_dblfl *pfr) @@ -1437,4 +1449,4 @@ ffi_go_closure_helper_DARWIN (ffi_go_closure *closure, void *rvalue, return ffi_closure_helper_common (closure->cif, closure->fun, closure, rvalue, pgr, pfr); } - +#endif diff --git a/libffi/src/powerpc/ffi_linux64.c b/libffi/src/powerpc/ffi_linux64.c index ef0361b..4d50878 100644 --- a/libffi/src/powerpc/ffi_linux64.c +++ b/libffi/src/powerpc/ffi_linux64.c @@ -38,7 +38,8 @@ /* About the LINUX64 ABI. */ enum { NUM_GPR_ARG_REGISTERS64 = 8, - NUM_FPR_ARG_REGISTERS64 = 13 + NUM_FPR_ARG_REGISTERS64 = 13, + NUM_VEC_ARG_REGISTERS64 = 12, }; enum { ASM_NEEDS_REGISTERS64 = 4 }; @@ -63,10 +64,31 @@ ffi_prep_types_linux64 (ffi_abi abi) static unsigned int -discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) +discover_homogeneous_aggregate (ffi_abi abi, + const ffi_type *t, + unsigned int *elnum) { switch (t->type) { +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + case FFI_TYPE_LONGDOUBLE: + /* 64-bit long doubles are equivalent to doubles. */ + if ((abi & FFI_LINUX_LONG_DOUBLE_128) == 0) + { + *elnum = 1; + return FFI_TYPE_DOUBLE; + } + /* IBM extended precision values use unaligned pairs + of FPRs, but according to the ABI must be considered + distinct from doubles. They are also limited to a + maximum of four members in a homogeneous aggregate. */ + else if ((abi & FFI_LINUX_LONG_DOUBLE_IEEE128) == 0) + { + *elnum = 2; + return FFI_TYPE_LONGDOUBLE; + } + /* Fall through. */ +#endif case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: *elnum = 1; @@ -79,7 +101,7 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) while (*el) { unsigned int el_elt, el_elnum = 0; - el_elt = discover_homogeneous_aggregate (*el, &el_elnum); + el_elt = discover_homogeneous_aggregate (abi, *el, &el_elnum); if (el_elt == 0 || (base_elt && base_elt != el_elt)) return 0; @@ -110,13 +132,23 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) { ffi_type **ptr; unsigned bytes; - unsigned i, fparg_count = 0, intarg_count = 0; + unsigned i, fparg_count = 0, intarg_count = 0, vecarg_count = 0; unsigned flags = cif->flags; - unsigned int elt, elnum; + unsigned elt, elnum, rtype; #if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE - /* If compiled without long double support.. */ - if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) + /* If compiled without long double support... */ + if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0 || + (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + return FFI_BAD_ABI; +#elif !defined(__VEC__) + /* If compiled without vector register support (used by assembly)... */ + if ((cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + return FFI_BAD_ABI; +#else + /* If the IEEE128 flag is set, but long double is only 64 bits wide... */ + if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) == 0 && + (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) return FFI_BAD_ABI; #endif @@ -138,10 +170,19 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) #endif /* Return value handling. */ - switch (cif->rtype->type) + rtype = cif->rtype->type; +#if _CALL_ELF == 2 +homogeneous: +#endif + switch (rtype) { #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: + if ((cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + flags |= FLAG_RETURNS_VEC; + break; + } if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) flags |= FLAG_RETURNS_128BITS; /* Fall through. */ @@ -164,19 +205,18 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) case FFI_TYPE_STRUCT: #if _CALL_ELF == 2 - elt = discover_homogeneous_aggregate (cif->rtype, &elnum); + elt = discover_homogeneous_aggregate (cif->abi, cif->rtype, &elnum); if (elt) - { - if (elt == FFI_TYPE_DOUBLE) - flags |= FLAG_RETURNS_64BITS; - flags |= FLAG_RETURNS_FP | FLAG_RETURNS_SMST; - break; - } + { + flags |= FLAG_RETURNS_SMST; + rtype = elt; + goto homogeneous; + } if (cif->rtype->size <= 16) - { - flags |= FLAG_RETURNS_SMST; - break; - } + { + flags |= FLAG_RETURNS_SMST; + break; + } #endif intarg_count++; flags |= FLAG_RETVAL_REFERENCE; @@ -198,6 +238,15 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) { #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: + if ((cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + vecarg_count++; + /* Align to 16 bytes, plus the 16-byte argument. */ + intarg_count = (intarg_count + 3) & ~0x1; + if (vecarg_count > NUM_VEC_ARG_REGISTERS64) + flags |= FLAG_ARG_NEEDS_PSAVE; + break; + } if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) { fparg_count++; @@ -221,10 +270,21 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) align = 16; align = align / 8; if (align > 1) - intarg_count = ALIGN (intarg_count, align); + intarg_count = FFI_ALIGN (intarg_count, align); } intarg_count += ((*ptr)->size + 7) / 8; - elt = discover_homogeneous_aggregate (*ptr, &elnum); + elt = discover_homogeneous_aggregate (cif->abi, *ptr, &elnum); +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + if (elt == FFI_TYPE_LONGDOUBLE && + (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + vecarg_count += elnum; + if (vecarg_count > NUM_VEC_ARG_REGISTERS64) + flags |= FLAG_ARG_NEEDS_PSAVE; + break; + } + else +#endif if (elt) { fparg_count += elnum; @@ -263,10 +323,17 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) flags |= FLAG_FP_ARGUMENTS; if (intarg_count > 4) flags |= FLAG_4_GPR_ARGUMENTS; + if (vecarg_count != 0) + flags |= FLAG_VEC_ARGUMENTS; /* Space for the FPR registers, if needed. */ if (fparg_count != 0) bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double); + /* Space for the vector registers, if needed, aligned to 16 bytes. */ + if (vecarg_count != 0) { + bytes = (bytes + 15) & ~0xF; + bytes += NUM_VEC_ARG_REGISTERS64 * sizeof (float128); + } /* Stack space. */ #if _CALL_ELF == 2 @@ -349,6 +416,8 @@ ffi_prep_cif_linux64_var (ffi_cif *cif, |--------------------------------------------| | | FPR registers f1-f13 (optional) 13*8 | | |--------------------------------------------| | + | VEC registers v2-v13 (optional) 12*16 | | + |--------------------------------------------| | | Parameter save area | | |--------------------------------------------| | | TOC save area 8 | | @@ -378,6 +447,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) unsigned long *ul; float *f; double *d; + float128 *f128; size_t p; } valp; @@ -391,11 +461,16 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) valp rest; valp next_arg; - /* 'fpr_base' points at the space for fpr3, and grows upwards as + /* 'fpr_base' points at the space for f1, and grows upwards as we use FPR registers. */ valp fpr_base; unsigned int fparg_count; + /* 'vec_base' points at the space for v2, and grows upwards as + we use vector registers. */ + valp vec_base; + unsigned int vecarg_count; + unsigned int i, words, nargs, nfixedargs; ffi_type **ptr; double double_tmp; @@ -412,6 +487,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) unsigned long **ul; float **f; double **d; + float128 **f128; } p_argv; unsigned long gprvalue; unsigned long align; @@ -426,11 +502,21 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) #endif fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64; fparg_count = 0; + /* Place the vector args below the FPRs, if used, else the GPRs. */ + if (ecif->cif->flags & FLAG_FP_ARGUMENTS) + vec_base.p = fpr_base.p & ~0xF; + else + vec_base.p = gpr_base.p; + vec_base.f128 -= NUM_VEC_ARG_REGISTERS64; + vecarg_count = 0; next_arg.ul = gpr_base.ul; /* Check that everything starts aligned properly. */ FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0); FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0); + FFI_ASSERT (((unsigned long) gpr_base.c & 0xF) == 0); + FFI_ASSERT (((unsigned long) gpr_end.c & 0xF) == 0); + FFI_ASSERT (((unsigned long) vec_base.c & 0xF) == 0); FFI_ASSERT ((bytes & 0xF) == 0); /* Deal with return values that are actually pass-by-reference. */ @@ -455,6 +541,22 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) { #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: + if ((ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + next_arg.p = FFI_ALIGN (next_arg.p, 16); + if (next_arg.ul == gpr_end.ul) + next_arg.ul = rest.ul; + if (vecarg_count < NUM_VEC_ARG_REGISTERS64 && i < nfixedargs) + memcpy (vec_base.f128++, *p_argv.f128, sizeof (float128)); + else + memcpy (next_arg.f128, *p_argv.f128, sizeof (float128)); + if (++next_arg.f128 == gpr_end.f128) + next_arg.f128 = rest.f128; + vecarg_count++; + FFI_ASSERT (__LDBL_MANT_DIG__ == 113); + FFI_ASSERT (flags & FLAG_VEC_ARGUMENTS); + break; + } if ((ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) { double_tmp = (*p_argv.d)[0]; @@ -492,7 +594,9 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) /* Fall through. */ #endif case FFI_TYPE_DOUBLE: +#if _CALL_ELF != 2 do_double: +#endif double_tmp = **p_argv.d; if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) { @@ -511,7 +615,9 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) break; case FFI_TYPE_FLOAT: +#if _CALL_ELF != 2 do_float: +#endif double_tmp = **p_argv.f; if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) { @@ -548,9 +654,13 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) if (align > 16) align = 16; if (align > 1) - next_arg.p = ALIGN (next_arg.p, align); + { + next_arg.p = FFI_ALIGN (next_arg.p, align); + if (next_arg.ul == gpr_end.ul) + next_arg.ul = rest.ul; + } } - elt = discover_homogeneous_aggregate (*ptr, &elnum); + elt = discover_homogeneous_aggregate (ecif->cif->abi, *ptr, &elnum); if (elt) { #if _CALL_ELF == 2 @@ -558,9 +668,29 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) void *v; float *f; double *d; + float128 *f128; } arg; arg.v = *p_argv.v; +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + if (elt == FFI_TYPE_LONGDOUBLE && + (ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + do + { + if (vecarg_count < NUM_VEC_ARG_REGISTERS64 + && i < nfixedargs) + memcpy (vec_base.f128++, arg.f128, sizeof (float128)); + else + memcpy (next_arg.f128, arg.f128++, sizeof (float128)); + if (++next_arg.f128 == gpr_end.f128) + next_arg.f128 = rest.f128; + vecarg_count++; + } + while (--elnum != 0); + } + else +#endif if (elt == FFI_TYPE_FLOAT) { do @@ -576,11 +706,9 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) fparg_count++; } while (--elnum != 0); - if ((next_arg.p & 3) != 0) - { - if (++next_arg.f == gpr_end.f) - next_arg.f = rest.f; - } + if ((next_arg.p & 7) != 0) + if (++next_arg.f == gpr_end.f) + next_arg.f = rest.f; } else do @@ -733,17 +861,20 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, void *user_data, void *rvalue, unsigned long *pst, - ffi_dblfl *pfr) + ffi_dblfl *pfr, + float128 *pvec) { /* rvalue is the pointer to space for return value in closure assembly */ /* pst is the pointer to parameter save area (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */ /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */ + /* pvec is the pointer to where v2-v13 are stored in ffi_closure_LINUX64 */ void **avalue; ffi_type **arg_types; unsigned long i, avn, nfixedargs; ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64; + float128 *end_pvec = pvec + NUM_VEC_ARG_REGISTERS64; unsigned long align; avalue = alloca (cif->nargs * sizeof (void *)); @@ -811,9 +942,9 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, if (align > 16) align = 16; if (align > 1) - pst = (unsigned long *) ALIGN ((size_t) pst, align); + pst = (unsigned long *) FFI_ALIGN ((size_t) pst, align); } - elt = discover_homogeneous_aggregate (arg_types[i], &elnum); + elt = discover_homogeneous_aggregate (cif->abi, arg_types[i], &elnum); if (elt) { #if _CALL_ELF == 2 @@ -822,6 +953,7 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, unsigned long *ul; float *f; double *d; + float128 *f128; size_t p; } to, from; @@ -829,6 +961,17 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, aggregate size is not greater than the space taken by the registers so store back to the register/parameter save arrays. */ +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + if (elt == FFI_TYPE_LONGDOUBLE && + (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + if (pvec + elnum <= end_pvec) + to.v = pvec; + else + to.v = pst; + } + else +#endif if (pfr + elnum <= end_pfr) to.v = pfr; else @@ -836,6 +979,23 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, avalue[i] = to.v; from.ul = pst; +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + if (elt == FFI_TYPE_LONGDOUBLE && + (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + do + { + if (pvec < end_pvec && i < nfixedargs) + memcpy (to.f128, pvec++, sizeof (float128)); + else + memcpy (to.f128, from.f128, sizeof (float128)); + to.f128++; + from.f128++; + } + while (--elnum != 0); + } + else +#endif if (elt == FFI_TYPE_FLOAT) { do @@ -891,7 +1051,18 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: - if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) + if ((cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + if (((unsigned long) pst & 0xF) != 0) + ++pst; + if (pvec < end_pvec && i < nfixedargs) + avalue[i] = pvec++; + else + avalue[i] = pst; + pst += 2; + break; + } + else if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) { if (pfr + 1 < end_pfr && i + 1 < nfixedargs) { @@ -915,7 +1086,9 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, /* Fall through. */ #endif case FFI_TYPE_DOUBLE: +#if _CALL_ELF != 2 do_double: +#endif /* On the outgoing stack all values are aligned to 8 */ /* there are 13 64bit floating point registers */ @@ -930,7 +1103,9 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, break; case FFI_TYPE_FLOAT: +#if _CALL_ELF != 2 do_float: +#endif if (pfr < end_pfr && i < nfixedargs) { /* Float values are stored as doubles in the @@ -962,13 +1137,17 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, /* Tell ffi_closure_LINUX64 how to perform return type promotions. */ if ((cif->flags & FLAG_RETURNS_SMST) != 0) { - if ((cif->flags & FLAG_RETURNS_FP) == 0) + if ((cif->flags & (FLAG_RETURNS_FP | FLAG_RETURNS_VEC)) == 0) return FFI_V2_TYPE_SMALL_STRUCT + cif->rtype->size - 1; + else if ((cif->flags & FLAG_RETURNS_VEC) != 0) + return FFI_V2_TYPE_VECTOR_HOMOG; else if ((cif->flags & FLAG_RETURNS_64BITS) != 0) return FFI_V2_TYPE_DOUBLE_HOMOG; else return FFI_V2_TYPE_FLOAT_HOMOG; } + if ((cif->flags & FLAG_RETURNS_VEC) != 0) + return FFI_V2_TYPE_VECTOR; return cif->rtype->type; } #endif diff --git a/libffi/src/powerpc/ffi_powerpc.h b/libffi/src/powerpc/ffi_powerpc.h index 3dcd6b5..960a5c4 100644 --- a/libffi/src/powerpc/ffi_powerpc.h +++ b/libffi/src/powerpc/ffi_powerpc.h @@ -31,22 +31,24 @@ enum { /* The assembly depends on these exact flags. */ /* These go in cr7 */ - FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */ + FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */ FLAG_RETURNS_NOTHING = 1 << (31-30), FLAG_RETURNS_FP = 1 << (31-29), - FLAG_RETURNS_64BITS = 1 << (31-28), + FLAG_RETURNS_VEC = 1 << (31-28), - /* This goes in cr6 */ - FLAG_RETURNS_128BITS = 1 << (31-27), + /* These go in cr6 */ + FLAG_RETURNS_64BITS = 1 << (31-27), + FLAG_RETURNS_128BITS = 1 << (31-26), - FLAG_COMPAT = 1 << (31- 8), /* Not used by assembly */ + FLAG_COMPAT = 1 << (31- 8), /* Not used by assembly */ /* These go in cr1 */ FLAG_ARG_NEEDS_COPY = 1 << (31- 7), /* Used by sysv code */ FLAG_ARG_NEEDS_PSAVE = FLAG_ARG_NEEDS_COPY, /* Used by linux64 code */ FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */ FLAG_4_GPR_ARGUMENTS = 1 << (31- 5), - FLAG_RETVAL_REFERENCE = 1 << (31- 4) + FLAG_RETVAL_REFERENCE = 1 << (31- 4), + FLAG_VEC_ARGUMENTS = 1 << (31- 3), }; typedef union @@ -55,6 +57,14 @@ typedef union double d; } ffi_dblfl; +#if defined(__FLOAT128_TYPE__) && defined(__HAVE_FLOAT128) +typedef _Float128 float128; +#elif defined(__FLOAT128__) +typedef __float128 float128; +#else +typedef char float128[16] __attribute__((aligned(16))); +#endif + void FFI_HIDDEN ffi_closure_SYSV (void); void FFI_HIDDEN ffi_go_closure_sysv (void); void FFI_HIDDEN ffi_call_SYSV(extended_cif *, void (*)(void), void *, @@ -91,4 +101,5 @@ int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_cif *, void (*) (ffi_cif *, void *, void **, void *), void *, void *, - unsigned long *, ffi_dblfl *); + unsigned long *, ffi_dblfl *, + float128 *); diff --git a/libffi/src/powerpc/ffitarget.h b/libffi/src/powerpc/ffitarget.h index 90aa36b..7fb9a93 100644 --- a/libffi/src/powerpc/ffitarget.h +++ b/libffi/src/powerpc/ffitarget.h @@ -91,15 +91,19 @@ typedef enum ffi_abi { /* This and following bits can reuse FFI_COMPAT values. */ FFI_LINUX_STRUCT_ALIGN = 1, FFI_LINUX_LONG_DOUBLE_128 = 2, + FFI_LINUX_LONG_DOUBLE_IEEE128 = 4, FFI_DEFAULT_ABI = (FFI_LINUX # ifdef __STRUCT_PARM_ALIGN__ | FFI_LINUX_STRUCT_ALIGN # endif # ifdef __LONG_DOUBLE_128__ | FFI_LINUX_LONG_DOUBLE_128 +# ifdef __LONG_DOUBLE_IEEE128__ + | FFI_LINUX_LONG_DOUBLE_IEEE128 +# endif # endif ), - FFI_LAST_ABI = 12 + FFI_LAST_ABI = 16 # else /* This bit, always set in new code, must not be set in any of the @@ -167,9 +171,11 @@ typedef enum ffi_abi { #define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_PPC_TYPE_LAST + 2) /* Used by ELFv2 for homogenous structure returns. */ -#define FFI_V2_TYPE_FLOAT_HOMOG (FFI_PPC_TYPE_LAST + 1) -#define FFI_V2_TYPE_DOUBLE_HOMOG (FFI_PPC_TYPE_LAST + 2) -#define FFI_V2_TYPE_SMALL_STRUCT (FFI_PPC_TYPE_LAST + 3) +#define FFI_V2_TYPE_VECTOR (FFI_PPC_TYPE_LAST + 1) +#define FFI_V2_TYPE_VECTOR_HOMOG (FFI_PPC_TYPE_LAST + 2) +#define FFI_V2_TYPE_FLOAT_HOMOG (FFI_PPC_TYPE_LAST + 3) +#define FFI_V2_TYPE_DOUBLE_HOMOG (FFI_PPC_TYPE_LAST + 4) +#define FFI_V2_TYPE_SMALL_STRUCT (FFI_PPC_TYPE_LAST + 5) #if _CALL_ELF == 2 # define FFI_TRAMPOLINE_SIZE 32 diff --git a/libffi/src/powerpc/linux64.S b/libffi/src/powerpc/linux64.S index f0006fe..e92d64a 100644 --- a/libffi/src/powerpc/linux64.S +++ b/libffi/src/powerpc/linux64.S @@ -109,40 +109,70 @@ ffi_call_LINUX64: ld %r2, 8(%r29) # endif /* Now do the call. */ - /* Set up cr1 with bits 4-7 of the flags. */ - mtcrf 0x40, %r31 + /* Set up cr1 with bits 3-7 of the flags. */ + mtcrf 0xc0, %r31 /* Get the address to call into CTR. */ mtctr %r12 /* Load all those argument registers. */ - ld %r3, -32-(8*8)(%r28) - ld %r4, -32-(7*8)(%r28) - ld %r5, -32-(6*8)(%r28) - ld %r6, -32-(5*8)(%r28) + addi %r29, %r28, -32-(8*8) + ld %r3, (0*8)(%r29) + ld %r4, (1*8)(%r29) + ld %r5, (2*8)(%r29) + ld %r6, (3*8)(%r29) bf- 5, 1f - ld %r7, -32-(4*8)(%r28) - ld %r8, -32-(3*8)(%r28) - ld %r9, -32-(2*8)(%r28) - ld %r10, -32-(1*8)(%r28) + ld %r7, (4*8)(%r29) + ld %r8, (5*8)(%r29) + ld %r9, (6*8)(%r29) + ld %r10, (7*8)(%r29) 1: /* Load all the FP registers. */ bf- 6, 2f - lfd %f1, -32-(21*8)(%r28) - lfd %f2, -32-(20*8)(%r28) - lfd %f3, -32-(19*8)(%r28) - lfd %f4, -32-(18*8)(%r28) - lfd %f5, -32-(17*8)(%r28) - lfd %f6, -32-(16*8)(%r28) - lfd %f7, -32-(15*8)(%r28) - lfd %f8, -32-(14*8)(%r28) - lfd %f9, -32-(13*8)(%r28) - lfd %f10, -32-(12*8)(%r28) - lfd %f11, -32-(11*8)(%r28) - lfd %f12, -32-(10*8)(%r28) - lfd %f13, -32-(9*8)(%r28) + addi %r29, %r29, -(14*8) + lfd %f1, ( 1*8)(%r29) + lfd %f2, ( 2*8)(%r29) + lfd %f3, ( 3*8)(%r29) + lfd %f4, ( 4*8)(%r29) + lfd %f5, ( 5*8)(%r29) + lfd %f6, ( 6*8)(%r29) + lfd %f7, ( 7*8)(%r29) + lfd %f8, ( 8*8)(%r29) + lfd %f9, ( 9*8)(%r29) + lfd %f10, (10*8)(%r29) + lfd %f11, (11*8)(%r29) + lfd %f12, (12*8)(%r29) + lfd %f13, (13*8)(%r29) 2: + /* Load all the vector registers. */ + bf- 3, 3f + addi %r29, %r29, -16 + lvx %v13, 0, %r29 + addi %r29, %r29, -16 + lvx %v12, 0, %r29 + addi %r29, %r29, -16 + lvx %v11, 0, %r29 + addi %r29, %r29, -16 + lvx %v10, 0, %r29 + addi %r29, %r29, -16 + lvx %v9, 0, %r29 + addi %r29, %r29, -16 + lvx %v8, 0, %r29 + addi %r29, %r29, -16 + lvx %v7, 0, %r29 + addi %r29, %r29, -16 + lvx %v6, 0, %r29 + addi %r29, %r29, -16 + lvx %v5, 0, %r29 + addi %r29, %r29, -16 + lvx %v4, 0, %r29 + addi %r29, %r29, -16 + lvx %v3, 0, %r29 + addi %r29, %r29, -16 + lvx %v2, 0, %r29 +3: + /* Make the call. */ ld %r11, 8(%r28) bctrl @@ -160,6 +190,7 @@ ffi_call_LINUX64: bt 31, .Lstruct_return_value bt 30, .Ldone_return_value bt 29, .Lfp_return_value + bt 28, .Lvec_return_value std %r3, 0(%r30) /* Fall through... */ @@ -175,12 +206,16 @@ ffi_call_LINUX64: ld %r31, -8(%r1) blr +.Lvec_return_value: + stvx %v2, 0, %r30 + b .Ldone_return_value + .Lfp_return_value: .cfi_def_cfa_register 28 - bf 28, .Lfloat_return_value - stfd %f1, 0(%r30) mtcrf 0x02, %r31 /* cr6 */ - bf 27, .Ldone_return_value + bf 27, .Lfloat_return_value + stfd %f1, 0(%r30) + bf 26, .Ldone_return_value stfd %f2, 8(%r30) b .Ldone_return_value .Lfloat_return_value: @@ -188,8 +223,9 @@ ffi_call_LINUX64: b .Ldone_return_value .Lstruct_return_value: - bf 29, .Lsmall_struct - bf 28, .Lfloat_homog_return_value + bf 29, .Lvec_homog_or_small_struct + mtcrf 0x02, %r31 /* cr6 */ + bf 27, .Lfloat_homog_return_value stfd %f1, 0(%r30) stfd %f2, 8(%r30) stfd %f3, 16(%r30) @@ -211,6 +247,25 @@ ffi_call_LINUX64: stfs %f8, 28(%r30) b .Ldone_return_value +.Lvec_homog_or_small_struct: + bf 28, .Lsmall_struct + stvx %v2, 0, %r30 + addi %r30, %r30, 16 + stvx %v3, 0, %r30 + addi %r30, %r30, 16 + stvx %v4, 0, %r30 + addi %r30, %r30, 16 + stvx %v5, 0, %r30 + addi %r30, %r30, 16 + stvx %v6, 0, %r30 + addi %r30, %r30, 16 + stvx %v7, 0, %r30 + addi %r30, %r30, 16 + stvx %v8, 0, %r30 + addi %r30, %r30, 16 + stvx %v9, 0, %r30 + b .Ldone_return_value + .Lsmall_struct: std %r3, 0(%r30) std %r4, 8(%r30) diff --git a/libffi/src/powerpc/linux64_closure.S b/libffi/src/powerpc/linux64_closure.S index 5663bb4..3469a2c 100644 --- a/libffi/src/powerpc/linux64_closure.S +++ b/libffi/src/powerpc/linux64_closure.S @@ -63,9 +63,15 @@ ffi_closure_LINUX64: # endif # if _CALL_ELF == 2 -# 32 byte special reg save area + 64 byte parm save area -# + 64 byte retval area + 13*8 fpr save area + round to 16 -# define STACKFRAME 272 +# ifdef __VEC__ +# 32 byte special reg save area + 64 byte parm save area +# + 128 byte retval area + 13*8 fpr save area + 12*16 vec save area + round to 16 +# define STACKFRAME 528 +# else +# 32 byte special reg save area + 64 byte parm save area +# + 64 byte retval area + 13*8 fpr save area + round to 16 +# define STACKFRAME 272 +# endif # define PARMSAVE 32 # define RETVAL PARMSAVE+64 # else @@ -148,6 +154,35 @@ ffi_closure_LINUX64: # load up the pointer to the saved fpr registers addi %r8, %r1, -104 +# ifdef __VEC__ + # load up the pointer to the saved vector registers + # 8 bytes padding for 16-byte alignment at -112(%r1) + addi %r9, %r8, -24 + stvx %v13, 0, %r9 + addi %r9, %r9, -16 + stvx %v12, 0, %r9 + addi %r9, %r9, -16 + stvx %v11, 0, %r9 + addi %r9, %r9, -16 + stvx %v10, 0, %r9 + addi %r9, %r9, -16 + stvx %v9, 0, %r9 + addi %r9, %r9, -16 + stvx %v8, 0, %r9 + addi %r9, %r9, -16 + stvx %v7, 0, %r9 + addi %r9, %r9, -16 + stvx %v6, 0, %r9 + addi %r9, %r9, -16 + stvx %v5, 0, %r9 + addi %r9, %r9, -16 + stvx %v4, 0, %r9 + addi %r9, %r9, -16 + stvx %v3, 0, %r9 + addi %r9, %r9, -16 + stvx %v2, 0, %r9 +# endif + # load up the pointer to the result storage addi %r6, %r1, -STACKFRAME+RETVAL @@ -323,6 +358,16 @@ ffi_closure_LINUX64: .cfi_def_cfa_offset 0 blr .cfi_def_cfa_offset STACKFRAME +# case FFI_V2_TYPE_VECTOR + addi %r3, %r1, RETVAL + lvx %v2, 0, %r3 + mtlr %r0 + b .Lfinish +# case FFI_V2_TYPE_VECTOR_HOMOG + addi %r3, %r1, RETVAL + lvx %v2, 0, %r3 + addi %r3, %r3, 16 + b .Lmorevector # case FFI_V2_TYPE_FLOAT_HOMOG lfs %f1, RETVAL+0(%r1) lfs %f2, RETVAL+4(%r1) @@ -342,6 +387,25 @@ ffi_closure_LINUX64: .cfi_def_cfa_offset 0 blr .cfi_def_cfa_offset STACKFRAME +.Lmorevector: + lvx %v3, 0, %r3 + addi %r3, %r3, 16 + lvx %v4, 0, %r3 + addi %r3, %r3, 16 + lvx %v5, 0, %r3 + mtlr %r0 + addi %r3, %r3, 16 + lvx %v6, 0, %r3 + addi %r3, %r3, 16 + lvx %v7, 0, %r3 + addi %r3, %r3, 16 + lvx %v8, 0, %r3 + addi %r3, %r3, 16 + lvx %v9, 0, %r3 + addi %r1, %r1, STACKFRAME + .cfi_def_cfa_offset 0 + blr + .cfi_def_cfa_offset STACKFRAME .Lmorefloat: lfs %f4, RETVAL+12(%r1) mtlr %r0 diff --git a/libffi/src/powerpc/sysv.S b/libffi/src/powerpc/sysv.S index 1474ce7..df97734 100644 --- a/libffi/src/powerpc/sysv.S +++ b/libffi/src/powerpc/sysv.S @@ -104,17 +104,16 @@ ENTRY(ffi_call_SYSV) bctrl /* Now, deal with the return value. */ - mtcrf 0x01,%r31 /* cr7 */ + mtcrf 0x03,%r31 /* cr6-cr7 */ bt- 31,L(small_struct_return_value) bt- 30,L(done_return_value) #ifndef __NO_FPRS__ bt- 29,L(fp_return_value) #endif stw %r3,0(%r30) - bf+ 28,L(done_return_value) + bf+ 27,L(done_return_value) stw %r4,4(%r30) - mtcrf 0x02,%r31 /* cr6 */ - bf 27,L(done_return_value) + bf 26,L(done_return_value) stw %r5,8(%r30) stw %r6,12(%r30) /* Fall through... */ @@ -145,10 +144,9 @@ L(done_return_value): #ifndef __NO_FPRS__ L(fp_return_value): .cfi_restore_state - bf 28,L(float_return_value) + bf 27,L(float_return_value) stfd %f1,0(%r30) - mtcrf 0x02,%r31 /* cr6 */ - bf 27,L(done_return_value) + bf 26,L(done_return_value) stfd %f2,8(%r30) b L(done_return_value) L(float_return_value): diff --git a/libffi/src/prep_cif.c b/libffi/src/prep_cif.c index 5881ceb..c1832b1 100644 --- a/libffi/src/prep_cif.c +++ b/libffi/src/prep_cif.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------- - prep_cif.c - Copyright (c) 2011, 2012 Anthony Green + prep_cif.c - Copyright (c) 2011, 2012, 2021 Anthony Green Copyright (c) 1996, 1998, 2007 Red Hat, Inc. Permission is hereby granted, free of charge, to any person obtaining @@ -29,12 +29,12 @@ /* Round up to FFI_SIZEOF_ARG. */ -#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) +#define STACK_ARG_SIZE(x) FFI_ALIGN(x, FFI_SIZEOF_ARG) /* Perform machine independent initialization of aggregate type specifications. */ -static ffi_status initialize_aggregate(ffi_type *arg) +static ffi_status initialize_aggregate(ffi_type *arg, size_t *offsets) { ffi_type **ptr; @@ -52,13 +52,15 @@ static ffi_status initialize_aggregate(ffi_type *arg) while ((*ptr) != NULL) { if (UNLIKELY(((*ptr)->size == 0) - && (initialize_aggregate((*ptr)) != FFI_OK))) + && (initialize_aggregate((*ptr), NULL) != FFI_OK))) return FFI_BAD_TYPEDEF; /* Perform a sanity check on the argument type */ FFI_ASSERT_VALID_TYPE(*ptr); - arg->size = ALIGN(arg->size, (*ptr)->alignment); + arg->size = FFI_ALIGN(arg->size, (*ptr)->alignment); + if (offsets) + *offsets++ = arg->size; arg->size += (*ptr)->size; arg->alignment = (arg->alignment > (*ptr)->alignment) ? @@ -74,7 +76,7 @@ static ffi_status initialize_aggregate(ffi_type *arg) struct A { long a; char b; }; struct B { struct A x; char y; }; should find y at an offset of 2*sizeof(long) and result in a total size of 3*sizeof(long). */ - arg->size = ALIGN (arg->size, arg->alignment); + arg->size = FFI_ALIGN (arg->size, arg->alignment); /* On some targets, the ABI defines that structures have an additional alignment beyond the "natural" one based on their elements. */ @@ -127,13 +129,16 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, cif->rtype = rtype; cif->flags = 0; - +#if (defined(_M_ARM64) || defined(__aarch64__)) && defined(_WIN32) + cif->is_variadic = isvariadic; +#endif #if HAVE_LONG_DOUBLE_VARIANT ffi_prep_types (abi); #endif /* Initialize the return type if necessary */ - if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) + if ((cif->rtype->size == 0) + && (initialize_aggregate(cif->rtype, NULL) != FFI_OK)) return FFI_BAD_TYPEDEF; #ifndef FFI_TARGET_HAS_COMPLEX_TYPE @@ -164,7 +169,8 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, { /* Initialize any uninitialized aggregate type definitions */ - if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) + if (((*ptr)->size == 0) + && (initialize_aggregate((*ptr), NULL) != FFI_OK)) return FFI_BAD_TYPEDEF; #ifndef FFI_TARGET_HAS_COMPLEX_TYPE @@ -179,7 +185,7 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, { /* Add any padding if necessary */ if (((*ptr)->alignment - 1) & bytes) - bytes = (unsigned)ALIGN(bytes, (*ptr)->alignment); + bytes = (unsigned)FFI_ALIGN(bytes, (*ptr)->alignment); #ifdef TILE if (bytes < 10 * FFI_SIZEOF_ARG && @@ -195,7 +201,7 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, bytes = 6*4; #endif - bytes += STACK_ARG_SIZE((*ptr)->size); + bytes += (unsigned int)STACK_ARG_SIZE((*ptr)->size); } #endif } @@ -225,7 +231,26 @@ ffi_status ffi_prep_cif_var(ffi_cif *cif, ffi_type *rtype, ffi_type **atypes) { - return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes); + ffi_status rc; + size_t int_size = ffi_type_sint.size; + int i; + + rc = ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes); + + if (rc != FFI_OK) + return rc; + + for (i = 1; i < ntotalargs; i++) + { + ffi_type *arg_type = atypes[i]; + if (arg_type == &ffi_type_float + || ((arg_type->type != FFI_TYPE_STRUCT + && arg_type->type != FFI_TYPE_COMPLEX) + && arg_type->size < int_size)) + return FFI_BAD_ARGTYPE; + } + + return FFI_OK; } #if FFI_CLOSURES @@ -240,3 +265,18 @@ ffi_prep_closure (ffi_closure* closure, } #endif + +ffi_status +ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets) +{ + if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI)) + return FFI_BAD_ABI; + if (struct_type->type != FFI_TYPE_STRUCT) + return FFI_BAD_TYPEDEF; + +#if HAVE_LONG_DOUBLE_VARIANT + ffi_prep_types (abi); +#endif + + return initialize_aggregate(struct_type, offsets); +} diff --git a/libffi/src/raw_api.c b/libffi/src/raw_api.c index 276cb22..be15611 100644 --- a/libffi/src/raw_api.c +++ b/libffi/src/raw_api.c @@ -43,10 +43,10 @@ ffi_raw_size (ffi_cif *cif) { #if !FFI_NO_STRUCTS if ((*at)->type == FFI_TYPE_STRUCT) - result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG); + result += FFI_ALIGN (sizeof (void*), FFI_SIZEOF_ARG); else #endif - result += ALIGN ((*at)->size, FFI_SIZEOF_ARG); + result += FFI_ALIGN ((*at)->size, FFI_SIZEOF_ARG); } return result; @@ -98,7 +98,7 @@ ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args) default: *args = raw; - raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + raw += FFI_ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; } } @@ -123,7 +123,7 @@ ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args) else { *args = (void*) raw; - raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*); + raw += FFI_ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*); } } @@ -186,7 +186,7 @@ ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw) default: memcpy ((void*) raw->data, (void*)*args, (*tp)->size); - raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + raw += FFI_ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; } } } diff --git a/libffi/src/riscv/ffi.c b/libffi/src/riscv/ffi.c index 8c5a860..c910858 100644 --- a/libffi/src/riscv/ffi.c +++ b/libffi/src/riscv/ffi.c @@ -120,7 +120,7 @@ static float_struct_info struct_passed_as_elements(call_builder *cb, ffi_type *t ret.type1 = fields[0]->type; ret.type2 = fields[1]->type; - ret.offset2 = ALIGN(fields[0]->size, fields[1]->alignment); + ret.offset2 = FFI_ALIGN(fields[0]->size, fields[1]->alignment); ret.as_elements = 1; } @@ -238,8 +238,8 @@ static void marshal(call_builder *cb, ffi_type *type, int var, void *data) { /* variadics are aligned even in registers */ if (type->alignment > __SIZEOF_POINTER__) { if (var) - cb->used_integer = ALIGN(cb->used_integer, 2); - cb->used_stack = (size_t *)ALIGN(cb->used_stack, 2*__SIZEOF_POINTER__); + cb->used_integer = FFI_ALIGN(cb->used_integer, 2); + cb->used_stack = (size_t *)FFI_ALIGN(cb->used_stack, 2*__SIZEOF_POINTER__); } memcpy(realign, data, type->size); @@ -286,8 +286,8 @@ static void *unmarshal(call_builder *cb, ffi_type *type, int var, void *data) { /* variadics are aligned even in registers */ if (type->alignment > __SIZEOF_POINTER__) { if (var) - cb->used_integer = ALIGN(cb->used_integer, 2); - cb->used_stack = (size_t *)ALIGN(cb->used_stack, 2*__SIZEOF_POINTER__); + cb->used_integer = FFI_ALIGN(cb->used_integer, 2); + cb->used_stack = (size_t *)FFI_ALIGN(cb->used_stack, 2*__SIZEOF_POINTER__); } if (type->size > 0) @@ -334,10 +334,10 @@ ffi_call_int (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue, /* this is a conservative estimate, assuming a complex return value and that all remaining arguments are long long / __int128 */ size_t arg_bytes = cif->nargs <= 3 ? 0 : - ALIGN(2 * sizeof(size_t) * (cif->nargs - 3), STKALIGN); + FFI_ALIGN(2 * sizeof(size_t) * (cif->nargs - 3), STKALIGN); size_t rval_bytes = 0; if (rvalue == NULL && cif->rtype->size > 2*__SIZEOF_POINTER__) - rval_bytes = ALIGN(cif->rtype->size, STKALIGN); + rval_bytes = FFI_ALIGN(cif->rtype->size, STKALIGN); size_t alloc_size = arg_bytes + rval_bytes + sizeof(call_context); /* the assembly code will deallocate all stack data at lower addresses @@ -350,7 +350,7 @@ ffi_call_int (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue, guarantee alloca alignment to at least that much */ alloc_base = (size_t)alloca(alloc_size); } else { - alloc_base = ALIGN(alloca(alloc_size + STKALIGN - 1), STKALIGN); + alloc_base = FFI_ALIGN(alloca(alloc_size + STKALIGN - 1), STKALIGN); } if (rval_bytes) diff --git a/libffi/src/sparc/ffi.c b/libffi/src/sparc/ffi.c index d5212d8..9e406d0 100644 --- a/libffi/src/sparc/ffi.c +++ b/libffi/src/sparc/ffi.c @@ -153,7 +153,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) /* FALLTHRU */ default: - z = ALIGN(z, 4); + z = FFI_ALIGN(z, 4); } bytes += z; } @@ -167,7 +167,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) bytes += 4; /* The stack must be 2 word aligned, so round bytes up appropriately. */ - bytes = ALIGN(bytes, 2 * 4); + bytes = FFI_ALIGN(bytes, 2 * 4); /* Include the call frame to prep_args. */ bytes += 4*16 + 4*8; @@ -293,7 +293,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, got to pass the return value to the callee. Otherwise ignore it. */ if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_MASK) == SPARC_RET_STRUCT) - bytes += ALIGN (cif->rtype->size, 8); + bytes += FFI_ALIGN (cif->rtype->size, 8); ffi_call_v8(cif, fn, rvalue, avalue, -bytes, closure); } diff --git a/libffi/src/sparc/ffi64.c b/libffi/src/sparc/ffi64.c index 340b198..9e04061 100644 --- a/libffi/src/sparc/ffi64.c +++ b/libffi/src/sparc/ffi64.c @@ -75,7 +75,7 @@ ffi_struct_float_mask (ffi_type *outer_type, int size_mask) size_t z = t->size; int o, m, tt; - size_mask = ALIGN(size_mask, t->alignment); + size_mask = FFI_ALIGN(size_mask, t->alignment); switch (t->type) { case FFI_TYPE_STRUCT: @@ -99,7 +99,7 @@ ffi_struct_float_mask (ffi_type *outer_type, int size_mask) size_mask += z; } - size_mask = ALIGN(size_mask, outer_type->alignment); + size_mask = FFI_ALIGN(size_mask, outer_type->alignment); FFI_ASSERT ((size_mask & 0xff) == outer_type->size); return size_mask; @@ -284,8 +284,8 @@ ffi_prep_cif_machdep_core(ffi_cif *cif) flags |= SPARC_FLAG_FP_ARGS; break; } - bytes = ALIGN(bytes, a); - bytes += ALIGN(z, 8); + bytes = FFI_ALIGN(bytes, a); + bytes += FFI_ALIGN(z, 8); } /* Sparc call frames require that space is allocated for 6 args, @@ -294,7 +294,7 @@ ffi_prep_cif_machdep_core(ffi_cif *cif) bytes = 6 * 8; /* The stack must be 2 word aligned, so round bytes up appropriately. */ - bytes = ALIGN(bytes, 16); + bytes = FFI_ALIGN(bytes, 16); /* Include the call frame to prep_args. */ bytes += 8*16 + 8*8; @@ -405,7 +405,7 @@ ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue) if (((unsigned long)argp & 15) && ty->alignment > 8) argp++; memcpy(argp, a, z); - argp += ALIGN(z, 8) / 8; + argp += FFI_ALIGN(z, 8) / 8; break; default: @@ -425,7 +425,7 @@ ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue, FFI_ASSERT (cif->abi == FFI_V9); if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM)) - bytes += ALIGN (cif->rtype->size, 16); + bytes += FFI_ALIGN (cif->rtype->size, 16); ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure); } @@ -547,7 +547,7 @@ ffi_closure_sparc_inner_v9(ffi_cif *cif, a = *(void **)a; else { - argx = argn + ALIGN (z, 8) / 8; + argx = argn + FFI_ALIGN (z, 8) / 8; if (named && argn < 16) { int size_mask = ffi_struct_float_mask (ty, 0); @@ -561,7 +561,7 @@ ffi_closure_sparc_inner_v9(ffi_cif *cif, break; case FFI_TYPE_LONGDOUBLE: - argn = ALIGN (argn, 2); + argn = FFI_ALIGN (argn, 2); a = (named && argn < 16 ? fpr : gpr) + argn; argx = argn + 2; break; diff --git a/libffi/src/tramp.c b/libffi/src/tramp.c new file mode 100644 index 0000000..265aeaa --- /dev/null +++ b/libffi/src/tramp.c @@ -0,0 +1,729 @@ +/* ----------------------------------------------------------------------- + tramp.c - Copyright (c) 2020 Madhavan T. Venkataraman + + API and support functions for managing statically defined closure + trampolines. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include <fficonfig.h> + +#ifdef FFI_EXEC_STATIC_TRAMP + +/* -------------------------- Headers and Definitions ---------------------*/ +/* + * Add support for other OSes later. For now, it is just Linux. + */ + +#if defined __linux__ +#ifdef __linux__ +#define _GNU_SOURCE 1 +#endif +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <fcntl.h> +#include <pthread.h> +#include <sys/mman.h> +#include <tramp.h> +#ifdef __linux__ +#include <linux/limits.h> +#include <linux/types.h> +#endif +#endif /* __linux__ */ + +/* + * Each architecture defines static code for a trampoline code table. The + * trampoline code table is mapped into the address space of a process. + * + * The following architecture specific function returns: + * + * - the address of the trampoline code table in the text segment + * - the size of each trampoline in the trampoline code table + * - the size of the mapping for the whole trampoline code table + */ +void __attribute__((weak)) *ffi_tramp_arch (size_t *tramp_size, + size_t *map_size); + +/* ------------------------- Trampoline Data Structures --------------------*/ + +struct tramp; + +/* + * Trampoline table. Manages one trampoline code table and one trampoline + * parameter table. + * + * prev, next Links in the global trampoline table list. + * code_table Trampoline code table mapping. + * parm_table Trampoline parameter table mapping. + * array Array of trampolines malloced. + * free List of free trampolines. + * nfree Number of free trampolines. + */ +struct tramp_table +{ + struct tramp_table *prev; + struct tramp_table *next; + void *code_table; + void *parm_table; + struct tramp *array; + struct tramp *free; + int nfree; +}; + +/* + * Parameters for each trampoline. + * + * data + * Data for the target code that the trampoline jumps to. + * target + * Target code that the trampoline jumps to. + */ +struct tramp_parm +{ + void *data; + void *target; +}; + +/* + * Trampoline structure for each trampoline. + * + * prev, next Links in the trampoline free list of a trampoline table. + * table Trampoline table to which this trampoline belongs. + * code Address of this trampoline in the code table mapping. + * parm Address of this trampoline's parameters in the parameter + * table mapping. + */ +struct tramp +{ + struct tramp *prev; + struct tramp *next; + struct tramp_table *table; + void *code; + struct tramp_parm *parm; +}; + +enum tramp_globals_status { + TRAMP_GLOBALS_UNINITIALIZED = 0, + TRAMP_GLOBALS_PASSED, + TRAMP_GLOBALS_FAILED, +}; + +/* + * Trampoline globals. + * + * fd + * File descriptor of binary file that contains the trampoline code table. + * offset + * Offset of the trampoline code table in that file. + * text + * Address of the trampoline code table in the text segment. + * map_size + * Size of the trampoline code table mapping. + * size + * Size of one trampoline in the trampoline code table. + * ntramp + * Total number of trampolines in the trampoline code table. + * free_tables + * List of trampoline tables that contain free trampolines. + * nfree_tables + * Number of trampoline tables that contain free trampolines. + * status + * Initialization status. + */ +struct tramp_globals +{ + int fd; + off_t offset; + void *text; + size_t map_size; + size_t size; + int ntramp; + struct tramp_table *free_tables; + int nfree_tables; + enum tramp_globals_status status; +}; + +static struct tramp_globals tramp_globals; + +/* --------------------- Trampoline File Initialization --------------------*/ + +/* + * The trampoline file is the file used to map the trampoline code table into + * the address space of a process. There are two ways to get this file: + * + * - From the OS. E.g., on Linux, /proc/<pid>/maps lists all the memory + * mappings for <pid>. For file-backed mappings, maps supplies the file name + * and the file offset. Using this, we can locate the mapping that maps + * libffi and get the path to the libffi binary. And, we can compute the + * offset of the trampoline code table within that binary. + * + * - Else, if we can create a temporary file, we can write the trampoline code + * table from the text segment into the temporary file. + * + * The first method is the preferred one. If the OS security subsystem + * disallows mapping unsigned files with PROT_EXEC, then the second method + * will fail. + * + * If an OS allows the trampoline code table in the text segment to be + * directly remapped (e.g., MACH vm_remap ()), then we don't need the + * trampoline file. + */ +static int tramp_table_alloc (void); + +#if defined __linux__ + +static int +ffi_tramp_get_libffi (void) +{ + FILE *fp; + char file[PATH_MAX], line[PATH_MAX+100], perm[10], dev[10]; + unsigned long start, end, offset, inode; + uintptr_t addr = (uintptr_t) tramp_globals.text; + int nfields, found; + + snprintf (file, PATH_MAX, "/proc/%d/maps", getpid()); + fp = fopen (file, "r"); + if (fp == NULL) + return 0; + + found = 0; + while (feof (fp) == 0) { + if (fgets (line, sizeof (line), fp) == 0) + break; + + nfields = sscanf (line, "%lx-%lx %9s %lx %9s %ld %s", + &start, &end, perm, &offset, dev, &inode, file); + if (nfields != 7) + continue; + + if (addr >= start && addr < end) { + tramp_globals.offset = offset + (addr - start); + found = 1; + break; + } + } + fclose (fp); + + if (!found) + return 0; + + tramp_globals.fd = open (file, O_RDONLY); + if (tramp_globals.fd == -1) + return 0; + + /* + * Allocate a trampoline table just to make sure that the trampoline code + * table can be mapped. + */ + if (!tramp_table_alloc ()) + { + close (tramp_globals.fd); + tramp_globals.fd = -1; + return 0; + } + return 1; +} + +#endif /* __linux__ */ + +#if defined __linux__ + +#if defined HAVE_MKSTEMP + +static int +ffi_tramp_get_temp_file (void) +{ + char template[12] = "/tmp/XXXXXX"; + ssize_t count; + + tramp_globals.offset = 0; + tramp_globals.fd = mkstemp (template); + if (tramp_globals.fd == -1) + return 0; + + unlink (template); + /* + * Write the trampoline code table into the temporary file and allocate a + * trampoline table to make sure that the temporary file can be mapped. + */ + count = write(tramp_globals.fd, tramp_globals.text, tramp_globals.map_size); + if (count == tramp_globals.map_size && tramp_table_alloc ()) + return 1; + + close (tramp_globals.fd); + tramp_globals.fd = -1; + return 0; +} + +#else /* !defined HAVE_MKSTEMP */ + +/* + * TODO: + * src/closures.c contains code for finding temp file that has EXEC + * permissions. May be, some of that code can be shared with static + * trampolines. + */ +static int +ffi_tramp_get_temp_file (void) +{ + tramp_globals.offset = 0; + tramp_globals.fd = -1; + return 0; +} + +#endif /* defined HAVE_MKSTEMP */ + +#endif /* __linux__ */ + +/* ------------------------ OS-specific Initialization ----------------------*/ + +#if defined __linux__ + +static int +ffi_tramp_init_os (void) +{ + if (ffi_tramp_get_libffi ()) + return 1; + return ffi_tramp_get_temp_file (); +} + +#endif /* __linux__ */ + +/* --------------------------- OS-specific Locking -------------------------*/ + +#if defined __linux__ + +static pthread_mutex_t tramp_globals_mutex = PTHREAD_MUTEX_INITIALIZER; + +static void +ffi_tramp_lock(void) +{ + pthread_mutex_lock (&tramp_globals_mutex); +} + +static void +ffi_tramp_unlock() +{ + pthread_mutex_unlock (&tramp_globals_mutex); +} + +#endif /* __linux__ */ + +/* ------------------------ OS-specific Memory Mapping ----------------------*/ + +/* + * Create a trampoline code table mapping and a trampoline parameter table + * mapping. The two mappings must be adjacent to each other for PC-relative + * access. + * + * For each trampoline in the code table, there is a corresponding parameter + * block in the parameter table. The size of the parameter block is the same + * as the size of the trampoline. This means that the parameter block is at + * a fixed offset from its trampoline making it easy for a trampoline to find + * its parameters using PC-relative access. + * + * The parameter block will contain a struct tramp_parm. This means that + * sizeof (struct tramp_parm) cannot exceed the size of a parameter block. + */ + +#if defined __linux__ + +static int +tramp_table_map (struct tramp_table *table) +{ + char *addr; + + /* + * Create an anonymous mapping twice the map size. The top half will be used + * for the code table. The bottom half will be used for the parameter table. + */ + addr = mmap (NULL, tramp_globals.map_size * 2, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (addr == MAP_FAILED) + return 0; + + /* + * Replace the top half of the anonymous mapping with the code table mapping. + */ + table->code_table = mmap (addr, tramp_globals.map_size, PROT_READ | PROT_EXEC, + MAP_PRIVATE | MAP_FIXED, tramp_globals.fd, tramp_globals.offset); + if (table->code_table == MAP_FAILED) + { + (void) munmap (addr, tramp_globals.map_size * 2); + return 0; + } + table->parm_table = table->code_table + tramp_globals.map_size; + return 1; +} + +static void +tramp_table_unmap (struct tramp_table *table) +{ + (void) munmap (table->code_table, tramp_globals.map_size); + (void) munmap (table->parm_table, tramp_globals.map_size); +} + +#endif /* __linux__ */ + +/* ------------------------ Trampoline Initialization ----------------------*/ + +/* + * Initialize the static trampoline feature. + */ +static int +ffi_tramp_init (void) +{ + if (tramp_globals.status == TRAMP_GLOBALS_PASSED) + return 1; + + if (tramp_globals.status == TRAMP_GLOBALS_FAILED) + return 0; + + if (ffi_tramp_arch == NULL) + { + tramp_globals.status = TRAMP_GLOBALS_FAILED; + return 0; + } + + tramp_globals.free_tables = NULL; + tramp_globals.nfree_tables = 0; + + /* + * Get trampoline code table information from the architecture. + */ + tramp_globals.text = ffi_tramp_arch (&tramp_globals.size, + &tramp_globals.map_size); + tramp_globals.ntramp = tramp_globals.map_size / tramp_globals.size; + + if (sysconf (_SC_PAGESIZE) > tramp_globals.map_size) + return 0; + + if (ffi_tramp_init_os ()) + { + tramp_globals.status = TRAMP_GLOBALS_PASSED; + return 1; + } + + tramp_globals.status = TRAMP_GLOBALS_FAILED; + return 0; +} + +/* ---------------------- Trampoline Table functions ---------------------- */ + +/* This code assumes that malloc () is available on all OSes. */ + +static void tramp_add (struct tramp *tramp); + +/* + * Allocate and initialize a trampoline table. + */ +static int +tramp_table_alloc (void) +{ + struct tramp_table *table; + struct tramp *tramp_array, *tramp; + size_t size; + char *code, *parm; + int i; + + /* + * If we already have tables with free trampolines, there is no need to + * allocate a new table. + */ + if (tramp_globals.nfree_tables > 0) + return 1; + + /* + * Allocate a new trampoline table structure. + */ + table = malloc (sizeof (*table)); + if (table == NULL) + return 0; + + /* + * Allocate new trampoline structures. + */ + tramp_array = malloc (sizeof (*tramp) * tramp_globals.ntramp); + if (tramp_array == NULL) + goto free_table; + + /* + * Map a code table and a parameter table into the caller's address space. + */ + if (!tramp_table_map (table)) + { + /* + * Failed to map the code and parameter tables. + */ + goto free_tramp_array; + } + + /* + * Initialize the trampoline table. + */ + table->array = tramp_array; + table->free = NULL; + table->nfree = 0; + + /* + * Populate the trampoline table free list. This will also add the trampoline + * table to the global list of trampoline tables. + */ + size = tramp_globals.size; + code = table->code_table; + parm = table->parm_table; + for (i = 0; i < tramp_globals.ntramp; i++) + { + tramp = &tramp_array[i]; + tramp->table = table; + tramp->code = code; + tramp->parm = (struct tramp_parm *) parm; + tramp_add (tramp); + + code += size; + parm += size; + } + /* Success */ + return 1; + +/* Failure */ +free_tramp_array: + free (tramp_array); +free_table: + free (table); + return 0; +} + +/* + * Free a trampoline table. + */ +static void +tramp_table_free (struct tramp_table *table) +{ + tramp_table_unmap (table); + free (table->array); + free (table); +} + +/* + * Add a new trampoline table to the global table list. + */ +static void +tramp_table_add (struct tramp_table *table) +{ + table->next = tramp_globals.free_tables; + table->prev = NULL; + if (tramp_globals.free_tables != NULL) + tramp_globals.free_tables->prev = table; + tramp_globals.free_tables = table; + tramp_globals.nfree_tables++; +} + +/* + * Delete a trampoline table from the global table list. + */ +static void +tramp_table_del (struct tramp_table *table) +{ + tramp_globals.nfree_tables--; + if (table->prev != NULL) + table->prev->next = table->next; + if (table->next != NULL) + table->next->prev = table->prev; + if (tramp_globals.free_tables == table) + tramp_globals.free_tables = table->next; +} + +/* ------------------------- Trampoline functions ------------------------- */ + +/* + * Add a trampoline to its trampoline table. + */ +static void +tramp_add (struct tramp *tramp) +{ + struct tramp_table *table = tramp->table; + + tramp->next = table->free; + tramp->prev = NULL; + if (table->free != NULL) + table->free->prev = tramp; + table->free = tramp; + table->nfree++; + + if (table->nfree == 1) + tramp_table_add (table); + + /* + * We don't want to keep too many free trampoline tables lying around. + */ + if (table->nfree == tramp_globals.ntramp && + tramp_globals.nfree_tables > 1) + { + tramp_table_del (table); + tramp_table_free (table); + } +} + +/* + * Remove a trampoline from its trampoline table. + */ +static void +tramp_del (struct tramp *tramp) +{ + struct tramp_table *table = tramp->table; + + table->nfree--; + if (tramp->prev != NULL) + tramp->prev->next = tramp->next; + if (tramp->next != NULL) + tramp->next->prev = tramp->prev; + if (table->free == tramp) + table->free = tramp->next; + + if (table->nfree == 0) + tramp_table_del (table); +} + +/* ------------------------ Trampoline API functions ------------------------ */ + +int +ffi_tramp_is_supported(void) +{ + int ret; + + ffi_tramp_lock(); + ret = ffi_tramp_init (); + ffi_tramp_unlock(); + return ret; +} + +/* + * Allocate a trampoline and return its opaque address. + */ +void * +ffi_tramp_alloc (int flags) +{ + struct tramp *tramp; + + ffi_tramp_lock(); + + if (!ffi_tramp_init () || flags != 0) + { + ffi_tramp_unlock(); + return NULL; + } + + if (!tramp_table_alloc ()) + { + ffi_tramp_unlock(); + return NULL; + } + + tramp = tramp_globals.free_tables->free; + tramp_del (tramp); + + ffi_tramp_unlock(); + + return tramp; +} + +/* + * Set the parameters for a trampoline. + */ +void +ffi_tramp_set_parms (void *arg, void *target, void *data) +{ + struct tramp *tramp = arg; + + ffi_tramp_lock(); + tramp->parm->target = target; + tramp->parm->data = data; + ffi_tramp_unlock(); +} + +/* + * Get the invocation address of a trampoline. + */ +void * +ffi_tramp_get_addr (void *arg) +{ + struct tramp *tramp = arg; + void *addr; + + ffi_tramp_lock(); + addr = tramp->code; + ffi_tramp_unlock(); + + return addr; +} + +/* + * Free a trampoline. + */ +void +ffi_tramp_free (void *arg) +{ + struct tramp *tramp = arg; + + ffi_tramp_lock(); + tramp_add (tramp); + ffi_tramp_unlock(); +} + +/* ------------------------------------------------------------------------- */ + +#else /* !FFI_EXEC_STATIC_TRAMP */ + +#include <stddef.h> + +int +ffi_tramp_is_supported(void) +{ + return 0; +} + +void * +ffi_tramp_alloc (int flags) +{ + return NULL; +} + +void +ffi_tramp_set_parms (void *arg, void *target, void *data) +{ +} + +void * +ffi_tramp_get_addr (void *arg) +{ + return NULL; +} + +void +ffi_tramp_free (void *arg) +{ +} + +#endif /* FFI_EXEC_STATIC_TRAMP */ diff --git a/libffi/src/types.c b/libffi/src/types.c index 7e80aec..9ec27f6 100644 --- a/libffi/src/types.c +++ b/libffi/src/types.c @@ -38,6 +38,7 @@ struct struct_align_##name { \ char c; \ type x; \ }; \ +FFI_EXTERN \ maybe_const ffi_type ffi_type_##name = { \ sizeof(type), \ offsetof(struct struct_align_##name, x), \ @@ -52,6 +53,7 @@ struct struct_align_complex_##name { \ char c; \ _Complex type x; \ }; \ +FFI_EXTERN \ maybe_const ffi_type ffi_type_complex_##name = { \ sizeof(_Complex type), \ offsetof(struct struct_align_complex_##name, x), \ @@ -60,7 +62,7 @@ maybe_const ffi_type ffi_type_complex_##name = { \ } /* Size and alignment are fake here. They must not be 0. */ -const ffi_type ffi_type_void = { +FFI_EXTERN const ffi_type ffi_type_void = { 1, 1, FFI_TYPE_VOID, NULL }; diff --git a/libffi/src/vax/ffi.c b/libffi/src/vax/ffi.c index f4d6bbb..e52caec 100644 --- a/libffi/src/vax/ffi.c +++ b/libffi/src/vax/ffi.c @@ -108,7 +108,7 @@ ffi_prep_args (extended_cif *ecif, void *stack) /* Align if necessary. */ if ((sizeof(int) - 1) & z) - z = ALIGN(z, sizeof(int)); + z = FFI_ALIGN(z, sizeof(int)); } p_argv++; @@ -215,7 +215,7 @@ ffi_prep_closure_elfbsd (ffi_cif *cif, void **avalue, char *stackp) /* Align if necessary */ if ((sizeof (int) - 1) & z) - z = ALIGN(z, sizeof (int)); + z = FFI_ALIGN(z, sizeof (int)); p_argv++; stackp += z; diff --git a/libffi/src/x86/asmnames.h b/libffi/src/x86/asmnames.h new file mode 100644 index 0000000..7551021 --- /dev/null +++ b/libffi/src/x86/asmnames.h @@ -0,0 +1,30 @@ +#ifndef ASMNAMES_H +#define ASMNAMES_H + +#define C2(X, Y) X ## Y +#define C1(X, Y) C2(X, Y) +#ifdef __USER_LABEL_PREFIX__ +# define C(X) C1(__USER_LABEL_PREFIX__, X) +#else +# define C(X) X +#endif + +#ifdef __APPLE__ +# define L(X) C1(L, X) +#else +# define L(X) C1(.L, X) +#endif + +#if defined(__ELF__) && defined(__PIC__) +# define PLT(X) X@PLT +#else +# define PLT(X) X +#endif + +#ifdef __ELF__ +# define ENDF(X) .type X,@function; .size X, . - X +#else +# define ENDF(X) +#endif + +#endif /* ASMNAMES_H */ diff --git a/libffi/src/x86/darwin.S b/libffi/src/x86/darwin.S deleted file mode 100644 index 8f0f070..0000000 --- a/libffi/src/x86/darwin.S +++ /dev/null @@ -1,444 +0,0 @@ -/* ----------------------------------------------------------------------- - darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005 Red Hat, Inc. - Copyright (C) 2008 Free Software Foundation, Inc. - - X86 Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- - */ - -#ifndef __x86_64__ - -#define LIBFFI_ASM -#include <fficonfig.h> -#include <ffi.h> - -.text - -.globl _ffi_prep_args - - .align 4 -.globl _ffi_call_SYSV - -_ffi_call_SYSV: -.LFB1: - pushl %ebp -.LCFI0: - movl %esp,%ebp -.LCFI1: - subl $8,%esp - /* Make room for all of the new args. */ - movl 16(%ebp),%ecx - subl %ecx,%esp - - movl %esp,%eax - - /* Place all of the ffi_prep_args in position */ - subl $8,%esp - pushl 12(%ebp) - pushl %eax - call *8(%ebp) - - /* Return stack to previous state and call the function */ - addl $16,%esp - - call *28(%ebp) - - /* Load %ecx with the return type code */ - movl 20(%ebp),%ecx - - /* Protect %esi. We're going to pop it in the epilogue. */ - pushl %esi - - /* If the return value pointer is NULL, assume no return value. */ - cmpl $0,24(%ebp) - jne 0f - - /* Even if there is no space for the return value, we are - obliged to handle floating-point values. */ - cmpl $FFI_TYPE_FLOAT,%ecx - jne noretval - fstp %st(0) - - jmp epilogue -0: - .align 4 - call 1f -.Lstore_table: - .long noretval-.Lstore_table /* FFI_TYPE_VOID */ - .long retint-.Lstore_table /* FFI_TYPE_INT */ - .long retfloat-.Lstore_table /* FFI_TYPE_FLOAT */ - .long retdouble-.Lstore_table /* FFI_TYPE_DOUBLE */ - .long retlongdouble-.Lstore_table /* FFI_TYPE_LONGDOUBLE */ - .long retuint8-.Lstore_table /* FFI_TYPE_UINT8 */ - .long retsint8-.Lstore_table /* FFI_TYPE_SINT8 */ - .long retuint16-.Lstore_table /* FFI_TYPE_UINT16 */ - .long retsint16-.Lstore_table /* FFI_TYPE_SINT16 */ - .long retint-.Lstore_table /* FFI_TYPE_UINT32 */ - .long retint-.Lstore_table /* FFI_TYPE_SINT32 */ - .long retint64-.Lstore_table /* FFI_TYPE_UINT64 */ - .long retint64-.Lstore_table /* FFI_TYPE_SINT64 */ - .long retstruct-.Lstore_table /* FFI_TYPE_STRUCT */ - .long retint-.Lstore_table /* FFI_TYPE_POINTER */ - .long retstruct1b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_1B */ - .long retstruct2b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_2B */ -1: - pop %esi - add (%esi, %ecx, 4), %esi - jmp *%esi - - /* Sign/zero extend as appropriate. */ -retsint8: - movsbl %al, %eax - jmp retint - -retsint16: - movswl %ax, %eax - jmp retint - -retuint8: - movzbl %al, %eax - jmp retint - -retuint16: - movzwl %ax, %eax - jmp retint - -retfloat: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstps (%ecx) - jmp epilogue - -retdouble: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstpl (%ecx) - jmp epilogue - -retlongdouble: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstpt (%ecx) - jmp epilogue - -retint64: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - movl %edx,4(%ecx) - jmp epilogue - -retstruct1b: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movb %al,0(%ecx) - jmp epilogue - -retstruct2b: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movw %ax,0(%ecx) - jmp epilogue - -retint: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - -retstruct: - /* Nothing to do! */ - -noretval: -epilogue: - popl %esi - movl %ebp,%esp - popl %ebp - ret - -.LFE1: -.ffi_call_SYSV_end: - - .align 4 -FFI_HIDDEN (ffi_closure_SYSV) -.globl _ffi_closure_SYSV - -_ffi_closure_SYSV: -.LFB2: - pushl %ebp -.LCFI2: - movl %esp, %ebp -.LCFI3: - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) /* resp */ - leal 8(%ebp), %edx - movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */ - leal -12(%ebp), %edx - movl %edx, (%esp) /* &resp */ - movl %ebx, 8(%esp) -.LCFI7: - call L_ffi_closure_SYSV_inner$stub - movl 8(%esp), %ebx - movl -12(%ebp), %ecx - cmpl $FFI_TYPE_INT, %eax - je .Lcls_retint - - /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, - FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ - cmpl $FFI_TYPE_UINT64, %eax - jge 0f - cmpl $FFI_TYPE_UINT8, %eax - jge .Lcls_retint - -0: cmpl $FFI_TYPE_FLOAT, %eax - je .Lcls_retfloat - cmpl $FFI_TYPE_DOUBLE, %eax - je .Lcls_retdouble - cmpl $FFI_TYPE_LONGDOUBLE, %eax - je .Lcls_retldouble - cmpl $FFI_TYPE_SINT64, %eax - je .Lcls_retllong - cmpl $FFI_TYPE_SMALL_STRUCT_1B, %eax - je .Lcls_retstruct1b - cmpl $FFI_TYPE_SMALL_STRUCT_2B, %eax - je .Lcls_retstruct2b - cmpl $FFI_TYPE_STRUCT, %eax - je .Lcls_retstruct -.Lcls_epilogue: - movl %ebp, %esp - popl %ebp - ret -.Lcls_retint: - movl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retfloat: - flds (%ecx) - jmp .Lcls_epilogue -.Lcls_retdouble: - fldl (%ecx) - jmp .Lcls_epilogue -.Lcls_retldouble: - fldt (%ecx) - jmp .Lcls_epilogue -.Lcls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lcls_epilogue -.Lcls_retstruct1b: - movsbl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retstruct2b: - movswl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retstruct: - lea -8(%ebp),%esp - movl %ebp, %esp - popl %ebp - ret $4 -.LFE2: - -#if !FFI_NO_RAW_API - -#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3) -#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) -#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) -#define CIF_FLAGS_OFFSET 20 - - .align 4 -FFI_HIDDEN (ffi_closure_raw_SYSV) -.globl _ffi_closure_raw_SYSV - -_ffi_closure_raw_SYSV: -.LFB3: - pushl %ebp -.LCFI4: - movl %esp, %ebp -.LCFI5: - pushl %esi -.LCFI6: - subl $36, %esp - movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */ - movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ - movl %edx, 12(%esp) /* user_data */ - leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */ - movl %edx, 8(%esp) /* raw_args */ - leal -24(%ebp), %edx - movl %edx, 4(%esp) /* &res */ - movl %esi, (%esp) /* cif */ - call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */ - movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */ - cmpl $FFI_TYPE_INT, %eax - je .Lrcls_retint - - /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, - FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ - cmpl $FFI_TYPE_UINT64, %eax - jge 0f - cmpl $FFI_TYPE_UINT8, %eax - jge .Lrcls_retint -0: - cmpl $FFI_TYPE_FLOAT, %eax - je .Lrcls_retfloat - cmpl $FFI_TYPE_DOUBLE, %eax - je .Lrcls_retdouble - cmpl $FFI_TYPE_LONGDOUBLE, %eax - je .Lrcls_retldouble - cmpl $FFI_TYPE_SINT64, %eax - je .Lrcls_retllong -.Lrcls_epilogue: - addl $36, %esp - popl %esi - popl %ebp - ret -.Lrcls_retint: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue -.Lrcls_retfloat: - flds -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retdouble: - fldl -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retldouble: - fldt -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retllong: - movl -24(%ebp), %eax - movl -20(%ebp), %edx - jmp .Lrcls_epilogue -.LFE3: -#endif - -.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5 -L_ffi_closure_SYSV_inner$stub: - .indirect_symbol _ffi_closure_SYSV_inner - hlt ; hlt ; hlt ; hlt ; hlt - - -.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support -EH_frame1: - .set L$set$0,LECIE1-LSCIE1 - .long L$set$0 -LSCIE1: - .long 0x0 - .byte 0x1 - .ascii "zR\0" - .byte 0x1 - .byte 0x7c - .byte 0x8 - .byte 0x1 - .byte 0x10 - .byte 0xc - .byte 0x5 - .byte 0x4 - .byte 0x88 - .byte 0x1 - .align 2 -LECIE1: -.globl _ffi_call_SYSV.eh -_ffi_call_SYSV.eh: -LSFDE1: - .set L$set$1,LEFDE1-LASFDE1 - .long L$set$1 -LASFDE1: - .long LASFDE1-EH_frame1 - .long .LFB1-. - .set L$set$2,.LFE1-.LFB1 - .long L$set$2 - .byte 0x0 - .byte 0x4 - .set L$set$3,.LCFI0-.LFB1 - .long L$set$3 - .byte 0xe - .byte 0x8 - .byte 0x84 - .byte 0x2 - .byte 0x4 - .set L$set$4,.LCFI1-.LCFI0 - .long L$set$4 - .byte 0xd - .byte 0x4 - .align 2 -LEFDE1: -.globl _ffi_closure_SYSV.eh -_ffi_closure_SYSV.eh: -LSFDE2: - .set L$set$5,LEFDE2-LASFDE2 - .long L$set$5 -LASFDE2: - .long LASFDE2-EH_frame1 - .long .LFB2-. - .set L$set$6,.LFE2-.LFB2 - .long L$set$6 - .byte 0x0 - .byte 0x4 - .set L$set$7,.LCFI2-.LFB2 - .long L$set$7 - .byte 0xe - .byte 0x8 - .byte 0x84 - .byte 0x2 - .byte 0x4 - .set L$set$8,.LCFI3-.LCFI2 - .long L$set$8 - .byte 0xd - .byte 0x4 - .align 2 -LEFDE2: - -#if !FFI_NO_RAW_API - -.globl _ffi_closure_raw_SYSV.eh -_ffi_closure_raw_SYSV.eh: -LSFDE3: - .set L$set$10,LEFDE3-LASFDE3 - .long L$set$10 -LASFDE3: - .long LASFDE3-EH_frame1 - .long .LFB3-. - .set L$set$11,.LFE3-.LFB3 - .long L$set$11 - .byte 0x0 - .byte 0x4 - .set L$set$12,.LCFI4-.LFB3 - .long L$set$12 - .byte 0xe - .byte 0x8 - .byte 0x84 - .byte 0x2 - .byte 0x4 - .set L$set$13,.LCFI5-.LCFI4 - .long L$set$13 - .byte 0xd - .byte 0x4 - .byte 0x4 - .set L$set$14,.LCFI6-.LCFI5 - .long L$set$14 - .byte 0x85 - .byte 0x3 - .align 2 -LEFDE3: - -#endif - -#endif /* ifndef __x86_64__ */ diff --git a/libffi/src/x86/darwin64.S b/libffi/src/x86/darwin64.S deleted file mode 100644 index 2f7394e..0000000 --- a/libffi/src/x86/darwin64.S +++ /dev/null @@ -1,416 +0,0 @@ -/* ----------------------------------------------------------------------- - darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc. - Copyright (c) 2008 Red Hat, Inc. - derived from unix64.S - - x86-64 Foreign Function Interface for Darwin. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#ifdef __x86_64__ -#define LIBFFI_ASM -#include <fficonfig.h> -#include <ffi.h> - - .file "darwin64.S" -.text - -/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, - void *raddr, void (*fnaddr)(void)); - - Bit o trickiness here -- ARGS+BYTES is the base of the stack frame - for this function. This has been allocated by ffi_call. We also - deallocate some of the stack that has been alloca'd. */ - - .align 3 - .globl _ffi_call_unix64 - -_ffi_call_unix64: -LUW0: - movq (%rsp), %r10 /* Load return address. */ - leaq (%rdi, %rsi), %rax /* Find local stack base. */ - movq %rdx, (%rax) /* Save flags. */ - movq %rcx, 8(%rax) /* Save raddr. */ - movq %rbp, 16(%rax) /* Save old frame pointer. */ - movq %r10, 24(%rax) /* Relocate return address. */ - movq %rax, %rbp /* Finalize local stack frame. */ -LUW1: - movq %rdi, %r10 /* Save a copy of the register area. */ - movq %r8, %r11 /* Save a copy of the target fn. */ - movl %r9d, %eax /* Set number of SSE registers. */ - - /* Load up all argument registers. */ - movq (%r10), %rdi - movq 8(%r10), %rsi - movq 16(%r10), %rdx - movq 24(%r10), %rcx - movq 32(%r10), %r8 - movq 40(%r10), %r9 - testl %eax, %eax - jnz Lload_sse -Lret_from_load_sse: - - /* Deallocate the reg arg area. */ - leaq 176(%r10), %rsp - - /* Call the user function. */ - call *%r11 - - /* Deallocate stack arg area; local stack frame in redzone. */ - leaq 24(%rbp), %rsp - - movq 0(%rbp), %rcx /* Reload flags. */ - movq 8(%rbp), %rdi /* Reload raddr. */ - movq 16(%rbp), %rbp /* Reload old frame pointer. */ -LUW2: - - /* The first byte of the flags contains the FFI_TYPE. */ - movzbl %cl, %r10d - leaq Lstore_table(%rip), %r11 - movslq (%r11, %r10, 4), %r10 - addq %r11, %r10 - jmp *%r10 - -Lstore_table: - .long Lst_void-Lstore_table /* FFI_TYPE_VOID */ - .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */ - .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */ - .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */ - .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */ - .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */ - .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */ - .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */ - .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */ - .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */ - .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */ - .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */ - .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */ - .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */ - .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */ - - .text - .align 3 -Lst_void: - ret - .align 3 -Lst_uint8: - movzbq %al, %rax - movq %rax, (%rdi) - ret - .align 3 -Lst_sint8: - movsbq %al, %rax - movq %rax, (%rdi) - ret - .align 3 -Lst_uint16: - movzwq %ax, %rax - movq %rax, (%rdi) - .align 3 -Lst_sint16: - movswq %ax, %rax - movq %rax, (%rdi) - ret - .align 3 -Lst_uint32: - movl %eax, %eax - movq %rax, (%rdi) - .align 3 -Lst_sint32: - cltq - movq %rax, (%rdi) - ret - .align 3 -Lst_int64: - movq %rax, (%rdi) - ret - .align 3 -Lst_float: - movss %xmm0, (%rdi) - ret - .align 3 -Lst_double: - movsd %xmm0, (%rdi) - ret -Lst_ldouble: - fstpt (%rdi) - ret - .align 3 -Lst_struct: - leaq -20(%rsp), %rsi /* Scratch area in redzone. */ - - /* We have to locate the values now, and since we don't want to - write too much data into the user's return value, we spill the - value to a 16 byte scratch area first. Bits 8, 9, and 10 - control where the values are located. Only one of the three - bits will be set; see ffi_prep_cif_machdep for the pattern. */ - movd %xmm0, %r10 - movd %xmm1, %r11 - testl $0x100, %ecx - cmovnz %rax, %rdx - cmovnz %r10, %rax - testl $0x200, %ecx - cmovnz %r10, %rdx - testl $0x400, %ecx - cmovnz %r10, %rax - cmovnz %r11, %rdx - movq %rax, (%rsi) - movq %rdx, 8(%rsi) - - /* Bits 12-31 contain the true size of the structure. Copy from - the scratch area to the true destination. */ - shrl $12, %ecx - rep movsb - ret - - /* Many times we can avoid loading any SSE registers at all. - It's not worth an indirect jump to load the exact set of - SSE registers needed; zero or all is a good compromise. */ - .align 3 -LUW3: -Lload_sse: - movdqa 48(%r10), %xmm0 - movdqa 64(%r10), %xmm1 - movdqa 80(%r10), %xmm2 - movdqa 96(%r10), %xmm3 - movdqa 112(%r10), %xmm4 - movdqa 128(%r10), %xmm5 - movdqa 144(%r10), %xmm6 - movdqa 160(%r10), %xmm7 - jmp Lret_from_load_sse - -LUW4: - .align 3 - .globl _ffi_closure_unix64 - -_ffi_closure_unix64: -LUW5: - /* The carry flag is set by the trampoline iff SSE registers - are used. Don't clobber it before the branch instruction. */ - leaq -200(%rsp), %rsp -LUW6: - movq %rdi, (%rsp) - movq %rsi, 8(%rsp) - movq %rdx, 16(%rsp) - movq %rcx, 24(%rsp) - movq %r8, 32(%rsp) - movq %r9, 40(%rsp) - jc Lsave_sse -Lret_from_save_sse: - - movq %r10, %rdi - leaq 176(%rsp), %rsi - movq %rsp, %rdx - leaq 208(%rsp), %rcx - call _ffi_closure_unix64_inner - - /* Deallocate stack frame early; return value is now in redzone. */ - addq $200, %rsp -LUW7: - - /* The first byte of the return value contains the FFI_TYPE. */ - movzbl %al, %r10d - leaq Lload_table(%rip), %r11 - movslq (%r11, %r10, 4), %r10 - addq %r11, %r10 - jmp *%r10 - -Lload_table: - .long Lld_void-Lload_table /* FFI_TYPE_VOID */ - .long Lld_int32-Lload_table /* FFI_TYPE_INT */ - .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */ - .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */ - .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */ - .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */ - .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */ - .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */ - .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */ - .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */ - .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */ - .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */ - .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */ - .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */ - .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */ - - .text - .align 3 -Lld_void: - ret - .align 3 -Lld_int8: - movzbl -24(%rsp), %eax - ret - .align 3 -Lld_int16: - movzwl -24(%rsp), %eax - ret - .align 3 -Lld_int32: - movl -24(%rsp), %eax - ret - .align 3 -Lld_int64: - movq -24(%rsp), %rax - ret - .align 3 -Lld_float: - movss -24(%rsp), %xmm0 - ret - .align 3 -Lld_double: - movsd -24(%rsp), %xmm0 - ret - .align 3 -Lld_ldouble: - fldt -24(%rsp) - ret - .align 3 -Lld_struct: - /* There are four possibilities here, %rax/%rdx, %xmm0/%rax, - %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading - both rdx and xmm1 with the second word. For the remaining, - bit 8 set means xmm0 gets the second word, and bit 9 means - that rax gets the second word. */ - movq -24(%rsp), %rcx - movq -16(%rsp), %rdx - movq -16(%rsp), %xmm1 - testl $0x100, %eax - cmovnz %rdx, %rcx - movd %rcx, %xmm0 - testl $0x200, %eax - movq -24(%rsp), %rax - cmovnz %rdx, %rax - ret - - /* See the comment above Lload_sse; the same logic applies here. */ - .align 3 -LUW8: -Lsave_sse: - movdqa %xmm0, 48(%rsp) - movdqa %xmm1, 64(%rsp) - movdqa %xmm2, 80(%rsp) - movdqa %xmm3, 96(%rsp) - movdqa %xmm4, 112(%rsp) - movdqa %xmm5, 128(%rsp) - movdqa %xmm6, 144(%rsp) - movdqa %xmm7, 160(%rsp) - jmp Lret_from_save_sse - -LUW9: -.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support -EH_frame1: - .set L$set$0,LECIE1-LSCIE1 /* CIE Length */ - .long L$set$0 -LSCIE1: - .long 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ - .ascii "zR\0" /* CIE Augmentation */ - .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ - .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */ - .byte 0x10 /* CIE RA Column */ - .byte 0x1 /* uleb128 0x1; Augmentation size */ - .byte 0x10 /* FDE Encoding (pcrel sdata4) */ - .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ - .byte 0x7 /* uleb128 0x7 */ - .byte 0x8 /* uleb128 0x8 */ - .byte 0x90 /* DW_CFA_offset, column 0x10 */ - .byte 0x1 - .align 3 -LECIE1: - .globl _ffi_call_unix64.eh -_ffi_call_unix64.eh: -LSFDE1: - .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */ - .long L$set$1 -LASFDE1: - .long LASFDE1-EH_frame1 /* FDE CIE offset */ - .quad LUW0-. /* FDE initial location */ - .set L$set$2,LUW4-LUW0 /* FDE address range */ - .quad L$set$2 - .byte 0x0 /* Augmentation size */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$3,LUW1-LUW0 - .long L$set$3 - - /* New stack frame based off rbp. This is a itty bit of unwind - trickery in that the CFA *has* changed. There is no easy way - to describe it correctly on entry to the function. Fortunately, - it doesn't matter too much since at all points we can correctly - unwind back to ffi_call. Note that the location to which we - moved the return address is (the new) CFA-8, so from the - perspective of the unwind info, it hasn't moved. */ - .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */ - .byte 0x6 - .byte 0x20 - .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */ - .byte 0x2 - .byte 0xa /* DW_CFA_remember_state */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$4,LUW2-LUW1 - .long L$set$4 - .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ - .byte 0x7 - .byte 0x8 - .byte 0xc0+6 /* DW_CFA_restore, %rbp */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$5,LUW3-LUW2 - .long L$set$5 - .byte 0xb /* DW_CFA_restore_state */ - - .align 3 -LEFDE1: - .globl _ffi_closure_unix64.eh -_ffi_closure_unix64.eh: -LSFDE3: - .set L$set$6,LEFDE3-LASFDE3 /* FDE Length */ - .long L$set$6 -LASFDE3: - .long LASFDE3-EH_frame1 /* FDE CIE offset */ - .quad LUW5-. /* FDE initial location */ - .set L$set$7,LUW9-LUW5 /* FDE address range */ - .quad L$set$7 - .byte 0x0 /* Augmentation size */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$8,LUW6-LUW5 - .long L$set$8 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 208,1 /* uleb128 208 */ - .byte 0xa /* DW_CFA_remember_state */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$9,LUW7-LUW6 - .long L$set$9 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$10,LUW8-LUW7 - .long L$set$10 - .byte 0xb /* DW_CFA_restore_state */ - - .align 3 -LEFDE3: - .subsections_via_symbols - -#endif /* __x86_64__ */ diff --git a/libffi/src/x86/darwin64_c.c b/libffi/src/x86/darwin64_c.c deleted file mode 100644 index 1daa1c0..0000000 --- a/libffi/src/x86/darwin64_c.c +++ /dev/null @@ -1,643 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi64.c - Copyright (c) 20011 Anthony Green - Copyright (c) 2008, 2010 Red Hat, Inc. - Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de> - - x86-64 Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include <ffi.h> -#include <ffi_common.h> - -#include <stdlib.h> -#include <stdarg.h> - -#ifdef __x86_64__ - -#define MAX_GPR_REGS 6 -#define MAX_SSE_REGS 8 - -#ifdef __INTEL_COMPILER -#define UINT128 __m128 -#else -#define UINT128 __int128_t -#endif - -struct register_args -{ - /* Registers for argument passing. */ - UINT64 gpr[MAX_GPR_REGS]; - UINT128 sse[MAX_SSE_REGS]; -}; - -extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, - void *raddr, void (*fnaddr)(void), unsigned ssecount); - -/* All reference to register classes here is identical to the code in - gcc/config/i386/i386.c. Do *not* change one without the other. */ - -/* Register class used for passing given 64bit part of the argument. - These represent classes as documented by the PS ABI, with the - exception of SSESF, SSEDF classes, that are basically SSE class, - just gcc will use SF or DFmode move instead of DImode to avoid - reformatting penalties. - - Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves - whenever possible (upper half does contain padding). */ -enum x86_64_reg_class - { - X86_64_NO_CLASS, - X86_64_INTEGER_CLASS, - X86_64_INTEGERSI_CLASS, - X86_64_SSE_CLASS, - X86_64_SSESF_CLASS, - X86_64_SSEDF_CLASS, - X86_64_SSEUP_CLASS, - X86_64_X87_CLASS, - X86_64_X87UP_CLASS, - X86_64_COMPLEX_X87_CLASS, - X86_64_MEMORY_CLASS - }; - -#define MAX_CLASSES 4 - -#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS) - -/* x86-64 register passing implementation. See x86-64 ABI for details. Goal - of this code is to classify each 8bytes of incoming argument by the register - class and assign registers accordingly. */ - -/* Return the union class of CLASS1 and CLASS2. - See the x86-64 PS ABI for details. */ - -static enum x86_64_reg_class -merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2) -{ - /* Rule #1: If both classes are equal, this is the resulting class. */ - if (class1 == class2) - return class1; - - /* Rule #2: If one of the classes is NO_CLASS, the resulting class is - the other class. */ - if (class1 == X86_64_NO_CLASS) - return class2; - if (class2 == X86_64_NO_CLASS) - return class1; - - /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */ - if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) - return X86_64_MEMORY_CLASS; - - /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ - if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) - || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) - return X86_64_INTEGERSI_CLASS; - if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS - || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) - return X86_64_INTEGER_CLASS; - - /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class, - MEMORY is used. */ - if (class1 == X86_64_X87_CLASS - || class1 == X86_64_X87UP_CLASS - || class1 == X86_64_COMPLEX_X87_CLASS - || class2 == X86_64_X87_CLASS - || class2 == X86_64_X87UP_CLASS - || class2 == X86_64_COMPLEX_X87_CLASS) - return X86_64_MEMORY_CLASS; - - /* Rule #6: Otherwise class SSE is used. */ - return X86_64_SSE_CLASS; -} - -/* Classify the argument of type TYPE and mode MODE. - CLASSES will be filled by the register class used to pass each word - of the operand. The number of words is returned. In case the parameter - should be passed in memory, 0 is returned. As a special case for zero - sized containers, classes[0] will be NO_CLASS and 1 is returned. - - See the x86-64 PS ABI for details. -*/ -static int -classify_argument (ffi_type *type, enum x86_64_reg_class classes[], - size_t byte_offset) -{ - switch (type->type) - { - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_POINTER: - { - int size = byte_offset + type->size; - - if (size <= 4) - { - classes[0] = X86_64_INTEGERSI_CLASS; - return 1; - } - else if (size <= 8) - { - classes[0] = X86_64_INTEGER_CLASS; - return 1; - } - else if (size <= 12) - { - classes[0] = X86_64_INTEGER_CLASS; - classes[1] = X86_64_INTEGERSI_CLASS; - return 2; - } - else if (size <= 16) - { - classes[0] = classes[1] = X86_64_INTEGERSI_CLASS; - return 2; - } - else - FFI_ASSERT (0); - } - case FFI_TYPE_FLOAT: - if (!(byte_offset % 8)) - classes[0] = X86_64_SSESF_CLASS; - else - classes[0] = X86_64_SSE_CLASS; - return 1; - case FFI_TYPE_DOUBLE: - classes[0] = X86_64_SSEDF_CLASS; - return 1; - case FFI_TYPE_LONGDOUBLE: - classes[0] = X86_64_X87_CLASS; - classes[1] = X86_64_X87UP_CLASS; - return 2; - case FFI_TYPE_STRUCT: - { - const int UNITS_PER_WORD = 8; - int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - ffi_type **ptr; - int i; - enum x86_64_reg_class subclasses[MAX_CLASSES]; - - /* If the struct is larger than 32 bytes, pass it on the stack. */ - if (type->size > 32) - return 0; - - for (i = 0; i < words; i++) - classes[i] = X86_64_NO_CLASS; - - /* Zero sized arrays or structures are NO_CLASS. We return 0 to - signalize memory class, so handle it as special case. */ - if (!words) - { - classes[0] = X86_64_NO_CLASS; - return 1; - } - - /* Merge the fields of structure. */ - for (ptr = type->elements; *ptr != NULL; ptr++) - { - int num; - - byte_offset = ALIGN (byte_offset, (*ptr)->alignment); - - num = classify_argument (*ptr, subclasses, byte_offset % 8); - if (num == 0) - return 0; - for (i = 0; i < num; i++) - { - int pos = byte_offset / 8; - classes[i + pos] = - merge_classes (subclasses[i], classes[i + pos]); - } - - byte_offset += (*ptr)->size; - } - - if (words > 2) - { - /* When size > 16 bytes, if the first one isn't - X86_64_SSE_CLASS or any other ones aren't - X86_64_SSEUP_CLASS, everything should be passed in - memory. */ - if (classes[0] != X86_64_SSE_CLASS) - return 0; - - for (i = 1; i < words; i++) - if (classes[i] != X86_64_SSEUP_CLASS) - return 0; - } - - /* Final merger cleanup. */ - for (i = 0; i < words; i++) - { - /* If one class is MEMORY, everything should be passed in - memory. */ - if (classes[i] == X86_64_MEMORY_CLASS) - return 0; - - /* The X86_64_SSEUP_CLASS should be always preceded by - X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */ - if (classes[i] == X86_64_SSEUP_CLASS - && classes[i - 1] != X86_64_SSE_CLASS - && classes[i - 1] != X86_64_SSEUP_CLASS) - { - /* The first one should never be X86_64_SSEUP_CLASS. */ - FFI_ASSERT (i != 0); - classes[i] = X86_64_SSE_CLASS; - } - - /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS, - everything should be passed in memory. */ - if (classes[i] == X86_64_X87UP_CLASS - && (classes[i - 1] != X86_64_X87_CLASS)) - { - /* The first one should never be X86_64_X87UP_CLASS. */ - FFI_ASSERT (i != 0); - return 0; - } - } - return words; - } - - default: - FFI_ASSERT(0); - } - return 0; /* Never reached. */ -} - -/* Examine the argument and return set number of register required in each - class. Return zero iff parameter should be passed in memory, otherwise - the number of registers. */ - -static int -examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES], - _Bool in_return, int *pngpr, int *pnsse) -{ - int i, n, ngpr, nsse; - - n = classify_argument (type, classes, 0); - if (n == 0) - return 0; - - ngpr = nsse = 0; - for (i = 0; i < n; ++i) - switch (classes[i]) - { - case X86_64_INTEGER_CLASS: - case X86_64_INTEGERSI_CLASS: - ngpr++; - break; - case X86_64_SSE_CLASS: - case X86_64_SSESF_CLASS: - case X86_64_SSEDF_CLASS: - nsse++; - break; - case X86_64_NO_CLASS: - case X86_64_SSEUP_CLASS: - break; - case X86_64_X87_CLASS: - case X86_64_X87UP_CLASS: - case X86_64_COMPLEX_X87_CLASS: - return in_return != 0; - default: - abort (); - } - - *pngpr = ngpr; - *pnsse = nsse; - - return n; -} - -/* Perform machine dependent cif processing. */ - -ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) -{ - int gprcount, ssecount, i, avn, n, ngpr, nsse, flags; - enum x86_64_reg_class classes[MAX_CLASSES]; - size_t bytes; - - gprcount = ssecount = 0; - - flags = cif->rtype->type; - if (flags != FFI_TYPE_VOID) - { - n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); - if (n == 0) - { - /* The return value is passed in memory. A pointer to that - memory is the first argument. Allocate a register for it. */ - gprcount++; - /* We don't have to do anything in asm for the return. */ - flags = FFI_TYPE_VOID; - } - else if (flags == FFI_TYPE_STRUCT) - { - /* Mark which registers the result appears in. */ - _Bool sse0 = SSE_CLASS_P (classes[0]); - _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]); - if (sse0 && !sse1) - flags |= 1 << 8; - else if (!sse0 && sse1) - flags |= 1 << 9; - else if (sse0 && sse1) - flags |= 1 << 10; - /* Mark the true size of the structure. */ - flags |= cif->rtype->size << 12; - } - } - - /* Go over all arguments and determine the way they should be passed. - If it's in a register and there is space for it, let that be so. If - not, add it's size to the stack byte count. */ - for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++) - { - if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0 - || gprcount + ngpr > MAX_GPR_REGS - || ssecount + nsse > MAX_SSE_REGS) - { - long align = cif->arg_types[i]->alignment; - - if (align < 8) - align = 8; - - bytes = ALIGN (bytes, align); - bytes += cif->arg_types[i]->size; - } - else - { - gprcount += ngpr; - ssecount += nsse; - } - } - if (ssecount) - flags |= 1 << 11; - cif->flags = flags; - cif->bytes = ALIGN (bytes, 8); - - return FFI_OK; -} - -void -ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - enum x86_64_reg_class classes[MAX_CLASSES]; - char *stack, *argp; - ffi_type **arg_types; - int gprcount, ssecount, ngpr, nsse, i, avn; - _Bool ret_in_memory; - struct register_args *reg_args; - - /* Can't call 32-bit mode from 64-bit mode. */ - FFI_ASSERT (cif->abi == FFI_UNIX64); - - /* If the return value is a struct and we don't have a return value - address then we need to make one. Note the setting of flags to - VOID above in ffi_prep_cif_machdep. */ - ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT - && (cif->flags & 0xff) == FFI_TYPE_VOID); - if (rvalue == NULL && ret_in_memory) - rvalue = alloca (cif->rtype->size); - - /* Allocate the space for the arguments, plus 4 words of temp space. */ - stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8); - reg_args = (struct register_args *) stack; - argp = stack + sizeof (struct register_args); - - gprcount = ssecount = 0; - - /* If the return value is passed in memory, add the pointer as the - first integer argument. */ - if (ret_in_memory) - reg_args->gpr[gprcount++] = (unsigned long) rvalue; - - avn = cif->nargs; - arg_types = cif->arg_types; - - for (i = 0; i < avn; ++i) - { - size_t size = arg_types[i]->size; - int n; - - n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); - if (n == 0 - || gprcount + ngpr > MAX_GPR_REGS - || ssecount + nsse > MAX_SSE_REGS) - { - long align = arg_types[i]->alignment; - - /* Stack arguments are *always* at least 8 byte aligned. */ - if (align < 8) - align = 8; - - /* Pass this argument in memory. */ - argp = (void *) ALIGN (argp, align); - memcpy (argp, avalue[i], size); - argp += size; - } - else - { - /* The argument is passed entirely in registers. */ - char *a = (char *) avalue[i]; - int j; - - for (j = 0; j < n; j++, a += 8, size -= 8) - { - switch (classes[j]) - { - case X86_64_INTEGER_CLASS: - case X86_64_INTEGERSI_CLASS: - reg_args->gpr[gprcount] = 0; - memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); - gprcount++; - break; - case X86_64_SSE_CLASS: - case X86_64_SSEDF_CLASS: - reg_args->sse[ssecount++] = *(UINT64 *) a; - break; - case X86_64_SSESF_CLASS: - reg_args->sse[ssecount++] = *(UINT32 *) a; - break; - default: - abort(); - } - } - } - } - - ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args), - cif->flags, rvalue, fn, ssecount); -} - - -extern void ffi_closure_unix64(void); - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - volatile unsigned short *tramp; - - /* Sanity check on the cif ABI. */ - { - int abi = cif->abi; - if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))) - return FFI_BAD_ABI; - } - - tramp = (volatile unsigned short *) &closure->tramp[0]; - - tramp[0] = 0xbb49; /* mov <code>, %r11 */ - *((unsigned long long * volatile) &tramp[1]) - = (unsigned long) ffi_closure_unix64; - tramp[5] = 0xba49; /* mov <data>, %r10 */ - *((unsigned long long * volatile) &tramp[6]) - = (unsigned long) codeloc; - - /* Set the carry bit iff the function uses any sse registers. - This is clc or stc, together with the first byte of the jmp. */ - tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8; - - tramp[11] = 0xe3ff; /* jmp *%r11 */ - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - return FFI_OK; -} - -int -ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue, - struct register_args *reg_args, char *argp) -{ - ffi_cif *cif; - void **avalue; - ffi_type **arg_types; - long i, avn; - int gprcount, ssecount, ngpr, nsse; - int ret; - - cif = closure->cif; - avalue = alloca(cif->nargs * sizeof(void *)); - gprcount = ssecount = 0; - - ret = cif->rtype->type; - if (ret != FFI_TYPE_VOID) - { - enum x86_64_reg_class classes[MAX_CLASSES]; - int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); - if (n == 0) - { - /* The return value goes in memory. Arrange for the closure - return value to go directly back to the original caller. */ - rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++]; - /* We don't have to do anything in asm for the return. */ - ret = FFI_TYPE_VOID; - } - else if (ret == FFI_TYPE_STRUCT && n == 2) - { - /* Mark which register the second word of the structure goes in. */ - _Bool sse0 = SSE_CLASS_P (classes[0]); - _Bool sse1 = SSE_CLASS_P (classes[1]); - if (!sse0 && sse1) - ret |= 1 << 8; - else if (sse0 && !sse1) - ret |= 1 << 9; - } - } - - avn = cif->nargs; - arg_types = cif->arg_types; - - for (i = 0; i < avn; ++i) - { - enum x86_64_reg_class classes[MAX_CLASSES]; - int n; - - n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); - if (n == 0 - || gprcount + ngpr > MAX_GPR_REGS - || ssecount + nsse > MAX_SSE_REGS) - { - long align = arg_types[i]->alignment; - - /* Stack arguments are *always* at least 8 byte aligned. */ - if (align < 8) - align = 8; - - /* Pass this argument in memory. */ - argp = (void *) ALIGN (argp, align); - avalue[i] = argp; - argp += arg_types[i]->size; - } - /* If the argument is in a single register, or two consecutive - integer registers, then we can use that address directly. */ - else if (n == 1 - || (n == 2 && !(SSE_CLASS_P (classes[0]) - || SSE_CLASS_P (classes[1])))) - { - /* The argument is in a single register. */ - if (SSE_CLASS_P (classes[0])) - { - avalue[i] = ®_args->sse[ssecount]; - ssecount += n; - } - else - { - avalue[i] = ®_args->gpr[gprcount]; - gprcount += n; - } - } - /* Otherwise, allocate space to make them consecutive. */ - else - { - char *a = alloca (16); - int j; - - avalue[i] = a; - for (j = 0; j < n; j++, a += 8) - { - if (SSE_CLASS_P (classes[j])) - memcpy (a, ®_args->sse[ssecount++], 8); - else - memcpy (a, ®_args->gpr[gprcount++], 8); - } - } - } - - /* Invoke the closure. */ - closure->fun (cif, rvalue, avalue, closure->user_data); - - /* Tell assembly how to perform return type promotions. */ - return ret; -} - -#endif /* __x86_64__ */ diff --git a/libffi/src/x86/darwin_c.c b/libffi/src/x86/darwin_c.c deleted file mode 100644 index 6338de2..0000000 --- a/libffi/src/x86/darwin_c.c +++ /dev/null @@ -1,843 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc. - Copyright (c) 2002 Ranjit Mathew - Copyright (c) 2002 Bo Thorsen - Copyright (c) 2002 Roger Sayle - Copyright (C) 2008, 2010 Free Software Foundation, Inc. - - x86 Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#if !defined(__x86_64__) || defined(_WIN64) || defined(__CYGWIN__) - -#ifdef _WIN64 -#include <windows.h> -#endif - -#include <ffi.h> -#include <ffi_common.h> - -#include <stdlib.h> - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ - -void ffi_prep_args(char *stack, extended_cif *ecif) -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; -#ifdef X86_WIN32 - size_t p_stack_args[2]; - void *p_stack_data[2]; - char *argp2 = stack; - int stack_args_count = 0; - int cabi = ecif->cif->abi; -#endif - - argp = stack; - - if ((ecif->cif->flags == FFI_TYPE_STRUCT - || ecif->cif->flags == FFI_TYPE_MS_STRUCT) -#ifdef X86_WIN64 - && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2 - && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8) -#endif - ) - { - *(void **) argp = ecif->rvalue; -#ifdef X86_WIN32 - /* For fastcall/thiscall this is first register-passed - argument. */ - if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL) - { - p_stack_args[stack_args_count] = sizeof (void*); - p_stack_data[stack_args_count] = argp; - ++stack_args_count; - } -#endif - argp += sizeof(void*); - } - - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - i != 0; - i--, p_arg++) - { - size_t z; - - /* Align if necessary */ - if ((sizeof(void*) - 1) & (size_t) argp) - argp = (char *) ALIGN(argp, sizeof(void*)); - - z = (*p_arg)->size; -#ifdef X86_WIN64 - if (z > sizeof(ffi_arg) - || ((*p_arg)->type == FFI_TYPE_STRUCT - && (z != 1 && z != 2 && z != 4 && z != 8)) -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE) -#endif - ) - { - z = sizeof(ffi_arg); - *(void **)argp = *p_argv; - } - else if ((*p_arg)->type == FFI_TYPE_FLOAT) - { - memcpy(argp, *p_argv, z); - } - else -#endif - if (z < sizeof(ffi_arg)) - { - z = sizeof(ffi_arg); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv); - break; - - case FFI_TYPE_SINT32: - *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv); - break; - - case FFI_TYPE_UINT32: - *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv); - break; - - case FFI_TYPE_STRUCT: - *(ffi_arg *) argp = *(ffi_arg *)(* p_argv); - break; - - default: - FFI_ASSERT(0); - } - } - else - { - memcpy(argp, *p_argv, z); - } - -#ifdef X86_WIN32 - /* For thiscall/fastcall convention register-passed arguments - are the first two none-floating-point arguments with a size - smaller or equal to sizeof (void*). */ - if ((cabi == FFI_THISCALL && stack_args_count < 1) - || (cabi == FFI_FASTCALL && stack_args_count < 2)) - { - if (z <= 4 - && ((*p_arg)->type != FFI_TYPE_FLOAT - && (*p_arg)->type != FFI_TYPE_STRUCT)) - { - p_stack_args[stack_args_count] = z; - p_stack_data[stack_args_count] = argp; - ++stack_args_count; - } - } -#endif - p_argv++; -#ifdef X86_WIN64 - argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1); -#else - argp += z; -#endif - } - -#ifdef X86_WIN32 - /* We need to move the register-passed arguments for thiscall/fastcall - on top of stack, so that those can be moved to registers ecx/edx by - call-handler. */ - if (stack_args_count > 0) - { - size_t zz = (p_stack_args[0] + 3) & ~3; - char *h; - - /* Move first argument to top-stack position. */ - if (p_stack_data[0] != argp2) - { - h = alloca (zz + 1); - memcpy (h, p_stack_data[0], zz); - memmove (argp2 + zz, argp2, - (size_t) ((char *) p_stack_data[0] - (char*)argp2)); - memcpy (argp2, h, zz); - } - - argp2 += zz; - --stack_args_count; - if (zz > 4) - stack_args_count = 0; - - /* If we have a second argument, then move it on top - after the first one. */ - if (stack_args_count > 0 && p_stack_data[1] != argp2) - { - zz = p_stack_args[1]; - zz = (zz + 3) & ~3; - h = alloca (zz + 1); - h = alloca (zz + 1); - memcpy (h, p_stack_data[1], zz); - memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2)); - memcpy (argp2, h, zz); - } - } -#endif - return; -} - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - unsigned int i; - ffi_type **ptr; - - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_UINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT8: - case FFI_TYPE_SINT16: -#ifdef X86_WIN64 - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: -#endif - case FFI_TYPE_SINT64: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#ifndef X86_WIN64 -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif -#endif - cif->flags = (unsigned) cif->rtype->type; - break; - - case FFI_TYPE_UINT64: -#ifdef X86_WIN64 - case FFI_TYPE_POINTER: -#endif - cif->flags = FFI_TYPE_SINT64; - break; - - case FFI_TYPE_STRUCT: -#ifndef X86 - if (cif->rtype->size == 1) - { - cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */ - } - else if (cif->rtype->size == 2) - { - cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */ - } - else if (cif->rtype->size == 4) - { -#ifdef X86_WIN64 - cif->flags = FFI_TYPE_SMALL_STRUCT_4B; -#else - cif->flags = FFI_TYPE_INT; /* same as int type */ -#endif - } - else if (cif->rtype->size == 8) - { - cif->flags = FFI_TYPE_SINT64; /* same as int64 type */ - } - else -#endif - { -#ifdef X86_WIN32 - if (cif->abi == FFI_MS_CDECL) - cif->flags = FFI_TYPE_MS_STRUCT; - else -#endif - cif->flags = FFI_TYPE_STRUCT; - /* allocate space for return value pointer */ - cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG); - } - break; - - default: -#ifdef X86_WIN64 - cif->flags = FFI_TYPE_SINT64; - break; - case FFI_TYPE_INT: - cif->flags = FFI_TYPE_SINT32; -#else - cif->flags = FFI_TYPE_INT; -#endif - break; - } - - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - if (((*ptr)->alignment - 1) & cif->bytes) - cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment); - cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG); - } - -#ifdef X86_WIN64 - /* ensure space for storing four registers */ - cif->bytes += 4 * sizeof(ffi_arg); -#endif - -#ifdef X86_DARWIN - cif->bytes = (cif->bytes + 15) & ~0xF; -#endif - - return FFI_OK; -} - -#ifdef X86_WIN64 -extern int -ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned *, void (*fn)(void)); -#elif defined(X86_WIN32) -extern void -ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned, unsigned *, void (*fn)(void)); -#else -extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned *, void (*fn)(void)); -#endif - -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - -#ifdef X86_WIN64 - if (rvalue == NULL - && cif->flags == FFI_TYPE_STRUCT - && cif->rtype->size != 1 && cif->rtype->size != 2 - && cif->rtype->size != 4 && cif->rtype->size != 8) - { - ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF); - } -#else - if (rvalue == NULL - && (cif->flags == FFI_TYPE_STRUCT - || cif->flags == FFI_TYPE_MS_STRUCT)) - { - ecif.rvalue = alloca(cif->rtype->size); - } -#endif - else - ecif.rvalue = rvalue; - - - switch (cif->abi) - { -#ifdef X86_WIN64 - case FFI_WIN64: - ffi_call_win64(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - break; -#elif defined(X86_WIN32) - case FFI_SYSV: - case FFI_STDCALL: - case FFI_MS_CDECL: - ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; - case FFI_THISCALL: - case FFI_FASTCALL: - { - unsigned int abi = cif->abi; - unsigned int i, passed_regs = 0; - - if (cif->flags == FFI_TYPE_STRUCT) - ++passed_regs; - - for (i=0; i < cif->nargs && passed_regs < 2;i++) - { - size_t sz; - - if (cif->arg_types[i]->type == FFI_TYPE_FLOAT - || cif->arg_types[i]->type == FFI_TYPE_STRUCT) - continue; - sz = (cif->arg_types[i]->size + 3) & ~3; - if (sz == 0 || sz > 4) - continue; - ++passed_regs; - } - if (passed_regs < 2 && abi == FFI_FASTCALL) - abi = FFI_THISCALL; - if (passed_regs < 1 && abi == FFI_THISCALL) - abi = FFI_STDCALL; - ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - } - break; -#else - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, - fn); - break; -#endif - default: - FFI_ASSERT(0); - break; - } -} - - -/** private members **/ - -/* The following __attribute__((regparm(1))) decorations will have no effect - on MSVC - standard cdecl convention applies. */ -static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, - void** args, ffi_cif* cif); -void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *) - __attribute__ ((regparm(1))); -unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *) - __attribute__ ((regparm(1))); -void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *) - __attribute__ ((regparm(1))); -#ifdef X86_WIN32 -void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *) - __attribute__ ((regparm(1))); -void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *) - __attribute__ ((regparm(1))); -void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *) - __attribute__ ((regparm(1))); -#endif -#ifdef X86_WIN64 -void FFI_HIDDEN ffi_closure_win64 (ffi_closure *); -#endif - -/* This function is jumped to by the trampoline */ - -#ifdef X86_WIN64 -void * FFI_HIDDEN -ffi_closure_win64_inner (ffi_closure *closure, void *args) { - ffi_cif *cif; - void **arg_area; - void *result; - void *resp = &result; - - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void*)); - - /* this call will initialize ARG_AREA, such that each - * element in that array points to the corresponding - * value on the stack; and if the function returns - * a structure, it will change RESP to point to the - * structure return address. */ - - ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif); - - (closure->fun) (cif, resp, arg_area, closure->user_data); - - /* The result is returned in rax. This does the right thing for - result types except for floats; we have to 'mov xmm0, rax' in the - caller to correct this. - TODO: structure sizes of 3 5 6 7 are returned by reference, too!!! - */ - return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp; -} - -#else -unsigned int FFI_HIDDEN __attribute__ ((regparm(1))) -ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args) -{ - /* our various things... */ - ffi_cif *cif; - void **arg_area; - - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void*)); - - /* this call will initialize ARG_AREA, such that each - * element in that array points to the corresponding - * value on the stack; and if the function returns - * a structure, it will change RESP to point to the - * structure return address. */ - - ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif); - - (closure->fun) (cif, *respp, arg_area, closure->user_data); - - return cif->flags; -} -#endif /* !X86_WIN64 */ - -static void -ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue, - ffi_cif *cif) -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - - argp = stack; - -#ifdef X86_WIN64 - if (cif->rtype->size > sizeof(ffi_arg) - || (cif->flags == FFI_TYPE_STRUCT - && (cif->rtype->size != 1 && cif->rtype->size != 2 - && cif->rtype->size != 4 && cif->rtype->size != 8))) { - *rvalue = *(void **) argp; - argp += sizeof(void *); - } -#else - if ( cif->flags == FFI_TYPE_STRUCT - || cif->flags == FFI_TYPE_MS_STRUCT ) { - *rvalue = *(void **) argp; - argp += sizeof(void *); - } -#endif - - p_argv = avalue; - - for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) - { - size_t z; - - /* Align if necessary */ - if ((sizeof(void*) - 1) & (size_t) argp) { - argp = (char *) ALIGN(argp, sizeof(void*)); - } - -#ifdef X86_WIN64 - if ((*p_arg)->size > sizeof(ffi_arg) - || ((*p_arg)->type == FFI_TYPE_STRUCT - && ((*p_arg)->size != 1 && (*p_arg)->size != 2 - && (*p_arg)->size != 4 && (*p_arg)->size != 8))) - { - z = sizeof(void *); - *p_argv = *(void **)argp; - } - else -#endif - { - z = (*p_arg)->size; - - /* because we're little endian, this is what it turns into. */ - - *p_argv = (void*) argp; - } - - p_argv++; -#ifdef X86_WIN64 - argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1); -#else - argp += z; -#endif - } - - return; -} - -#define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \ -{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - void* __fun = (void*)(FUN); \ - void* __ctx = (void*)(CTX); \ - *(unsigned char*) &__tramp[0] = 0x41; \ - *(unsigned char*) &__tramp[1] = 0xbb; \ - *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \ - *(unsigned char*) &__tramp[6] = 0x48; \ - *(unsigned char*) &__tramp[7] = 0xb8; \ - *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \ - *(unsigned char *) &__tramp[16] = 0x49; \ - *(unsigned char *) &__tramp[17] = 0xba; \ - *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \ - *(unsigned char *) &__tramp[26] = 0x41; \ - *(unsigned char *) &__tramp[27] = 0xff; \ - *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \ - } - -/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */ - -#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ -{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ - unsigned int __dis = __fun - (__ctx + 10); \ - *(unsigned char*) &__tramp[0] = 0xb8; \ - *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \ - *(unsigned char *) &__tramp[5] = 0xe9; \ - *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \ - } - -#define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \ -{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ - unsigned int __dis = __fun - (__ctx + 49); \ - unsigned short __size = (unsigned short)(SIZE); \ - *(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \ - *(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \ - *(unsigned int *) &__tramp[8] = 0x04890424; /* mov %ecx, 4(%esp) */ \ - *(unsigned char*) &__tramp[12] = 0x24; /* mov %eax, (%esp) */ \ - *(unsigned char*) &__tramp[13] = 0xb8; \ - *(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \ - *(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \ - *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \ - *(unsigned short*) &__tramp[26] = 0x0b74; /* jz 1f */ \ - *(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \ - *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \ - *(unsigned char*) &__tramp[36] = 0x48; /* dec %eax */ \ - *(unsigned short*) &__tramp[37] = 0xf575; /* jnz 2b ; 1f: */ \ - *(unsigned char*) &__tramp[39] = 0xb8; \ - *(unsigned int*) &__tramp[40] = __ctx; /* movl __ctx, %eax */ \ - *(unsigned char *) &__tramp[44] = 0xe8; \ - *(unsigned int*) &__tramp[45] = __dis; /* call __fun */ \ - *(unsigned char*) &__tramp[49] = 0xc2; /* ret */ \ - *(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \ - } - -#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \ -{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ - unsigned int __dis = __fun - (__ctx + 10); \ - unsigned short __size = (unsigned short)(SIZE); \ - *(unsigned char*) &__tramp[0] = 0xb8; \ - *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \ - *(unsigned char *) &__tramp[5] = 0xe8; \ - *(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \ - *(unsigned char *) &__tramp[10] = 0xc2; \ - *(unsigned short*) &__tramp[11] = __size; /* ret __size */ \ - } - -/* the cif must already be prep'ed */ - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) -{ -#ifdef X86_WIN64 -#define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE) -#define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0) - if (cif->abi == FFI_WIN64) - { - int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3); - FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0], - &ffi_closure_win64, - codeloc, mask); - /* make sure we can execute here */ - } -#else - if (cif->abi == FFI_SYSV) - { - FFI_INIT_TRAMPOLINE (&closure->tramp[0], - &ffi_closure_SYSV, - (void*)codeloc); - } -#ifdef X86_WIN32 - else if (cif->abi == FFI_THISCALL) - { - FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], - &ffi_closure_THISCALL, - (void*)codeloc, - cif->bytes); - } - else if (cif->abi == FFI_STDCALL) - { - FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0], - &ffi_closure_STDCALL, - (void*)codeloc, cif->bytes); - } - else if (cif->abi == FFI_MS_CDECL) - { - FFI_INIT_TRAMPOLINE (&closure->tramp[0], - &ffi_closure_SYSV, - (void*)codeloc); - } -#endif /* X86_WIN32 */ -#endif /* !X86_WIN64 */ - else - { - return FFI_BAD_ABI; - } - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} - -/* ------- Native raw API support -------------------------------- */ - -#if !FFI_NO_RAW_API - -ffi_status -ffi_prep_raw_closure_loc (ffi_raw_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,ffi_raw*,void*), - void *user_data, - void *codeloc) -{ - int i; - - if (cif->abi != FFI_SYSV) { -#ifdef X86_WIN32 - if (cif->abi != FFI_THISCALL) -#endif - return FFI_BAD_ABI; - } - - /* we currently don't support certain kinds of arguments for raw - closures. This should be implemented by a separate assembly - language routine, since it would require argument processing, - something we don't do now for performance. */ - - for (i = cif->nargs-1; i >= 0; i--) - { - FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT); - FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE); - } - -#ifdef X86_WIN32 - if (cif->abi == FFI_SYSV) - { -#endif - FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV, - codeloc); -#ifdef X86_WIN32 - } - else if (cif->abi == FFI_THISCALL) - { - FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL, - codeloc, cif->bytes); - } -#endif - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} - -static void -ffi_prep_args_raw(char *stack, extended_cif *ecif) -{ - memcpy (stack, ecif->avalue, ecif->cif->bytes); -} - -/* we borrow this routine from libffi (it must be changed, though, to - * actually call the function passed in the first argument. as of - * libffi-1.20, this is not the case.) - */ - -void -ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue) -{ - extended_cif ecif; - void **avalue = (void **)fake_avalue; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - if (rvalue == NULL - && (cif->flags == FFI_TYPE_STRUCT - || cif->flags == FFI_TYPE_MS_STRUCT)) - { - ecif.rvalue = alloca(cif->rtype->size); - } - else - ecif.rvalue = rvalue; - - - switch (cif->abi) - { -#ifdef X86_WIN32 - case FFI_SYSV: - case FFI_STDCALL: - case FFI_MS_CDECL: - ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; - case FFI_THISCALL: - case FFI_FASTCALL: - { - unsigned int abi = cif->abi; - unsigned int i, passed_regs = 0; - - if (cif->flags == FFI_TYPE_STRUCT) - ++passed_regs; - - for (i=0; i < cif->nargs && passed_regs < 2;i++) - { - size_t sz; - - if (cif->arg_types[i]->type == FFI_TYPE_FLOAT - || cif->arg_types[i]->type == FFI_TYPE_STRUCT) - continue; - sz = (cif->arg_types[i]->size + 3) & ~3; - if (sz == 0 || sz > 4) - continue; - ++passed_regs; - } - if (passed_regs < 2 && abi == FFI_FASTCALL) - cif->abi = abi = FFI_THISCALL; - if (passed_regs < 1 && abi == FFI_THISCALL) - cif->abi = abi = FFI_STDCALL; - ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - } - break; -#else - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; -#endif - default: - FFI_ASSERT(0); - break; - } -} - -#endif - -#endif /* !__x86_64__ || X86_WIN64 */ - diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c index feb5cbb..24431c1 100644 --- a/libffi/src/x86/ffi.c +++ b/libffi/src/x86/ffi.c @@ -1,5 +1,6 @@ /* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc. + ffi.c - Copyright (c) 2017 Anthony Green + Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc. Copyright (c) 2002 Ranjit Mathew Copyright (c) 2002 Bo Thorsen Copyright (c) 2002 Roger Sayle @@ -28,10 +29,12 @@ DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ -#ifndef __x86_64__ +#if defined(__i386__) || defined(_M_IX86) #include <ffi.h> #include <ffi_common.h> +#include <stdint.h> #include <stdlib.h> +#include <tramp.h> #include "internal.h" /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE; @@ -49,6 +52,13 @@ # define __declspec(x) __attribute__((x)) #endif +#if defined(_MSC_VER) && defined(_M_IX86) +/* Stack is not 16-byte aligned on Windows. */ +#define STACK_ALIGN(bytes) (bytes) +#else +#define STACK_ALIGN(bytes) FFI_ALIGN (bytes, 16) +#endif + /* Perform machine dependent cif processing. */ ffi_status FFI_HIDDEN ffi_prep_cif_machdep(ffi_cif *cif) @@ -134,7 +144,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) break; } /* Allocate space for return value pointer. */ - bytes += ALIGN (sizeof(void*), FFI_SIZEOF_ARG); + bytes += FFI_ALIGN (sizeof(void*), FFI_SIZEOF_ARG); } break; case FFI_TYPE_COMPLEX: @@ -172,10 +182,10 @@ ffi_prep_cif_machdep(ffi_cif *cif) { ffi_type *t = cif->arg_types[i]; - bytes = ALIGN (bytes, t->alignment); - bytes += ALIGN (t->size, FFI_SIZEOF_ARG); + bytes = FFI_ALIGN (bytes, t->alignment); + bytes += FFI_ALIGN (t->size, FFI_SIZEOF_ARG); } - cif->bytes = ALIGN (bytes, 16); + cif->bytes = bytes; return FFI_OK; } @@ -234,12 +244,25 @@ static const struct abi_params abi_params[FFI_LAST_ABI] = { [FFI_MS_CDECL] = { 1, R_ECX, 0 } }; -extern void ffi_call_i386(struct call_frame *, char *) -#if HAVE_FASTCALL - __declspec(fastcall) +#ifdef HAVE_FASTCALL + #ifdef _MSC_VER + #define FFI_DECLARE_FASTCALL __fastcall + #else + #define FFI_DECLARE_FASTCALL __declspec(fastcall) + #endif +#else + #define FFI_DECLARE_FASTCALL #endif - FFI_HIDDEN; +extern void FFI_DECLARE_FASTCALL ffi_call_i386(struct call_frame *, char *) FFI_HIDDEN; + +/* We perform some black magic here to use some of the parent's stack frame in + * ffi_call_i386() that breaks with the MSVC compiler with the /RTCs or /GZ + * flags. Disable the 'Stack frame run time error checking' for this function + * so we don't hit weird exceptions in debug builds. */ +#if defined(_MSC_VER) +#pragma runtime_checks("s", off) +#endif static void ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, void *closure) @@ -277,7 +300,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, } } - bytes = cif->bytes; + bytes = STACK_ALIGN (cif->bytes); stack = alloca(bytes + sizeof(*frame) + rsize); argp = (dir < 0 ? stack + bytes : stack); frame = (struct call_frame *)(stack + bytes); @@ -334,9 +357,18 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, } else { - size_t za = ALIGN (z, FFI_SIZEOF_ARG); + size_t za = FFI_ALIGN (z, FFI_SIZEOF_ARG); size_t align = FFI_SIZEOF_ARG; + /* Issue 434: For thiscall and fastcall, if the paramter passed + as 64-bit integer or struct, all following integer parameters + will be passed on stack. */ + if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL) + && (t == FFI_TYPE_SINT64 + || t == FFI_TYPE_UINT64 + || t == FFI_TYPE_STRUCT)) + narg_reg = 2; + /* Alignment rules for arguments are quite complex. Vectors and structures with 16 byte alignment get it. Note that long double on Darwin does have 16 byte alignment, and does not get this @@ -356,7 +388,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, } else { - argp = (char *)ALIGN (argp, align); + argp = (char *)FFI_ALIGN (argp, align); memcpy (argp, valp, z); argp += za; } @@ -366,6 +398,9 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_call_i386 (frame, stack); } +#if defined(_MSC_VER) +#pragma runtime_checks("s", restore) +#endif void ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) @@ -373,18 +408,25 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) ffi_call_int (cif, fn, rvalue, avalue, NULL); } +#ifdef FFI_GO_CLOSURES void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, void *closure) { ffi_call_int (cif, fn, rvalue, avalue, closure); } +#endif /** private members **/ void FFI_HIDDEN ffi_closure_i386(void); void FFI_HIDDEN ffi_closure_STDCALL(void); void FFI_HIDDEN ffi_closure_REGISTER(void); +#if defined(FFI_EXEC_STATIC_TRAMP) +void FFI_HIDDEN ffi_closure_i386_alt(void); +void FFI_HIDDEN ffi_closure_STDCALL_alt(void); +void FFI_HIDDEN ffi_closure_REGISTER_alt(void); +#endif struct closure_frame { @@ -395,10 +437,7 @@ struct closure_frame void *user_data; /* 36 */ }; -int FFI_HIDDEN -#if HAVE_FASTCALL -__declspec(fastcall) -#endif +int FFI_HIDDEN FFI_DECLARE_FASTCALL ffi_closure_inner (struct closure_frame *frame, char *stack) { ffi_cif *cif = frame->cif; @@ -415,7 +454,7 @@ ffi_closure_inner (struct closure_frame *frame, char *stack) rvalue = frame->rettemp; pabi = &abi_params[cabi]; dir = pabi->dir; - argp = (dir < 0 ? stack + cif->bytes : stack); + argp = (dir < 0 ? stack + STACK_ALIGN (cif->bytes) : stack); switch (flags) { @@ -463,13 +502,22 @@ ffi_closure_inner (struct closure_frame *frame, char *stack) } else { - size_t za = ALIGN (z, FFI_SIZEOF_ARG); + size_t za = FFI_ALIGN (z, FFI_SIZEOF_ARG); size_t align = FFI_SIZEOF_ARG; /* See the comment in ffi_call_int. */ if (t == FFI_TYPE_STRUCT && ty->alignment >= 16) align = 16; + /* Issue 434: For thiscall and fastcall, if the paramter passed + as 64-bit integer or struct, all following integer parameters + will be passed on stack. */ + if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL) + && (t == FFI_TYPE_SINT64 + || t == FFI_TYPE_UINT64 + || t == FFI_TYPE_STRUCT)) + narg_reg = 2; + if (dir < 0) { /* ??? These reverse argument ABIs are probably too old @@ -479,7 +527,7 @@ ffi_closure_inner (struct closure_frame *frame, char *stack) } else { - argp = (char *)ALIGN (argp, align); + argp = (char *)FFI_ALIGN (argp, align); valp = argp; argp += za; } @@ -490,10 +538,17 @@ ffi_closure_inner (struct closure_frame *frame, char *stack) frame->fun (cif, rvalue, avalue, frame->user_data); - if (cabi == FFI_STDCALL) - return flags + (cif->bytes << X86_RET_POP_SHIFT); - else - return flags; + switch (cabi) + { + case FFI_STDCALL: + return flags | (cif->bytes << X86_RET_POP_SHIFT); + case FFI_THISCALL: + case FFI_FASTCALL: + return flags | ((cif->bytes - (narg_reg * FFI_SIZEOF_ARG)) + << X86_RET_POP_SHIFT); + default: + return flags; + } } ffi_status @@ -510,30 +565,51 @@ ffi_prep_closure_loc (ffi_closure* closure, switch (cif->abi) { case FFI_SYSV: - case FFI_THISCALL: - case FFI_FASTCALL: case FFI_MS_CDECL: dest = ffi_closure_i386; break; case FFI_STDCALL: + case FFI_THISCALL: + case FFI_FASTCALL: case FFI_PASCAL: dest = ffi_closure_STDCALL; break; case FFI_REGISTER: dest = ffi_closure_REGISTER; op = 0x68; /* pushl imm */ + break; default: return FFI_BAD_ABI; } +#if defined(FFI_EXEC_STATIC_TRAMP) + if (ffi_tramp_is_present(closure)) + { + /* Initialize the static trampoline's parameters. */ + if (dest == ffi_closure_i386) + dest = ffi_closure_i386_alt; + else if (dest == ffi_closure_STDCALL) + dest = ffi_closure_STDCALL_alt; + else + dest = ffi_closure_REGISTER_alt; + ffi_tramp_set_parms (closure->ftramp, dest, closure); + goto out; + } +#endif + + /* Initialize the dynamic trampoline. */ + /* endbr32. */ + *(UINT32 *) tramp = 0xfb1e0ff3; + /* movl or pushl immediate. */ - tramp[0] = op; - *(void **)(tramp + 1) = codeloc; + tramp[4] = op; + *(void **)(tramp + 5) = codeloc; /* jmp dest */ - tramp[5] = 0xe9; - *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10); + tramp[9] = 0xe9; + *(unsigned *)(tramp + 10) = (unsigned)dest - ((unsigned)codeloc + 14); +out: closure->cif = cif; closure->fun = fun; closure->user_data = user_data; @@ -541,6 +617,8 @@ ffi_prep_closure_loc (ffi_closure* closure, return FFI_OK; } +#ifdef FFI_GO_CLOSURES + void FFI_HIDDEN ffi_go_closure_EAX(void); void FFI_HIDDEN ffi_go_closure_ECX(void); void FFI_HIDDEN ffi_go_closure_STDCALL(void); @@ -577,6 +655,8 @@ ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, return FFI_OK; } +#endif /* FFI_GO_CLOSURES */ + /* ------- Native raw API support -------------------------------- */ #if !FFI_NO_RAW_API @@ -669,8 +749,9 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue) } } - bytes = cif->bytes; - argp = stack = alloca(bytes + sizeof(*frame) + rsize); + bytes = STACK_ALIGN (cif->bytes); + argp = stack = + (void *)((uintptr_t)alloca(bytes + sizeof(*frame) + rsize + 15) & ~16); frame = (struct call_frame *)(stack + bytes); if (rsize) rvalue = frame + 1; @@ -714,7 +795,7 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue) else { memcpy (argp, avalue, z); - z = ALIGN (z, FFI_SIZEOF_ARG); + z = FFI_ALIGN (z, FFI_SIZEOF_ARG); argp += z; } avalue += z; @@ -726,4 +807,17 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue) ffi_call_i386 (frame, stack); } #endif /* !FFI_NO_RAW_API */ -#endif /* !__x86_64__ */ + +#if defined(FFI_EXEC_STATIC_TRAMP) +void * +ffi_tramp_arch (size_t *tramp_size, size_t *map_size) +{ + extern void *trampoline_code_table; + + *map_size = X86_TRAMP_MAP_SIZE; + *tramp_size = X86_TRAMP_SIZE; + return &trampoline_code_table; +} +#endif + +#endif /* __i386__ */ diff --git a/libffi/src/x86/ffi64.c b/libffi/src/x86/ffi64.c index 243cbc7..438b374 100644 --- a/libffi/src/x86/ffi64.c +++ b/libffi/src/x86/ffi64.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- - ffi64.c - Copyright (c) 2013 The Written Word, Inc. - Copyright (c) 2011 Anthony Green + ffi64.c - Copyright (c) 2011, 2018 Anthony Green + Copyright (c) 2013 The Written Word, Inc. Copyright (c) 2008, 2010 Red Hat, Inc. Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de> @@ -33,6 +33,7 @@ #include <stdlib.h> #include <stdarg.h> #include <stdint.h> +#include <tramp.h> #include "internal64.h" #ifdef __x86_64__ @@ -217,10 +218,10 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[], case FFI_TYPE_STRUCT: { const size_t UNITS_PER_WORD = 8; - size_t words = (type->size + byte_offset + UNITS_PER_WORD - 1) - / UNITS_PER_WORD; + size_t words = (type->size + byte_offset + UNITS_PER_WORD - 1) + / UNITS_PER_WORD; ffi_type **ptr; - int i; + unsigned int i; enum x86_64_reg_class subclasses[MAX_CLASSES]; /* If the struct is larger than 32 bytes, pass it on the stack. */ @@ -244,14 +245,15 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[], { size_t num, pos; - byte_offset = ALIGN (byte_offset, (*ptr)->alignment); + byte_offset = FFI_ALIGN (byte_offset, (*ptr)->alignment); num = classify_argument (*ptr, subclasses, byte_offset % 8); if (num == 0) return 0; - pos = byte_offset / 8; - for (i = 0; i < num && (i + pos) < words; i++) + pos = byte_offset / 8; + for (i = 0; i < num && (i + pos) < words; i++) { + size_t pos = byte_offset / 8; classes[i + pos] = merge_classes (subclasses[i], classes[i + pos]); } @@ -283,7 +285,7 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[], /* The X86_64_SSEUP_CLASS should be always preceded by X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */ - if (classes[i] == X86_64_SSEUP_CLASS + if (i > 1 && classes[i] == X86_64_SSEUP_CLASS && classes[i - 1] != X86_64_SSE_CLASS && classes[i - 1] != X86_64_SSEUP_CLASS) { @@ -294,7 +296,7 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[], /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS, everything should be passed in memory. */ - if (classes[i] == X86_64_X87UP_CLASS + if (i > 1 && classes[i] == X86_64_X87UP_CLASS && (classes[i - 1] != X86_64_X87_CLASS)) { /* The first one should never be X86_64_X87UP_CLASS. */ @@ -351,7 +353,8 @@ examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES], _Bool in_return, int *pngpr, int *pnsse) { size_t n; - int i, ngpr, nsse; + unsigned int i; + int ngpr, nsse; n = classify_argument (type, classes, 0); if (n == 0) @@ -389,14 +392,24 @@ examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES], /* Perform machine dependent cif processing. */ -ffi_status +#ifndef __ILP32__ +extern ffi_status +ffi_prep_cif_machdep_efi64(ffi_cif *cif); +#endif + +ffi_status FFI_HIDDEN ffi_prep_cif_machdep (ffi_cif *cif) { - int gprcount, ssecount, i, avn, ngpr, nsse, flags; + int gprcount, ssecount, i, avn, ngpr, nsse; + unsigned flags; enum x86_64_reg_class classes[MAX_CLASSES]; size_t bytes, n, rtype_size; ffi_type *rtype; +#ifndef __ILP32__ + if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64) + return ffi_prep_cif_machdep_efi64(cif); +#endif if (cif->abi != FFI_UNIX64) return FFI_BAD_ABI; @@ -441,9 +454,11 @@ ffi_prep_cif_machdep (ffi_cif *cif) case FFI_TYPE_DOUBLE: flags = UNIX64_RET_XMM64; break; +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: flags = UNIX64_RET_X87; break; +#endif case FFI_TYPE_STRUCT: n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); if (n == 0) @@ -489,7 +504,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) case FFI_TYPE_SINT32: case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: - flags = UNIX64_RET_ST_RAX_RDX | (rtype_size << UNIX64_SIZE_SHIFT); + flags = UNIX64_RET_ST_RAX_RDX | ((unsigned) rtype_size << UNIX64_SIZE_SHIFT); break; case FFI_TYPE_FLOAT: flags = UNIX64_RET_XMM64; @@ -524,7 +539,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) if (align < 8) align = 8; - bytes = ALIGN (bytes, align); + bytes = FFI_ALIGN (bytes, align); bytes += cif->arg_types[i]->size; } else @@ -537,7 +552,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) flags |= UNIX64_FLAG_XMM_ARGS; cif->flags = flags; - cif->bytes = ALIGN (bytes, 8); + cif->bytes = (unsigned) FFI_ALIGN (bytes, 8); return FFI_OK; } @@ -599,7 +614,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, align = 8; /* Pass this argument in memory. */ - argp = (void *) ALIGN (argp, align); + argp = (void *) FFI_ALIGN (argp, align); memcpy (argp, avalue[i], size); argp += size; } @@ -607,7 +622,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, { /* The argument is passed entirely in registers. */ char *a = (char *) avalue[i]; - int j; + unsigned int j; for (j = 0; j < n; j++, a += 8, size -= 8) { @@ -641,10 +656,10 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, break; case X86_64_SSE_CLASS: case X86_64_SSEDF_CLASS: - reg_args->sse[ssecount++].i64 = *(UINT64 *) a; + memcpy (®_args->sse[ssecount++].i64, a, sizeof(UINT64)); break; case X86_64_SSESF_CLASS: - reg_args->sse[ssecount++].i32 = *(UINT32 *) a; + memcpy (®_args->sse[ssecount++].i32, a, sizeof(UINT32)); break; default: abort(); @@ -658,21 +673,63 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, flags, rvalue, fn); } +#ifndef __ILP32__ +extern void +ffi_call_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue); +#endif + void ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { +#ifndef __ILP32__ + if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64) + { + ffi_call_efi64(cif, fn, rvalue, avalue); + return; + } +#endif ffi_call_int (cif, fn, rvalue, avalue, NULL); } +#ifdef FFI_GO_CLOSURES + +#ifndef __ILP32__ +extern void +ffi_call_go_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure); +#endif + void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, void *closure) { +#ifndef __ILP32__ + if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64) + { + ffi_call_go_efi64(cif, fn, rvalue, avalue, closure); + return; + } +#endif ffi_call_int (cif, fn, rvalue, avalue, closure); } +#endif /* FFI_GO_CLOSURES */ + extern void ffi_closure_unix64(void) FFI_HIDDEN; extern void ffi_closure_unix64_sse(void) FFI_HIDDEN; +#if defined(FFI_EXEC_STATIC_TRAMP) +extern void ffi_closure_unix64_alt(void) FFI_HIDDEN; +extern void ffi_closure_unix64_sse_alt(void) FFI_HIDDEN; +#endif + +#ifndef __ILP32__ +extern ffi_status +ffi_prep_closure_loc_efi64(ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, + void *codeloc); +#endif ffi_status ffi_prep_closure_loc (ffi_closure* closure, @@ -681,17 +738,23 @@ ffi_prep_closure_loc (ffi_closure* closure, void *user_data, void *codeloc) { - static const unsigned char trampoline[16] = { - /* leaq -0x7(%rip),%r10 # 0x0 */ - 0x4c, 0x8d, 0x15, 0xf9, 0xff, 0xff, 0xff, - /* jmpq *0x3(%rip) # 0x10 */ - 0xff, 0x25, 0x03, 0x00, 0x00, 0x00, - /* nopl (%rax) */ - 0x0f, 0x1f, 0x00 + static const unsigned char trampoline[24] = { + /* endbr64 */ + 0xf3, 0x0f, 0x1e, 0xfa, + /* leaq -0xb(%rip),%r10 # 0x0 */ + 0x4c, 0x8d, 0x15, 0xf5, 0xff, 0xff, 0xff, + /* jmpq *0x7(%rip) # 0x18 */ + 0xff, 0x25, 0x07, 0x00, 0x00, 0x00, + /* nopl 0(%rax) */ + 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 }; void (*dest)(void); char *tramp = closure->tramp; +#ifndef __ILP32__ + if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64) + return ffi_prep_closure_loc_efi64(closure, cif, fun, user_data, codeloc); +#endif if (cif->abi != FFI_UNIX64) return FFI_BAD_ABI; @@ -700,9 +763,24 @@ ffi_prep_closure_loc (ffi_closure* closure, else dest = ffi_closure_unix64; +#if defined(FFI_EXEC_STATIC_TRAMP) + if (ffi_tramp_is_present(closure)) + { + /* Initialize the static trampoline's parameters. */ + if (dest == ffi_closure_unix64_sse) + dest = ffi_closure_unix64_sse_alt; + else + dest = ffi_closure_unix64_alt; + ffi_tramp_set_parms (closure->ftramp, dest, closure); + goto out; + } +#endif + + /* Initialize the dynamic trampoline. */ memcpy (tramp, trampoline, sizeof(trampoline)); - *(UINT64 *)(tramp + 16) = (uintptr_t)dest; + *(UINT64 *)(tramp + sizeof (trampoline)) = (uintptr_t)dest; +out: closure->cif = cif; closure->fun = fun; closure->user_data = user_data; @@ -757,7 +835,7 @@ ffi_closure_unix64_inner(ffi_cif *cif, align = 8; /* Pass this argument in memory. */ - argp = (void *) ALIGN (argp, align); + argp = (void *) FFI_ALIGN (argp, align); avalue[i] = argp; argp += arg_types[i]->size; } @@ -783,7 +861,7 @@ ffi_closure_unix64_inner(ffi_cif *cif, else { char *a = alloca (16); - int j; + unsigned int j; avalue[i] = a; for (j = 0; j < n; j++, a += 8) @@ -803,13 +881,25 @@ ffi_closure_unix64_inner(ffi_cif *cif, return flags; } +#ifdef FFI_GO_CLOSURES + extern void ffi_go_closure_unix64(void) FFI_HIDDEN; extern void ffi_go_closure_unix64_sse(void) FFI_HIDDEN; +#ifndef __ILP32__ +extern ffi_status +ffi_prep_go_closure_efi64(ffi_go_closure* closure, ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*)); +#endif + ffi_status ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*, void*, void**, void*)) { +#ifndef __ILP32__ + if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64) + return ffi_prep_go_closure_efi64(closure, cif, fun); +#endif if (cif->abi != FFI_UNIX64) return FFI_BAD_ABI; @@ -822,4 +912,18 @@ ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, return FFI_OK; } +#endif /* FFI_GO_CLOSURES */ + +#if defined(FFI_EXEC_STATIC_TRAMP) +void * +ffi_tramp_arch (size_t *tramp_size, size_t *map_size) +{ + extern void *trampoline_code_table; + + *map_size = UNIX64_TRAMP_MAP_SIZE; + *tramp_size = UNIX64_TRAMP_SIZE; + return &trampoline_code_table; +} +#endif + #endif /* __x86_64__ */ diff --git a/libffi/src/x86/ffitarget.h b/libffi/src/x86/ffitarget.h index a576961..f454341 100644 --- a/libffi/src/x86/ffitarget.h +++ b/libffi/src/x86/ffitarget.h @@ -1,5 +1,5 @@ /* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012, 2014 Anthony Green + ffitarget.h - Copyright (c) 2012, 2014, 2018 Anthony Green Copyright (c) 1996-2003, 2010 Red Hat, Inc. Copyright (C) 2008 Free Software Foundation, Inc. @@ -50,8 +50,7 @@ #endif #define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION - -#if !defined(_MSC_VER) && !defined(X86_DARWIN) && !defined(X86_64_DARWIN) +#ifndef _MSC_VER #define FFI_TARGET_HAS_COMPLEX_TYPE #endif @@ -81,13 +80,21 @@ typedef signed long ffi_sarg; typedef enum ffi_abi { #if defined(X86_WIN64) FFI_FIRST_ABI = 0, - FFI_WIN64, + FFI_WIN64, /* sizeof(long double) == 8 - microsoft compilers */ + FFI_GNUW64, /* sizeof(long double) == 16 - GNU compilers */ FFI_LAST_ABI, +#ifdef __GNUC__ + FFI_DEFAULT_ABI = FFI_GNUW64 +#else FFI_DEFAULT_ABI = FFI_WIN64 +#endif -#elif defined(X86_64) || defined(X86_64_DARWIN) +#elif defined(X86_64) || (defined (__x86_64__) && defined (X86_DARWIN)) FFI_FIRST_ABI = 1, FFI_UNIX64, + FFI_WIN64, + FFI_EFI64 = FFI_WIN64, + FFI_GNUW64, FFI_LAST_ABI, FFI_DEFAULT_ABI = FFI_UNIX64 @@ -120,23 +127,36 @@ typedef enum ffi_abi { /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 - -#if !defined(X86_DARWIN) && !defined(X86_64_DARWIN) #define FFI_GO_CLOSURES 1 -#endif #define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1) #define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2) #define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3) #define FFI_TYPE_MS_STRUCT (FFI_TYPE_LAST + 4) -#if defined (X86_64) || defined(X86_WIN64) || defined(X86_64_DARWIN) -# define FFI_TRAMPOLINE_SIZE 24 +#if defined (X86_64) || defined(X86_WIN64) \ + || (defined (__x86_64__) && defined (X86_DARWIN)) +/* 4 bytes of ENDBR64 + 7 bytes of LEA + 6 bytes of JMP + 7 bytes of NOP + + 8 bytes of pointer. */ +# define FFI_TRAMPOLINE_SIZE 32 # define FFI_NATIVE_RAW_API 0 #else -# define FFI_TRAMPOLINE_SIZE 12 +/* 4 bytes of ENDBR32 + 5 bytes of MOV + 5 bytes of JMP + 2 unused + bytes. */ +# define FFI_TRAMPOLINE_SIZE 16 # define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ #endif +#if !defined(GENERATE_LIBFFI_MAP) && defined(__CET__) +# include <cet.h> +# if (__CET__ & 1) != 0 +# define ENDBR_PRESENT +# endif +# define _CET_NOTRACK notrack +#else +# define _CET_ENDBR +# define _CET_NOTRACK +#endif + #endif diff --git a/libffi/src/x86/ffiw64.c b/libffi/src/x86/ffiw64.c index 8a33a6c..6870d07 100644 --- a/libffi/src/x86/ffiw64.c +++ b/libffi/src/x86/ffiw64.c @@ -1,5 +1,6 @@ /* ----------------------------------------------------------------------- - ffiw64.c - Copyright (c) 2014 Red Hat, Inc. + ffiw64.c - Copyright (c) 2018 Anthony Green + Copyright (c) 2014 Red Hat, Inc. x86 win64 Foreign Function Interface @@ -24,12 +25,18 @@ DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ +#if defined(__x86_64__) || defined(_M_AMD64) #include <ffi.h> #include <ffi_common.h> #include <stdlib.h> #include <stdint.h> +#include <tramp.h> #ifdef X86_WIN64 +#define EFI64(name) name +#else +#define EFI64(name) FFI_HIDDEN name##_efi64 +#endif struct win64_call_frame { @@ -43,13 +50,19 @@ struct win64_call_frame extern void ffi_call_win64 (void *stack, struct win64_call_frame *, void *closure) FFI_HIDDEN; -ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) +ffi_status FFI_HIDDEN +EFI64(ffi_prep_cif_machdep)(ffi_cif *cif) { int flags, n; - if (cif->abi != FFI_WIN64) - return FFI_BAD_ABI; + switch (cif->abi) + { + case FFI_WIN64: + case FFI_GNUW64: + break; + default: + return FFI_BAD_ABI; + } flags = cif->rtype->type; switch (flags) @@ -57,7 +70,9 @@ ffi_prep_cif_machdep (ffi_cif *cif) default: break; case FFI_TYPE_LONGDOUBLE: - flags = FFI_TYPE_STRUCT; + /* GCC returns long double values by reference, like a struct */ + if (cif->abi == FFI_GNUW64) + flags = FFI_TYPE_STRUCT; break; case FFI_TYPE_COMPLEX: flags = FFI_TYPE_STRUCT; @@ -93,6 +108,13 @@ ffi_prep_cif_machdep (ffi_cif *cif) return FFI_OK; } +/* We perform some black magic here to use some of the parent's stack frame in + * ffi_call_win64() that breaks with the MSVC compiler with the /RTCs or /GZ + * flags. Disable the 'Stack frame run time error checking' for this function + * so we don't hit weird exceptions in debug builds. */ +#if defined(_MSC_VER) +#pragma runtime_checks("s", off) +#endif static void ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, void *closure) @@ -102,7 +124,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, size_t rsize; struct win64_call_frame *frame; - FFI_ASSERT(cif->abi == FFI_WIN64); + FFI_ASSERT(cif->abi == FFI_GNUW64 || cif->abi == FFI_WIN64); flags = cif->flags; rsize = 0; @@ -157,15 +179,18 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_call_win64 (stack, frame, closure); } +#if defined(_MSC_VER) +#pragma runtime_checks("s", restore) +#endif void -ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +EFI64(ffi_call)(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { ffi_call_int (cif, fn, rvalue, avalue, NULL); } void -ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, +EFI64(ffi_call_go)(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, void *closure) { ffi_call_int (cif, fn, rvalue, avalue, closure); @@ -173,31 +198,56 @@ ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, extern void ffi_closure_win64(void) FFI_HIDDEN; +#if defined(FFI_EXEC_STATIC_TRAMP) +extern void ffi_closure_win64_alt(void) FFI_HIDDEN; +#endif + +#ifdef FFI_GO_CLOSURES extern void ffi_go_closure_win64(void) FFI_HIDDEN; +#endif ffi_status -ffi_prep_closure_loc (ffi_closure* closure, +EFI64(ffi_prep_closure_loc)(ffi_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*, void*, void**, void*), void *user_data, void *codeloc) { - static const unsigned char trampoline[16] = { - /* leaq -0x7(%rip),%r10 # 0x0 */ - 0x4c, 0x8d, 0x15, 0xf9, 0xff, 0xff, 0xff, - /* jmpq *0x3(%rip) # 0x10 */ - 0xff, 0x25, 0x03, 0x00, 0x00, 0x00, - /* nopl (%rax) */ - 0x0f, 0x1f, 0x00 + static const unsigned char trampoline[FFI_TRAMPOLINE_SIZE - 8] = { + /* endbr64 */ + 0xf3, 0x0f, 0x1e, 0xfa, + /* leaq -0xb(%rip),%r10 # 0x0 */ + 0x4c, 0x8d, 0x15, 0xf5, 0xff, 0xff, 0xff, + /* jmpq *0x7(%rip) # 0x18 */ + 0xff, 0x25, 0x07, 0x00, 0x00, 0x00, + /* nopl 0(%rax) */ + 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 }; - unsigned char *tramp = closure->tramp; + char *tramp = closure->tramp; + + switch (cif->abi) + { + case FFI_WIN64: + case FFI_GNUW64: + break; + default: + return FFI_BAD_ABI; + } - if (cif->abi != FFI_WIN64) - return FFI_BAD_ABI; +#if defined(FFI_EXEC_STATIC_TRAMP) + if (ffi_tramp_is_present(closure)) + { + /* Initialize the static trampoline's parameters. */ + ffi_tramp_set_parms (closure->ftramp, ffi_closure_win64_alt, closure); + goto out; + } +#endif + /* Initialize the dynamic trampoline. */ memcpy (tramp, trampoline, sizeof(trampoline)); - *(UINT64 *)(tramp + 16) = (uintptr_t)ffi_closure_win64; + *(UINT64 *)(tramp + sizeof (trampoline)) = (uintptr_t)ffi_closure_win64; +out: closure->cif = cif; closure->fun = fun; closure->user_data = user_data; @@ -205,12 +255,19 @@ ffi_prep_closure_loc (ffi_closure* closure, return FFI_OK; } +#ifdef FFI_GO_CLOSURES ffi_status -ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, +EFI64(ffi_prep_go_closure)(ffi_go_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*, void*, void**, void*)) { - if (cif->abi != FFI_WIN64) - return FFI_BAD_ABI; + switch (cif->abi) + { + case FFI_WIN64: + case FFI_GNUW64: + break; + default: + return FFI_BAD_ABI; + } closure->tramp = ffi_go_closure_win64; closure->cif = cif; @@ -218,6 +275,7 @@ ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, return FFI_OK; } +#endif struct win64_closure_frame { @@ -227,7 +285,11 @@ struct win64_closure_frame UINT64 args[]; }; -int FFI_HIDDEN +/* Force the inner function to use the MS ABI. When compiling on win64 + this is a nop. When compiling on unix, this simplifies the assembly, + and places the burden of saving the extra call-saved registers on + the compiler. */ +int FFI_HIDDEN __attribute__((ms_abi)) ffi_closure_win64_inner(ffi_cif *cif, void (*fun)(ffi_cif*, void*, void**, void*), void *user_data, @@ -278,4 +340,4 @@ ffi_closure_win64_inner(ffi_cif *cif, return flags; } -#endif /* X86_WIN64 */ +#endif /* __x86_64__ */ diff --git a/libffi/src/x86/internal.h b/libffi/src/x86/internal.h index 09771ba..23be7a2 100644 --- a/libffi/src/x86/internal.h +++ b/libffi/src/x86/internal.h @@ -27,3 +27,17 @@ #else # define HAVE_FASTCALL 1 #endif + +#if defined(FFI_EXEC_STATIC_TRAMP) +/* + * For the trampoline code table mapping, a mapping size of 4K (base page size) + * is chosen. + */ +#define X86_TRAMP_MAP_SHIFT 12 +#define X86_TRAMP_MAP_SIZE (1 << X86_TRAMP_MAP_SHIFT) +#ifdef ENDBR_PRESENT +#define X86_TRAMP_SIZE 44 +#else +#define X86_TRAMP_SIZE 40 +#endif +#endif diff --git a/libffi/src/x86/internal64.h b/libffi/src/x86/internal64.h index 512e955..282b408 100644 --- a/libffi/src/x86/internal64.h +++ b/libffi/src/x86/internal64.h @@ -20,3 +20,17 @@ #define UNIX64_FLAG_RET_IN_MEM (1 << 10) #define UNIX64_FLAG_XMM_ARGS (1 << 11) #define UNIX64_SIZE_SHIFT 12 + +#if defined(FFI_EXEC_STATIC_TRAMP) +/* + * For the trampoline code table mapping, a mapping size of 4K (base page size) + * is chosen. + */ +#define UNIX64_TRAMP_MAP_SHIFT 12 +#define UNIX64_TRAMP_MAP_SIZE (1 << UNIX64_TRAMP_MAP_SHIFT) +#ifdef ENDBR_PRESENT +#define UNIX64_TRAMP_SIZE 40 +#else +#define UNIX64_TRAMP_SIZE 32 +#endif +#endif diff --git a/libffi/src/x86/sysv.S b/libffi/src/x86/sysv.S index 78f245b..7110f02 100644 --- a/libffi/src/x86/sysv.S +++ b/libffi/src/x86/sysv.S @@ -1,6 +1,7 @@ /* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2013 The Written Word, Inc. - - Copyright (c) 1996,1998,2001-2003,2005,2008,2010 Red Hat, Inc. + sysv.S - Copyright (c) 2017 Anthony Green + - Copyright (c) 2013 The Written Word, Inc. + - Copyright (c) 1996,1998,2001-2003,2005,2008,2010 Red Hat, Inc. X86 Foreign Function Interface @@ -25,7 +26,8 @@ DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ -#ifndef __x86_64__ +#ifdef __i386__ +#ifndef _MSC_VER #define LIBFFI_ASM #include <fficonfig.h> @@ -54,8 +56,8 @@ /* Handle win32 fastcall name mangling. */ #ifdef X86_WIN32 -# define ffi_call_i386 @ffi_call_i386@8 -# define ffi_closure_inner @ffi_closure_inner@8 +# define ffi_call_i386 "@ffi_call_i386@8" +# define ffi_closure_inner "@ffi_closure_inner@8" #else # define ffi_call_i386 C(ffi_call_i386) # define ffi_closure_inner C(ffi_closure_inner) @@ -90,6 +92,7 @@ ffi_call_i386: L(UW0): # cfi_startproc + _CET_ENDBR #if !HAVE_FASTCALL movl 4(%esp), %ecx movl 8(%esp), %edx @@ -131,7 +134,7 @@ L(pc1): leal L(store_table)(,%ecx, 8), %ebx #endif movl 16(%ebp), %ecx /* load result address */ - jmp *%ebx + _CET_NOTRACK jmp *%ebx .balign 8 L(store_table): @@ -254,7 +257,7 @@ ENDF(ffi_call_i386) andl $X86_RET_TYPE_MASK, %eax; \ leal L(C1(load_table,N))(, %eax, 8), %edx; \ movl closure_CF(%esp), %eax; /* optimiztic load */ \ - jmp *%edx + _CET_NOTRACK jmp *%edx #ifdef __PIC__ # if defined X86_DARWIN || defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE @@ -265,14 +268,14 @@ ENDF(ffi_call_i386) L(C1(pc,N)): \ leal L(C1(load_table,N))-L(C1(pc,N))(%edx, %eax, 8), %edx; \ movl closure_CF(%esp), %eax; /* optimiztic load */ \ - jmp *%edx + _CET_NOTRACK jmp *%edx # else # define FFI_CLOSURE_CALL_INNER_SAVE_EBX # undef FFI_CLOSURE_CALL_INNER # define FFI_CLOSURE_CALL_INNER(UWN) \ movl %ebx, 40(%esp); /* save ebx */ \ L(C1(UW,UWN)): \ - # cfi_rel_offset(%ebx, 40); \ + /* cfi_rel_offset(%ebx, 40); */ \ call C(__x86.get_pc_thunk.bx); /* load got register */ \ addl $C(_GLOBAL_OFFSET_TABLE_), %ebx; \ call ffi_closure_inner@PLT @@ -282,9 +285,9 @@ L(C1(UW,UWN)): \ leal L(C1(load_table,N))@GOTOFF(%ebx, %eax, 8), %edx; \ movl 40(%esp), %ebx; /* restore ebx */ \ L(C1(UW,UWN)): \ - # cfi_restore(%ebx); \ + /* cfi_restore(%ebx); */ \ movl closure_CF(%esp), %eax; /* optimiztic load */ \ - jmp *%edx + _CET_NOTRACK jmp *%edx # endif /* DARWIN || HIDDEN */ #endif /* __PIC__ */ @@ -294,6 +297,7 @@ L(C1(UW,UWN)): \ C(ffi_go_closure_EAX): L(UW6): # cfi_startproc + _CET_ENDBR subl $closure_FS, %esp L(UW7): # cfi_def_cfa_offset(closure_FS + 4) @@ -314,6 +318,7 @@ ENDF(C(ffi_go_closure_EAX)) C(ffi_go_closure_ECX): L(UW9): # cfi_startproc + _CET_ENDBR subl $closure_FS, %esp L(UW10): # cfi_def_cfa_offset(closure_FS + 4) @@ -338,6 +343,7 @@ ENDF(C(ffi_go_closure_ECX)) C(ffi_closure_i386): L(UW12): # cfi_startproc + _CET_ENDBR subl $closure_FS, %esp L(UW13): # cfi_def_cfa_offset(closure_FS + 4) @@ -421,6 +427,7 @@ ENDF(C(ffi_closure_i386)) C(ffi_go_closure_STDCALL): L(UW21): # cfi_startproc + _CET_ENDBR subl $closure_FS, %esp L(UW22): # cfi_def_cfa_offset(closure_FS + 4) @@ -446,6 +453,7 @@ L(UW24): # cfi_startproc # cfi_def_cfa(%esp, 8) # cfi_offset(%eip, -8) + _CET_ENDBR subl $closure_FS-4, %esp L(UW25): # cfi_def_cfa_offset(closure_FS + 4) @@ -468,6 +476,7 @@ ENDF(C(ffi_closure_REGISTER)) C(ffi_closure_STDCALL): L(UW27): # cfi_startproc + _CET_ENDBR subl $closure_FS, %esp L(UW28): # cfi_def_cfa_offset(closure_FS + 4) @@ -564,6 +573,94 @@ L(UW31): # cfi_endproc ENDF(C(ffi_closure_STDCALL)) +#if defined(FFI_EXEC_STATIC_TRAMP) + .balign 16 + .globl C(ffi_closure_i386_alt) + FFI_HIDDEN(C(ffi_closure_i386_alt)) +C(ffi_closure_i386_alt): + /* See the comments above trampoline_code_table. */ + _CET_ENDBR + movl 4(%esp), %eax /* Load closure in eax */ + add $8, %esp /* Restore the stack */ + jmp C(ffi_closure_i386) +ENDF(C(ffi_closure_i386_alt)) + + .balign 16 + .globl C(ffi_closure_REGISTER_alt) + FFI_HIDDEN(C(ffi_closure_REGISTER_alt)) +C(ffi_closure_REGISTER_alt): + /* See the comments above trampoline_code_table. */ + _CET_ENDBR + movl (%esp), %eax /* Restore eax */ + add $4, %esp /* Leave closure on stack */ + jmp C(ffi_closure_REGISTER) +ENDF(C(ffi_closure_REGISTER_alt)) + + .balign 16 + .globl C(ffi_closure_STDCALL_alt) + FFI_HIDDEN(C(ffi_closure_STDCALL_alt)) +C(ffi_closure_STDCALL_alt): + /* See the comments above trampoline_code_table. */ + _CET_ENDBR + movl 4(%esp), %eax /* Load closure in eax */ + add $8, %esp /* Restore the stack */ + jmp C(ffi_closure_STDCALL) +ENDF(C(ffi_closure_STDCALL_alt)) + +/* + * Below is the definition of the trampoline code table. Each element in + * the code table is a trampoline. + * + * Because we jump to the trampoline, we place a _CET_ENDBR at the + * beginning of the trampoline to mark it as a valid branch target. This is + * part of the the Intel CET (Control Flow Enforcement Technology). + */ +/* + * The trampoline uses register eax. It saves the original value of eax on + * the stack. + * + * The trampoline has two parameters - target code to jump to and data for + * the target code. The trampoline extracts the parameters from its parameter + * block (see tramp_table_map()). The trampoline saves the data address on + * the stack. Finally, it jumps to the target code. + * + * The target code can choose to: + * + * - restore the value of eax + * - load the data address in a register + * - restore the stack pointer to what it was when the trampoline was invoked. + */ +#ifdef ENDBR_PRESENT +#define X86_DATA_OFFSET 4081 +#define X86_CODE_OFFSET 4070 +#else +#define X86_DATA_OFFSET 4085 +#define X86_CODE_OFFSET 4074 +#endif + + .align X86_TRAMP_MAP_SIZE + .globl C(trampoline_code_table) + FFI_HIDDEN(C(trampoline_code_table)) +C(trampoline_code_table): + .rept X86_TRAMP_MAP_SIZE / X86_TRAMP_SIZE + _CET_ENDBR + sub $8, %esp + movl %eax, (%esp) /* Save %eax on stack */ + call 1f /* Get next PC into %eax */ + movl X86_DATA_OFFSET(%eax), %eax /* Copy data into %eax */ + movl %eax, 4(%esp) /* Save data on stack */ + call 1f /* Get next PC into %eax */ + movl X86_CODE_OFFSET(%eax), %eax /* Copy code into %eax */ + jmp *%eax /* Jump to code */ +1: + mov (%esp), %eax + ret + .align 4 + .endr +ENDF(C(trampoline_code_table)) + .align X86_TRAMP_MAP_SIZE +#endif /* FFI_EXEC_STATIC_TRAMP */ + #if !FFI_NO_RAW_API #define raw_closure_S_FS (16+16+12) @@ -574,6 +671,7 @@ ENDF(C(ffi_closure_STDCALL)) C(ffi_closure_raw_SYSV): L(UW32): # cfi_startproc + _CET_ENDBR subl $raw_closure_S_FS, %esp L(UW33): # cfi_def_cfa_offset(raw_closure_S_FS + 4) @@ -677,6 +775,7 @@ ENDF(C(ffi_closure_raw_SYSV)) C(ffi_closure_raw_THISCALL): L(UW41): # cfi_startproc + _CET_ENDBR /* Rearrange the stack such that %ecx is the first argument. This means moving the return address. */ popl %edx @@ -790,9 +889,9 @@ ENDF(C(ffi_closure_raw_THISCALL)) #ifdef X86_DARWIN # define COMDAT(X) \ - .section __TEXT,__textcoal_nt,coalesced,pure_instructions; \ + .section __TEXT,__text,coalesced,pure_instructions; \ .weak_definition X; \ - .private_extern X + FFI_HIDDEN(X) #elif defined __ELF__ && !(defined(__sun__) && defined(__svr4__)) # define COMDAT(X) \ .section .text.X,"axG",@progbits,X,comdat; \ @@ -1033,7 +1132,95 @@ L(SFDE9): L(EFDE9): #endif /* !FFI_NO_RAW_API */ -#endif /* ifndef __x86_64__ */ +#ifdef _WIN32 + .def @feat.00; + .scl 3; + .type 0; + .endef + .globl @feat.00 +@feat.00 = 1 +#endif + +#ifdef __APPLE__ + .subsections_via_symbols + .section __LD,__compact_unwind,regular,debug + + /* compact unwind for ffi_call_i386 */ + .long C(ffi_call_i386) + .set L1,L(UW5)-L(UW0) + .long L1 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_go_closure_EAX */ + .long C(ffi_go_closure_EAX) + .set L2,L(UW8)-L(UW6) + .long L2 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_go_closure_ECX */ + .long C(ffi_go_closure_ECX) + .set L3,L(UW11)-L(UW9) + .long L3 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_closure_i386 */ + .long C(ffi_closure_i386) + .set L4,L(UW20)-L(UW12) + .long L4 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_go_closure_STDCALL */ + .long C(ffi_go_closure_STDCALL) + .set L5,L(UW23)-L(UW21) + .long L5 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_closure_REGISTER */ + .long C(ffi_closure_REGISTER) + .set L6,L(UW26)-L(UW24) + .long L6 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_closure_STDCALL */ + .long C(ffi_closure_STDCALL) + .set L7,L(UW31)-L(UW27) + .long L7 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_closure_raw_SYSV */ + .long C(ffi_closure_raw_SYSV) + .set L8,L(UW40)-L(UW32) + .long L8 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_closure_raw_THISCALL */ + .long C(ffi_closure_raw_THISCALL) + .set L9,L(UW52)-L(UW41) + .long L9 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 +#endif /* __APPLE__ */ + +#endif /* ifndef _MSC_VER */ + +#endif /* ifdef __i386__ */ #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",@progbits diff --git a/libffi/src/x86/sysv_intel.S b/libffi/src/x86/sysv_intel.S new file mode 100644 index 0000000..3cafd71 --- /dev/null +++ b/libffi/src/x86/sysv_intel.S @@ -0,0 +1,995 @@ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 2017 Anthony Green + - Copyright (c) 2013 The Written Word, Inc. + - Copyright (c) 1996,1998,2001-2003,2005,2008,2010 Red Hat, Inc. + + X86 Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#ifndef __x86_64__ +#ifdef _MSC_VER + +#define LIBFFI_ASM +#include <fficonfig.h> +#include <ffi.h> +#include <ffi_cfi.h> +#include "internal.h" + +#define C2(X, Y) X ## Y +#define C1(X, Y) C2(X, Y) +#define L(X) C1(L, X) +# define ENDF(X) X ENDP + +/* This macro allows the safe creation of jump tables without an + actual table. The entry points into the table are all 8 bytes. + The use of ORG asserts that we're at the correct location. */ +/* ??? The clang assembler doesn't handle .org with symbolic expressions. */ +#if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__)) +# define E(BASE, X) ALIGN 8 +#else +# define E(BASE, X) ALIGN 8; ORG BASE + X * 8 +#endif + + .686P + .MODEL FLAT + +EXTRN @ffi_closure_inner@8:PROC +_TEXT SEGMENT + +/* This is declared as + + void ffi_call_i386(struct call_frame *frame, char *argp) + __attribute__((fastcall)); + + Thus the arguments are present in + + ecx: frame + edx: argp +*/ + +ALIGN 16 +PUBLIC @ffi_call_i386@8 +@ffi_call_i386@8 PROC +L(UW0): + cfi_startproc + #if !HAVE_FASTCALL + mov ecx, [esp+4] + mov edx, [esp+8] + #endif + mov eax, [esp] /* move the return address */ + mov [ecx], ebp /* store ebp into local frame */ + mov [ecx+4], eax /* store retaddr into local frame */ + + /* New stack frame based off ebp. This is a itty bit of unwind + trickery in that the CFA *has* changed. There is no easy way + to describe it correctly on entry to the function. Fortunately, + it doesn't matter too much since at all points we can correctly + unwind back to ffi_call. Note that the location to which we + moved the return address is (the new) CFA-4, so from the + perspective of the unwind info, it hasn't moved. */ + mov ebp, ecx +L(UW1): + // cfi_def_cfa(%ebp, 8) + // cfi_rel_offset(%ebp, 0) + + mov esp, edx /* set outgoing argument stack */ + mov eax, [20+R_EAX*4+ebp] /* set register arguments */ + mov edx, [20+R_EDX*4+ebp] + mov ecx, [20+R_ECX*4+ebp] + + call dword ptr [ebp+8] + + mov ecx, [12+ebp] /* load return type code */ + mov [ebp+8], ebx /* preserve %ebx */ +L(UW2): + // cfi_rel_offset(%ebx, 8) + + and ecx, X86_RET_TYPE_MASK + lea ebx, [L(store_table) + ecx * 8] + mov ecx, [ebp+16] /* load result address */ + jmp ebx + + ALIGN 8 +L(store_table): +E(L(store_table), X86_RET_FLOAT) + fstp DWORD PTR [ecx] + jmp L(e1) +E(L(store_table), X86_RET_DOUBLE) + fstp QWORD PTR [ecx] + jmp L(e1) +E(L(store_table), X86_RET_LDOUBLE) + fstp QWORD PTR [ecx] + jmp L(e1) +E(L(store_table), X86_RET_SINT8) + movsx eax, al + mov [ecx], eax + jmp L(e1) +E(L(store_table), X86_RET_SINT16) + movsx eax, ax + mov [ecx], eax + jmp L(e1) +E(L(store_table), X86_RET_UINT8) + movzx eax, al + mov [ecx], eax + jmp L(e1) +E(L(store_table), X86_RET_UINT16) + movzx eax, ax + mov [ecx], eax + jmp L(e1) +E(L(store_table), X86_RET_INT64) + mov [ecx+4], edx + /* fallthru */ +E(L(store_table), X86_RET_int 32) + mov [ecx], eax + /* fallthru */ +E(L(store_table), X86_RET_VOID) +L(e1): + mov ebx, [ebp+8] + mov esp, ebp + pop ebp +L(UW3): + // cfi_remember_state + // cfi_def_cfa(%esp, 4) + // cfi_restore(%ebx) + // cfi_restore(%ebp) + ret +L(UW4): + // cfi_restore_state + +E(L(store_table), X86_RET_STRUCTPOP) + jmp L(e1) +E(L(store_table), X86_RET_STRUCTARG) + jmp L(e1) +E(L(store_table), X86_RET_STRUCT_1B) + mov [ecx], al + jmp L(e1) +E(L(store_table), X86_RET_STRUCT_2B) + mov [ecx], ax + jmp L(e1) + + /* Fill out the table so that bad values are predictable. */ +E(L(store_table), X86_RET_UNUSED14) + int 3 +E(L(store_table), X86_RET_UNUSED15) + int 3 + +L(UW5): + // cfi_endproc +ENDF(@ffi_call_i386@8) + +/* The inner helper is declared as + + void ffi_closure_inner(struct closure_frame *frame, char *argp) + __attribute_((fastcall)) + + Thus the arguments are placed in + + ecx: frame + edx: argp +*/ + +/* Macros to help setting up the closure_data structure. */ + +#if HAVE_FASTCALL +# define closure_FS (40 + 4) +# define closure_CF 0 +#else +# define closure_FS (8 + 40 + 12) +# define closure_CF 8 +#endif + +FFI_CLOSURE_SAVE_REGS MACRO + mov [esp + closure_CF+16+R_EAX*4], eax + mov [esp + closure_CF+16+R_EDX*4], edx + mov [esp + closure_CF+16+R_ECX*4], ecx +ENDM + +FFI_CLOSURE_COPY_TRAMP_DATA MACRO + mov edx, [eax+FFI_TRAMPOLINE_SIZE] /* copy cif */ + mov ecx, [eax+FFI_TRAMPOLINE_SIZE+4] /* copy fun */ + mov eax, [eax+FFI_TRAMPOLINE_SIZE+8]; /* copy user_data */ + mov [esp+closure_CF+28], edx + mov [esp+closure_CF+32], ecx + mov [esp+closure_CF+36], eax +ENDM + +#if HAVE_FASTCALL +FFI_CLOSURE_PREP_CALL MACRO + mov ecx, esp /* load closure_data */ + lea edx, [esp+closure_FS+4] /* load incoming stack */ +ENDM +#else +FFI_CLOSURE_PREP_CALL MACRO + lea ecx, [esp+closure_CF] /* load closure_data */ + lea edx, [esp+closure_FS+4] /* load incoming stack */ + mov [esp], ecx + mov [esp+4], edx +ENDM +#endif + +FFI_CLOSURE_CALL_INNER MACRO UWN + call @ffi_closure_inner@8 +ENDM + +FFI_CLOSURE_MASK_AND_JUMP MACRO LABEL + and eax, X86_RET_TYPE_MASK + lea edx, [LABEL+eax*8] + mov eax, [esp+closure_CF] /* optimiztic load */ + jmp edx +ENDM + +ALIGN 16 +PUBLIC ffi_go_closure_EAX +ffi_go_closure_EAX PROC C +L(UW6): + // cfi_startproc + sub esp, closure_FS +L(UW7): + // cfi_def_cfa_offset(closure_FS + 4) + FFI_CLOSURE_SAVE_REGS + mov edx, [eax+4] /* copy cif */ + mov ecx, [eax +8] /* copy fun */ + mov [esp+closure_CF+28], edx + mov [esp+closure_CF+32], ecx + mov [esp+closure_CF+36], eax /* closure is user_data */ + jmp L(do_closure_i386) +L(UW8): + // cfi_endproc +ENDF(ffi_go_closure_EAX) + +ALIGN 16 +PUBLIC ffi_go_closure_ECX +ffi_go_closure_ECX PROC C +L(UW9): + // cfi_startproc + sub esp, closure_FS +L(UW10): + // cfi_def_cfa_offset(closure_FS + 4) + FFI_CLOSURE_SAVE_REGS + mov edx, [ecx+4] /* copy cif */ + mov eax, [ecx+8] /* copy fun */ + mov [esp+closure_CF+28], edx + mov [esp+closure_CF+32], eax + mov [esp+closure_CF+36], ecx /* closure is user_data */ + jmp L(do_closure_i386) +L(UW11): + // cfi_endproc +ENDF(ffi_go_closure_ECX) + +/* The closure entry points are reached from the ffi_closure trampoline. + On entry, %eax contains the address of the ffi_closure. */ + +ALIGN 16 +PUBLIC ffi_closure_i386 +ffi_closure_i386 PROC C +L(UW12): + // cfi_startproc + sub esp, closure_FS +L(UW13): + // cfi_def_cfa_offset(closure_FS + 4) + + FFI_CLOSURE_SAVE_REGS + FFI_CLOSURE_COPY_TRAMP_DATA + + /* Entry point from preceeding Go closures. */ +L(do_closure_i386):: + + FFI_CLOSURE_PREP_CALL + FFI_CLOSURE_CALL_INNER(14) + FFI_CLOSURE_MASK_AND_JUMP L(C1(load_table,2)) + + ALIGN 8 +L(load_table2): +E(L(load_table2), X86_RET_FLOAT) + fld dword ptr [esp+closure_CF] + jmp L(e2) +E(L(load_table2), X86_RET_DOUBLE) + fld qword ptr [esp+closure_CF] + jmp L(e2) +E(L(load_table2), X86_RET_LDOUBLE) + fld qword ptr [esp+closure_CF] + jmp L(e2) +E(L(load_table2), X86_RET_SINT8) + movsx eax, al + jmp L(e2) +E(L(load_table2), X86_RET_SINT16) + movsx eax, ax + jmp L(e2) +E(L(load_table2), X86_RET_UINT8) + movzx eax, al + jmp L(e2) +E(L(load_table2), X86_RET_UINT16) + movzx eax, ax + jmp L(e2) +E(L(load_table2), X86_RET_INT64) + mov edx, [esp+closure_CF+4] + jmp L(e2) +E(L(load_table2), X86_RET_INT32) + nop + /* fallthru */ +E(L(load_table2), X86_RET_VOID) +L(e2): + add esp, closure_FS +L(UW16): + // cfi_adjust_cfa_offset(-closure_FS) + ret +L(UW17): + // cfi_adjust_cfa_offset(closure_FS) +E(L(load_table2), X86_RET_STRUCTPOP) + add esp, closure_FS +L(UW18): + // cfi_adjust_cfa_offset(-closure_FS) + ret 4 +L(UW19): + // cfi_adjust_cfa_offset(closure_FS) +E(L(load_table2), X86_RET_STRUCTARG) + jmp L(e2) +E(L(load_table2), X86_RET_STRUCT_1B) + movzx eax, al + jmp L(e2) +E(L(load_table2), X86_RET_STRUCT_2B) + movzx eax, ax + jmp L(e2) + + /* Fill out the table so that bad values are predictable. */ +E(L(load_table2), X86_RET_UNUSED14) + int 3 +E(L(load_table2), X86_RET_UNUSED15) + int 3 + +L(UW20): + // cfi_endproc +ENDF(ffi_closure_i386) + +ALIGN 16 +PUBLIC ffi_go_closure_STDCALL +ffi_go_closure_STDCALL PROC C +L(UW21): + // cfi_startproc + sub esp, closure_FS +L(UW22): + // cfi_def_cfa_offset(closure_FS + 4) + FFI_CLOSURE_SAVE_REGS + mov edx, [ecx+4] /* copy cif */ + mov eax, [ecx+8] /* copy fun */ + mov [esp+closure_CF+28], edx + mov [esp+closure_CF+32], eax + mov [esp+closure_CF+36], ecx /* closure is user_data */ + jmp L(do_closure_STDCALL) +L(UW23): + // cfi_endproc +ENDF(ffi_go_closure_STDCALL) + +/* For REGISTER, we have no available parameter registers, and so we + enter here having pushed the closure onto the stack. */ + +ALIGN 16 +PUBLIC ffi_closure_REGISTER +ffi_closure_REGISTER PROC C +L(UW24): + // cfi_startproc + // cfi_def_cfa(%esp, 8) + // cfi_offset(%eip, -8) + sub esp, closure_FS-4 +L(UW25): + // cfi_def_cfa_offset(closure_FS + 4) + FFI_CLOSURE_SAVE_REGS + mov ecx, [esp+closure_FS-4] /* load retaddr */ + mov eax, [esp+closure_FS] /* load closure */ + mov [esp+closure_FS], ecx /* move retaddr */ + jmp L(do_closure_REGISTER) +L(UW26): + // cfi_endproc +ENDF(ffi_closure_REGISTER) + +/* For STDCALL (and others), we need to pop N bytes of arguments off + the stack following the closure. The amount needing to be popped + is returned to us from ffi_closure_inner. */ + +ALIGN 16 +PUBLIC ffi_closure_STDCALL +ffi_closure_STDCALL PROC C +L(UW27): + // cfi_startproc + sub esp, closure_FS +L(UW28): + // cfi_def_cfa_offset(closure_FS + 4) + + FFI_CLOSURE_SAVE_REGS + + /* Entry point from ffi_closure_REGISTER. */ +L(do_closure_REGISTER):: + + FFI_CLOSURE_COPY_TRAMP_DATA + + /* Entry point from preceeding Go closure. */ +L(do_closure_STDCALL):: + + FFI_CLOSURE_PREP_CALL + FFI_CLOSURE_CALL_INNER(29) + + mov ecx, eax + shr ecx, X86_RET_POP_SHIFT /* isolate pop count */ + lea ecx, [esp+closure_FS+ecx] /* compute popped esp */ + mov edx, [esp+closure_FS] /* move return address */ + mov [ecx], edx + + /* From this point on, the value of %esp upon return is %ecx+4, + and we've copied the return address to %ecx to make return easy. + There's no point in representing this in the unwind info, as + there is always a window between the mov and the ret which + will be wrong from one point of view or another. */ + + FFI_CLOSURE_MASK_AND_JUMP L(C1(load_table,3)) + + ALIGN 8 +L(load_table3): +E(L(load_table3), X86_RET_FLOAT) + fld DWORD PTR [esp+closure_CF] + mov esp, ecx + ret +E(L(load_table3), X86_RET_DOUBLE) + fld QWORD PTR [esp+closure_CF] + mov esp, ecx + ret +E(L(load_table3), X86_RET_LDOUBLE) + fld QWORD PTR [esp+closure_CF] + mov esp, ecx + ret +E(L(load_table3), X86_RET_SINT8) + movsx eax, al + mov esp, ecx + ret +E(L(load_table3), X86_RET_SINT16) + movsx eax, ax + mov esp, ecx + ret +E(L(load_table3), X86_RET_UINT8) + movzx eax, al + mov esp, ecx + ret +E(L(load_table3), X86_RET_UINT16) + movzx eax, ax + mov esp, ecx + ret +E(L(load_table3), X86_RET_INT64) + mov edx, [esp+closure_CF+4] + mov esp, ecx + ret +E(L(load_table3), X86_RET_int 32) + mov esp, ecx + ret +E(L(load_table3), X86_RET_VOID) + mov esp, ecx + ret +E(L(load_table3), X86_RET_STRUCTPOP) + mov esp, ecx + ret +E(L(load_table3), X86_RET_STRUCTARG) + mov esp, ecx + ret +E(L(load_table3), X86_RET_STRUCT_1B) + movzx eax, al + mov esp, ecx + ret +E(L(load_table3), X86_RET_STRUCT_2B) + movzx eax, ax + mov esp, ecx + ret + + /* Fill out the table so that bad values are predictable. */ +E(L(load_table3), X86_RET_UNUSED14) + int 3 +E(L(load_table3), X86_RET_UNUSED15) + int 3 + +L(UW31): + // cfi_endproc +ENDF(ffi_closure_STDCALL) + +#if !FFI_NO_RAW_API + +#define raw_closure_S_FS (16+16+12) + +ALIGN 16 +PUBLIC ffi_closure_raw_SYSV +ffi_closure_raw_SYSV PROC C +L(UW32): + // cfi_startproc + sub esp, raw_closure_S_FS +L(UW33): + // cfi_def_cfa_offset(raw_closure_S_FS + 4) + mov [esp+raw_closure_S_FS-4], ebx +L(UW34): + // cfi_rel_offset(%ebx, raw_closure_S_FS-4) + + mov edx, [eax+FFI_TRAMPOLINE_SIZE+8] /* load cl->user_data */ + mov [esp+12], edx + lea edx, [esp+raw_closure_S_FS+4] /* load raw_args */ + mov [esp+8], edx + lea edx, [esp+16] /* load &res */ + mov [esp+4], edx + mov ebx, [eax+FFI_TRAMPOLINE_SIZE] /* load cl->cif */ + mov [esp], ebx + call DWORD PTR [eax+FFI_TRAMPOLINE_SIZE+4] /* call cl->fun */ + + mov eax, [ebx+20] /* load cif->flags */ + and eax, X86_RET_TYPE_MASK +// #ifdef __PIC__ +// call __x86.get_pc_thunk.bx +// L(pc4): +// lea ecx, L(load_table4)-L(pc4)(%ebx, %eax, 8), %ecx +// #else + lea ecx, [L(load_table4)+eax+8] +// #endif + mov ebx, [esp+raw_closure_S_FS-4] +L(UW35): + // cfi_restore(%ebx) + mov eax, [esp+16] /* Optimistic load */ + jmp dword ptr [ecx] + + ALIGN 8 +L(load_table4): +E(L(load_table4), X86_RET_FLOAT) + fld DWORD PTR [esp +16] + jmp L(e4) +E(L(load_table4), X86_RET_DOUBLE) + fld QWORD PTR [esp +16] + jmp L(e4) +E(L(load_table4), X86_RET_LDOUBLE) + fld QWORD PTR [esp +16] + jmp L(e4) +E(L(load_table4), X86_RET_SINT8) + movsx eax, al + jmp L(e4) +E(L(load_table4), X86_RET_SINT16) + movsx eax, ax + jmp L(e4) +E(L(load_table4), X86_RET_UINT8) + movzx eax, al + jmp L(e4) +E(L(load_table4), X86_RET_UINT16) + movzx eax, ax + jmp L(e4) +E(L(load_table4), X86_RET_INT64) + mov edx, [esp+16+4] + jmp L(e4) +E(L(load_table4), X86_RET_int 32) + nop + /* fallthru */ +E(L(load_table4), X86_RET_VOID) +L(e4): + add esp, raw_closure_S_FS +L(UW36): + // cfi_adjust_cfa_offset(-raw_closure_S_FS) + ret +L(UW37): + // cfi_adjust_cfa_offset(raw_closure_S_FS) +E(L(load_table4), X86_RET_STRUCTPOP) + add esp, raw_closure_S_FS +L(UW38): + // cfi_adjust_cfa_offset(-raw_closure_S_FS) + ret 4 +L(UW39): + // cfi_adjust_cfa_offset(raw_closure_S_FS) +E(L(load_table4), X86_RET_STRUCTARG) + jmp L(e4) +E(L(load_table4), X86_RET_STRUCT_1B) + movzx eax, al + jmp L(e4) +E(L(load_table4), X86_RET_STRUCT_2B) + movzx eax, ax + jmp L(e4) + + /* Fill out the table so that bad values are predictable. */ +E(L(load_table4), X86_RET_UNUSED14) + int 3 +E(L(load_table4), X86_RET_UNUSED15) + int 3 + +L(UW40): + // cfi_endproc +ENDF(ffi_closure_raw_SYSV) + +#define raw_closure_T_FS (16+16+8) + +ALIGN 16 +PUBLIC ffi_closure_raw_THISCALL +ffi_closure_raw_THISCALL PROC C +L(UW41): + // cfi_startproc + /* Rearrange the stack such that %ecx is the first argument. + This means moving the return address. */ + pop edx +L(UW42): + // cfi_def_cfa_offset(0) + // cfi_register(%eip, %edx) + push ecx +L(UW43): + // cfi_adjust_cfa_offset(4) + push edx +L(UW44): + // cfi_adjust_cfa_offset(4) + // cfi_rel_offset(%eip, 0) + sub esp, raw_closure_T_FS +L(UW45): + // cfi_adjust_cfa_offset(raw_closure_T_FS) + mov [esp+raw_closure_T_FS-4], ebx +L(UW46): + // cfi_rel_offset(%ebx, raw_closure_T_FS-4) + + mov edx, [eax+FFI_TRAMPOLINE_SIZE+8] /* load cl->user_data */ + mov [esp+12], edx + lea edx, [esp+raw_closure_T_FS+4] /* load raw_args */ + mov [esp+8], edx + lea edx, [esp+16] /* load &res */ + mov [esp+4], edx + mov ebx, [eax+FFI_TRAMPOLINE_SIZE] /* load cl->cif */ + mov [esp], ebx + call DWORD PTR [eax+FFI_TRAMPOLINE_SIZE+4] /* call cl->fun */ + + mov eax, [ebx+20] /* load cif->flags */ + and eax, X86_RET_TYPE_MASK +// #ifdef __PIC__ +// call __x86.get_pc_thunk.bx +// L(pc5): +// leal L(load_table5)-L(pc5)(%ebx, %eax, 8), %ecx +// #else + lea ecx, [L(load_table5)+eax*8] +//#endif + mov ebx, [esp+raw_closure_T_FS-4] +L(UW47): + // cfi_restore(%ebx) + mov eax, [esp+16] /* Optimistic load */ + jmp DWORD PTR [ecx] + + AlIGN 4 +L(load_table5): +E(L(load_table5), X86_RET_FLOAT) + fld DWORD PTR [esp +16] + jmp L(e5) +E(L(load_table5), X86_RET_DOUBLE) + fld QWORD PTR [esp +16] + jmp L(e5) +E(L(load_table5), X86_RET_LDOUBLE) + fld QWORD PTR [esp+16] + jmp L(e5) +E(L(load_table5), X86_RET_SINT8) + movsx eax, al + jmp L(e5) +E(L(load_table5), X86_RET_SINT16) + movsx eax, ax + jmp L(e5) +E(L(load_table5), X86_RET_UINT8) + movzx eax, al + jmp L(e5) +E(L(load_table5), X86_RET_UINT16) + movzx eax, ax + jmp L(e5) +E(L(load_table5), X86_RET_INT64) + mov edx, [esp+16+4] + jmp L(e5) +E(L(load_table5), X86_RET_int 32) + nop + /* fallthru */ +E(L(load_table5), X86_RET_VOID) +L(e5): + add esp, raw_closure_T_FS +L(UW48): + // cfi_adjust_cfa_offset(-raw_closure_T_FS) + /* Remove the extra %ecx argument we pushed. */ + ret 4 +L(UW49): + // cfi_adjust_cfa_offset(raw_closure_T_FS) +E(L(load_table5), X86_RET_STRUCTPOP) + add esp, raw_closure_T_FS +L(UW50): + // cfi_adjust_cfa_offset(-raw_closure_T_FS) + ret 8 +L(UW51): + // cfi_adjust_cfa_offset(raw_closure_T_FS) +E(L(load_table5), X86_RET_STRUCTARG) + jmp L(e5) +E(L(load_table5), X86_RET_STRUCT_1B) + movzx eax, al + jmp L(e5) +E(L(load_table5), X86_RET_STRUCT_2B) + movzx eax, ax + jmp L(e5) + + /* Fill out the table so that bad values are predictable. */ +E(L(load_table5), X86_RET_UNUSED14) + int 3 +E(L(load_table5), X86_RET_UNUSED15) + int 3 + +L(UW52): + // cfi_endproc +ENDF(ffi_closure_raw_THISCALL) + +#endif /* !FFI_NO_RAW_API */ + +#ifdef X86_DARWIN +# define COMDAT(X) \ + .section __TEXT,__text,coalesced,pure_instructions; \ + .weak_definition X; \ + FFI_HIDDEN(X) +#elif defined __ELF__ && !(defined(__sun__) && defined(__svr4__)) +# define COMDAT(X) \ + .section .text.X,"axG",@progbits,X,comdat; \ + PUBLIC X; \ + FFI_HIDDEN(X) +#else +# define COMDAT(X) +#endif + +// #if defined(__PIC__) +// COMDAT(C(__x86.get_pc_thunk.bx)) +// C(__x86.get_pc_thunk.bx): +// movl (%esp), %ebx +// ret +// ENDF(C(__x86.get_pc_thunk.bx)) +// # if defined X86_DARWIN || defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE +// COMDAT(C(__x86.get_pc_thunk.dx)) +// C(__x86.get_pc_thunk.dx): +// movl (%esp), %edx +// ret +// ENDF(C(__x86.get_pc_thunk.dx)) +// #endif /* DARWIN || HIDDEN */ +// #endif /* __PIC__ */ + +#if 0 +/* Sadly, OSX cctools-as doesn't understand .cfi directives at all. */ + +#ifdef __APPLE__ +.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support +EHFrame0: +#elif defined(X86_WIN32) +.section .eh_frame,"r" +#elif defined(HAVE_AS_X86_64_UNWIND_SECTION_TYPE) +.section .eh_frame,EH_FRAME_FLAGS,@unwind +#else +.section .eh_frame,EH_FRAME_FLAGS,@progbits +#endif + +#ifdef HAVE_AS_X86_PCREL +# define PCREL(X) X - . +#else +# define PCREL(X) X@rel +#endif + +/* Simplify advancing between labels. Assume DW_CFA_advance_loc1 fits. */ +#define ADV(N, P) .byte 2, L(N)-L(P) + + .balign 4 +L(CIE): + .set L(set0),L(ECIE)-L(SCIE) + .long L(set0) /* CIE Length */ +L(SCIE): + .long 0 /* CIE Identifier Tag */ + .byte 1 /* CIE Version */ + .ascii "zR\0" /* CIE Augmentation */ + .byte 1 /* CIE Code Alignment Factor */ + .byte 0x7c /* CIE Data Alignment Factor */ + .byte 0x8 /* CIE RA Column */ + .byte 1 /* Augmentation size */ + .byte 0x1b /* FDE Encoding (pcrel sdata4) */ + .byte 0xc, 4, 4 /* DW_CFA_def_cfa, %esp offset 4 */ + .byte 0x80+8, 1 /* DW_CFA_offset, %eip offset 1*-4 */ + .balign 4 +L(ECIE): + + .set L(set1),L(EFDE1)-L(SFDE1) + .long L(set1) /* FDE Length */ +L(SFDE1): + .long L(SFDE1)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW0)) /* Initial location */ + .long L(UW5)-L(UW0) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW1, UW0) + .byte 0xc, 5, 8 /* DW_CFA_def_cfa, %ebp 8 */ + .byte 0x80+5, 2 /* DW_CFA_offset, %ebp 2*-4 */ + ADV(UW2, UW1) + .byte 0x80+3, 0 /* DW_CFA_offset, %ebx 0*-4 */ + ADV(UW3, UW2) + .byte 0xa /* DW_CFA_remember_state */ + .byte 0xc, 4, 4 /* DW_CFA_def_cfa, %esp 4 */ + .byte 0xc0+3 /* DW_CFA_restore, %ebx */ + .byte 0xc0+5 /* DW_CFA_restore, %ebp */ + ADV(UW4, UW3) + .byte 0xb /* DW_CFA_restore_state */ + .balign 4 +L(EFDE1): + + .set L(set2),L(EFDE2)-L(SFDE2) + .long L(set2) /* FDE Length */ +L(SFDE2): + .long L(SFDE2)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW6)) /* Initial location */ + .long L(UW8)-L(UW6) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW7, UW6) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE2): + + .set L(set3),L(EFDE3)-L(SFDE3) + .long L(set3) /* FDE Length */ +L(SFDE3): + .long L(SFDE3)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW9)) /* Initial location */ + .long L(UW11)-L(UW9) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW10, UW9) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE3): + + .set L(set4),L(EFDE4)-L(SFDE4) + .long L(set4) /* FDE Length */ +L(SFDE4): + .long L(SFDE4)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW12)) /* Initial location */ + .long L(UW20)-L(UW12) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW13, UW12) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ +#ifdef FFI_CLOSURE_CALL_INNER_SAVE_EBX + ADV(UW14, UW13) + .byte 0x80+3, (40-(closure_FS+4))/-4 /* DW_CFA_offset %ebx */ + ADV(UW15, UW14) + .byte 0xc0+3 /* DW_CFA_restore %ebx */ + ADV(UW16, UW15) +#else + ADV(UW16, UW13) +#endif + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW17, UW16) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + ADV(UW18, UW17) + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW19, UW18) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE4): + + .set L(set5),L(EFDE5)-L(SFDE5) + .long L(set5) /* FDE Length */ +L(SFDE5): + .long L(SFDE5)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW21)) /* Initial location */ + .long L(UW23)-L(UW21) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW22, UW21) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE5): + + .set L(set6),L(EFDE6)-L(SFDE6) + .long L(set6) /* FDE Length */ +L(SFDE6): + .long L(SFDE6)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW24)) /* Initial location */ + .long L(UW26)-L(UW24) /* Address range */ + .byte 0 /* Augmentation size */ + .byte 0xe, 8 /* DW_CFA_def_cfa_offset */ + .byte 0x80+8, 2 /* DW_CFA_offset %eip, 2*-4 */ + ADV(UW25, UW24) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE6): + + .set L(set7),L(EFDE7)-L(SFDE7) + .long L(set7) /* FDE Length */ +L(SFDE7): + .long L(SFDE7)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW27)) /* Initial location */ + .long L(UW31)-L(UW27) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW28, UW27) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ +#ifdef FFI_CLOSURE_CALL_INNER_SAVE_EBX + ADV(UW29, UW28) + .byte 0x80+3, (40-(closure_FS+4))/-4 /* DW_CFA_offset %ebx */ + ADV(UW30, UW29) + .byte 0xc0+3 /* DW_CFA_restore %ebx */ +#endif + .balign 4 +L(EFDE7): + +#if !FFI_NO_RAW_API + .set L(set8),L(EFDE8)-L(SFDE8) + .long L(set8) /* FDE Length */ +L(SFDE8): + .long L(SFDE8)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW32)) /* Initial location */ + .long L(UW40)-L(UW32) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW33, UW32) + .byte 0xe, raw_closure_S_FS+4 /* DW_CFA_def_cfa_offset */ + ADV(UW34, UW33) + .byte 0x80+3, 2 /* DW_CFA_offset %ebx 2*-4 */ + ADV(UW35, UW34) + .byte 0xc0+3 /* DW_CFA_restore %ebx */ + ADV(UW36, UW35) + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW37, UW36) + .byte 0xe, raw_closure_S_FS+4 /* DW_CFA_def_cfa_offset */ + ADV(UW38, UW37) + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW39, UW38) + .byte 0xe, raw_closure_S_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE8): + + .set L(set9),L(EFDE9)-L(SFDE9) + .long L(set9) /* FDE Length */ +L(SFDE9): + .long L(SFDE9)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW41)) /* Initial location */ + .long L(UW52)-L(UW41) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW42, UW41) + .byte 0xe, 0 /* DW_CFA_def_cfa_offset */ + .byte 0x9, 8, 2 /* DW_CFA_register %eip, %edx */ + ADV(UW43, UW42) + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW44, UW43) + .byte 0xe, 8 /* DW_CFA_def_cfa_offset */ + .byte 0x80+8, 2 /* DW_CFA_offset %eip 2*-4 */ + ADV(UW45, UW44) + .byte 0xe, raw_closure_T_FS+8 /* DW_CFA_def_cfa_offset */ + ADV(UW46, UW45) + .byte 0x80+3, 3 /* DW_CFA_offset %ebx 3*-4 */ + ADV(UW47, UW46) + .byte 0xc0+3 /* DW_CFA_restore %ebx */ + ADV(UW48, UW47) + .byte 0xe, 8 /* DW_CFA_def_cfa_offset */ + ADV(UW49, UW48) + .byte 0xe, raw_closure_T_FS+8 /* DW_CFA_def_cfa_offset */ + ADV(UW50, UW49) + .byte 0xe, 8 /* DW_CFA_def_cfa_offset */ + ADV(UW51, UW50) + .byte 0xe, raw_closure_T_FS+8 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE9): +#endif /* !FFI_NO_RAW_API */ + +#ifdef _WIN32 + .def @feat.00; + .scl 3; + .type 0; + .endef + PUBLIC @feat.00 +@feat.00 = 1 +#endif + +#endif /* ifndef _MSC_VER */ +#endif /* ifndef __x86_64__ */ + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",@progbits +#endif +#endif + +END
\ No newline at end of file diff --git a/libffi/src/x86/unix64.S b/libffi/src/x86/unix64.S index c83010c..ca6fe0c 100644 --- a/libffi/src/x86/unix64.S +++ b/libffi/src/x86/unix64.S @@ -31,31 +31,10 @@ #include <fficonfig.h> #include <ffi.h> #include "internal64.h" +#include "asmnames.h" .text -#define C2(X, Y) X ## Y -#define C1(X, Y) C2(X, Y) -#ifdef __USER_LABEL_PREFIX__ -# define C(X) C1(__USER_LABEL_PREFIX__, X) -#else -# define C(X) X -#endif - -#ifdef __APPLE__ -# define L(X) C1(L, X) -#else -# define L(X) C1(.L, X) -#endif - -#ifdef __ELF__ -# define PLT(X) X@PLT -# define ENDF(X) .type X,@function; .size X, . - X -#else -# define PLT(X) X -# define ENDF(X) -#endif - /* This macro allows the safe creation of jump tables without an actual table. The entry points into the table are all 8 bytes. The use of ORG asserts that we're at the correct location. */ @@ -63,7 +42,11 @@ #if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__)) # define E(BASE, X) .balign 8 #else -# define E(BASE, X) .balign 8; .org BASE + X * 8 +# ifdef __CET__ +# define E(BASE, X) .balign 8; .org BASE + X * 16 +# else +# define E(BASE, X) .balign 8; .org BASE + X * 8 +# endif #endif /* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, @@ -79,6 +62,7 @@ C(ffi_call_unix64): L(UW0): + _CET_ENDBR movq (%rsp), %r10 /* Load return address. */ leaq (%rdi, %rsi), %rax /* Find local stack base. */ movq %rdx, (%rax) /* Save flags. */ @@ -100,7 +84,6 @@ L(UW1): movq %rdi, %r10 /* Save a copy of the register area. */ movq %r8, %r11 /* Save a copy of the target fn. */ - movl %r9d, %eax /* Set number of SSE registers. */ /* Load up all argument registers. */ movq (%r10), %rdi @@ -109,7 +92,7 @@ L(UW1): movq 0x18(%r10), %rcx movq 0x20(%r10), %r8 movq 0x28(%r10), %r9 - movl 0xb0(%r10), %eax + movl 0xb0(%r10), %eax /* Set number of SSE registers. */ testl %eax, %eax jnz L(load_sse) L(ret_from_load_sse): @@ -137,6 +120,11 @@ L(UW2): movzbl %cl, %r10d leaq L(store_table)(%rip), %r11 ja L(sa) +#ifdef __CET__ + /* NB: Originally, each slot is 8 byte. 4 bytes of ENDBR64 + + 4 bytes NOP padding double slot size to 16 bytes. */ + addl %r10d, %r10d +#endif leaq (%r11, %r10, 8), %r10 /* Prep for the structure cases: scratch area in redzone. */ @@ -146,57 +134,73 @@ L(UW2): .balign 8 L(store_table): E(L(store_table), UNIX64_RET_VOID) + _CET_ENDBR ret E(L(store_table), UNIX64_RET_UINT8) + _CET_ENDBR movzbl %al, %eax movq %rax, (%rdi) ret E(L(store_table), UNIX64_RET_UINT16) + _CET_ENDBR movzwl %ax, %eax movq %rax, (%rdi) ret E(L(store_table), UNIX64_RET_UINT32) + _CET_ENDBR movl %eax, %eax movq %rax, (%rdi) ret E(L(store_table), UNIX64_RET_SINT8) + _CET_ENDBR movsbq %al, %rax movq %rax, (%rdi) ret E(L(store_table), UNIX64_RET_SINT16) + _CET_ENDBR movswq %ax, %rax movq %rax, (%rdi) ret E(L(store_table), UNIX64_RET_SINT32) + _CET_ENDBR cltq movq %rax, (%rdi) ret E(L(store_table), UNIX64_RET_INT64) + _CET_ENDBR movq %rax, (%rdi) ret E(L(store_table), UNIX64_RET_XMM32) + _CET_ENDBR movd %xmm0, (%rdi) ret E(L(store_table), UNIX64_RET_XMM64) + _CET_ENDBR movq %xmm0, (%rdi) ret E(L(store_table), UNIX64_RET_X87) + _CET_ENDBR fstpt (%rdi) ret E(L(store_table), UNIX64_RET_X87_2) + _CET_ENDBR fstpt (%rdi) fstpt 16(%rdi) ret E(L(store_table), UNIX64_RET_ST_XMM0_RAX) + _CET_ENDBR movq %rax, 8(%rsi) jmp L(s3) E(L(store_table), UNIX64_RET_ST_RAX_XMM0) + _CET_ENDBR movq %xmm0, 8(%rsi) jmp L(s2) E(L(store_table), UNIX64_RET_ST_XMM0_XMM1) + _CET_ENDBR movq %xmm1, 8(%rsi) jmp L(s3) E(L(store_table), UNIX64_RET_ST_RAX_RDX) + _CET_ENDBR movq %rdx, 8(%rsi) L(s2): movq %rax, (%rsi) @@ -248,6 +252,7 @@ ENDF(C(ffi_call_unix64)) C(ffi_closure_unix64_sse): L(UW5): + _CET_ENDBR subq $ffi_closure_FS, %rsp L(UW6): /* cfi_adjust_cfa_offset(ffi_closure_FS) */ @@ -271,6 +276,7 @@ ENDF(C(ffi_closure_unix64_sse)) C(ffi_closure_unix64): L(UW8): + _CET_ENDBR subq $ffi_closure_FS, %rsp L(UW9): /* cfi_adjust_cfa_offset(ffi_closure_FS) */ @@ -295,7 +301,7 @@ L(do_closure): leaq ffi_closure_OFS_RVALUE(%rsp), %rcx /* Load rvalue */ movq %rsp, %r8 /* Load reg_args */ leaq ffi_closure_FS+8(%rsp), %r9 /* Load argp */ - call C(ffi_closure_unix64_inner) + call PLT(C(ffi_closure_unix64_inner)) /* Deallocate stack frame early; return value is now in redzone. */ addq $ffi_closure_FS, %rsp @@ -307,6 +313,11 @@ L(UW10): movzbl %al, %r10d leaq L(load_table)(%rip), %r11 ja L(la) +#ifdef __CET__ + /* NB: Originally, each slot is 8 byte. 4 bytes of ENDBR64 + + 4 bytes NOP padding double slot size to 16 bytes. */ + addl %r10d, %r10d +#endif leaq (%r11, %r10, 8), %r10 leaq ffi_closure_RED_RVALUE(%rsp), %rsi jmp *%r10 @@ -314,51 +325,67 @@ L(UW10): .balign 8 L(load_table): E(L(load_table), UNIX64_RET_VOID) + _CET_ENDBR ret E(L(load_table), UNIX64_RET_UINT8) + _CET_ENDBR movzbl (%rsi), %eax ret E(L(load_table), UNIX64_RET_UINT16) + _CET_ENDBR movzwl (%rsi), %eax ret E(L(load_table), UNIX64_RET_UINT32) + _CET_ENDBR movl (%rsi), %eax ret E(L(load_table), UNIX64_RET_SINT8) + _CET_ENDBR movsbl (%rsi), %eax ret E(L(load_table), UNIX64_RET_SINT16) + _CET_ENDBR movswl (%rsi), %eax ret E(L(load_table), UNIX64_RET_SINT32) + _CET_ENDBR movl (%rsi), %eax ret E(L(load_table), UNIX64_RET_INT64) + _CET_ENDBR movq (%rsi), %rax ret E(L(load_table), UNIX64_RET_XMM32) + _CET_ENDBR movd (%rsi), %xmm0 ret E(L(load_table), UNIX64_RET_XMM64) + _CET_ENDBR movq (%rsi), %xmm0 ret E(L(load_table), UNIX64_RET_X87) + _CET_ENDBR fldt (%rsi) ret E(L(load_table), UNIX64_RET_X87_2) + _CET_ENDBR fldt 16(%rsi) fldt (%rsi) ret E(L(load_table), UNIX64_RET_ST_XMM0_RAX) + _CET_ENDBR movq 8(%rsi), %rax jmp L(l3) E(L(load_table), UNIX64_RET_ST_RAX_XMM0) + _CET_ENDBR movq 8(%rsi), %xmm0 jmp L(l2) E(L(load_table), UNIX64_RET_ST_XMM0_XMM1) + _CET_ENDBR movq 8(%rsi), %xmm1 jmp L(l3) E(L(load_table), UNIX64_RET_ST_RAX_RDX) + _CET_ENDBR movq 8(%rsi), %rdx L(l2): movq (%rsi), %rax @@ -379,6 +406,7 @@ ENDF(C(ffi_closure_unix64)) C(ffi_go_closure_unix64_sse): L(UW12): + _CET_ENDBR subq $ffi_closure_FS, %rsp L(UW13): /* cfi_adjust_cfa_offset(ffi_closure_FS) */ @@ -402,6 +430,7 @@ ENDF(C(ffi_go_closure_unix64_sse)) C(ffi_go_closure_unix64): L(UW15): + _CET_ENDBR subq $ffi_closure_FS, %rsp L(UW16): /* cfi_adjust_cfa_offset(ffi_closure_FS) */ @@ -427,6 +456,81 @@ L(sse_entry2): L(UW17): ENDF(C(ffi_go_closure_unix64)) +#if defined(FFI_EXEC_STATIC_TRAMP) + .balign 8 + .globl C(ffi_closure_unix64_sse_alt) + FFI_HIDDEN(C(ffi_closure_unix64_sse_alt)) + +C(ffi_closure_unix64_sse_alt): + /* See the comments above trampoline_code_table. */ + _CET_ENDBR + movq 8(%rsp), %r10 /* Load closure in r10 */ + addq $16, %rsp /* Restore the stack */ + jmp C(ffi_closure_unix64_sse) +ENDF(C(ffi_closure_unix64_sse_alt)) + + .balign 8 + .globl C(ffi_closure_unix64_alt) + FFI_HIDDEN(C(ffi_closure_unix64_alt)) + +C(ffi_closure_unix64_alt): + /* See the comments above trampoline_code_table. */ + _CET_ENDBR + movq 8(%rsp), %r10 /* Load closure in r10 */ + addq $16, %rsp /* Restore the stack */ + jmp C(ffi_closure_unix64) + ENDF(C(ffi_closure_unix64_alt)) + +/* + * Below is the definition of the trampoline code table. Each element in + * the code table is a trampoline. + * + * Because we jump to the trampoline, we place a _CET_ENDBR at the + * beginning of the trampoline to mark it as a valid branch target. This is + * part of the the Intel CET (Control Flow Enforcement Technology). + */ +/* + * The trampoline uses register r10. It saves the original value of r10 on + * the stack. + * + * The trampoline has two parameters - target code to jump to and data for + * the target code. The trampoline extracts the parameters from its parameter + * block (see tramp_table_map()). The trampoline saves the data address on + * the stack. Finally, it jumps to the target code. + * + * The target code can choose to: + * + * - restore the value of r10 + * - load the data address in a register + * - restore the stack pointer to what it was when the trampoline was invoked. + */ +#ifdef ENDBR_PRESENT +#define X86_DATA_OFFSET 4077 +#define X86_CODE_OFFSET 4073 +#else +#define X86_DATA_OFFSET 4081 +#define X86_CODE_OFFSET 4077 +#endif + + .align UNIX64_TRAMP_MAP_SIZE + .globl trampoline_code_table + FFI_HIDDEN(C(trampoline_code_table)) + +C(trampoline_code_table): + .rept UNIX64_TRAMP_MAP_SIZE / UNIX64_TRAMP_SIZE + _CET_ENDBR + subq $16, %rsp /* Make space on the stack */ + movq %r10, (%rsp) /* Save %r10 on stack */ + movq X86_DATA_OFFSET(%rip), %r10 /* Copy data into %r10 */ + movq %r10, 8(%rsp) /* Save data on stack */ + movq X86_CODE_OFFSET(%rip), %r10 /* Copy code into %r10 */ + jmp *%r10 /* Jump to code */ + .align 8 + .endr +ENDF(C(trampoline_code_table)) + .align UNIX64_TRAMP_MAP_SIZE +#endif /* FFI_EXEC_STATIC_TRAMP */ + /* Sadly, OSX cctools-as doesn't understand .cfi directives at all. */ #ifdef __APPLE__ @@ -445,7 +549,12 @@ EHFrame0: #endif /* Simplify advancing between labels. Assume DW_CFA_advance_loc1 fits. */ -#define ADV(N, P) .byte 2, L(N)-L(P) +#ifdef __CET__ +/* Use DW_CFA_advance_loc2 when IBT is enabled. */ +# define ADV(N, P) .byte 3; .2byte L(N)-L(P) +#else +# define ADV(N, P) .byte 2, L(N)-L(P) +#endif .balign 8 L(CIE): @@ -538,6 +647,47 @@ L(SFDE5): L(EFDE5): #ifdef __APPLE__ .subsections_via_symbols + .section __LD,__compact_unwind,regular,debug + + /* compact unwind for ffi_call_unix64 */ + .quad C(ffi_call_unix64) + .set L1,L(UW4)-L(UW0) + .long L1 + .long 0x04000000 /* use dwarf unwind info */ + .quad 0 + .quad 0 + + /* compact unwind for ffi_closure_unix64_sse */ + .quad C(ffi_closure_unix64_sse) + .set L2,L(UW7)-L(UW5) + .long L2 + .long 0x04000000 /* use dwarf unwind info */ + .quad 0 + .quad 0 + + /* compact unwind for ffi_closure_unix64 */ + .quad C(ffi_closure_unix64) + .set L3,L(UW11)-L(UW8) + .long L3 + .long 0x04000000 /* use dwarf unwind info */ + .quad 0 + .quad 0 + + /* compact unwind for ffi_go_closure_unix64_sse */ + .quad C(ffi_go_closure_unix64_sse) + .set L4,L(UW14)-L(UW12) + .long L4 + .long 0x04000000 /* use dwarf unwind info */ + .quad 0 + .quad 0 + + /* compact unwind for ffi_go_closure_unix64 */ + .quad C(ffi_go_closure_unix64) + .set L5,L(UW17)-L(UW15) + .long L5 + .long 0x04000000 /* use dwarf unwind info */ + .quad 0 + .quad 0 #endif #endif /* __x86_64__ */ diff --git a/libffi/src/x86/win64.S b/libffi/src/x86/win64.S index a5a20b6..f3ace8d 100644 --- a/libffi/src/x86/win64.S +++ b/libffi/src/x86/win64.S @@ -1,27 +1,37 @@ +#ifdef __x86_64__ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> #include <ffi_cfi.h> +#include "asmnames.h" #if defined(HAVE_AS_CFI_PSEUDO_OP) .cfi_sections .debug_frame #endif +#ifdef X86_WIN64 +#define SEH(...) __VA_ARGS__ #define arg0 %rcx #define arg1 %rdx #define arg2 %r8 #define arg3 %r9 - -#ifdef SYMBOL_UNDERSCORE -#define SYMBOL_NAME(name) _##name #else -#define SYMBOL_NAME(name) name +#define SEH(...) +#define arg0 %rdi +#define arg1 %rsi +#define arg2 %rdx +#define arg3 %rcx #endif -.macro E which - .align 8 - .org 0b + \which * 8 -.endm +/* This macro allows the safe creation of jump tables without an + actual table. The entry points into the table are all 8 bytes. + The use of ORG asserts that we're at the correct location. */ +/* ??? The clang assembler doesn't handle .org with symbolic expressions. */ +#if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__)) +# define E(BASE, X) .balign 8 +#else +# define E(BASE, X) .balign 8; .org BASE + (X) * 8 +#endif .text @@ -32,11 +42,13 @@ deallocate some of the stack that has been alloca'd. */ .align 8 - .globl ffi_call_win64 + .globl C(ffi_call_win64) + FFI_HIDDEN(C(ffi_call_win64)) - .seh_proc ffi_call_win64 -ffi_call_win64: + SEH(.seh_proc ffi_call_win64) +C(ffi_call_win64): cfi_startproc + _CET_ENDBR /* Set up the local stack frame and install it in rbp/rsp. */ movq (%rsp), %rax movq %rbp, (arg1) @@ -44,9 +56,9 @@ ffi_call_win64: movq arg1, %rbp cfi_def_cfa(%rbp, 16) cfi_rel_offset(%rbp, 0) - .seh_pushreg %rbp - .seh_setframe %rbp, 0 - .seh_endprologue + SEH(.seh_pushreg %rbp) + SEH(.seh_setframe %rbp, 0) + SEH(.seh_endprologue) movq arg0, %rsp movq arg2, %r10 @@ -69,7 +81,7 @@ ffi_call_win64: cmpl $FFI_TYPE_SMALL_STRUCT_4B, %ecx leaq (%r10, %rcx, 8), %r10 ja 99f - jmp *%r10 + _CET_NOTRACK jmp *%r10 /* Below, we're space constrained most of the time. Thus we eschew the modern "mov, pop, ret" sequence (5 bytes) for "leave, ret" (2 bytes). */ @@ -84,72 +96,73 @@ ffi_call_win64: .align 8 0: -E FFI_TYPE_VOID +E(0b, FFI_TYPE_VOID) epilogue -E FFI_TYPE_INT +E(0b, FFI_TYPE_INT) movslq %eax, %rax movq %rax, (%r8) epilogue -E FFI_TYPE_FLOAT +E(0b, FFI_TYPE_FLOAT) movss %xmm0, (%r8) epilogue -E FFI_TYPE_DOUBLE +E(0b, FFI_TYPE_DOUBLE) movsd %xmm0, (%r8) epilogue -E FFI_TYPE_LONGDOUBLE - call abort -E FFI_TYPE_UINT8 +// FFI_TYPE_LONGDOUBLE may be FFI_TYPE_DOUBLE but we need a different value here. +E(0b, FFI_TYPE_DOUBLE + 1) + call PLT(C(abort)) +E(0b, FFI_TYPE_UINT8) movzbl %al, %eax movq %rax, (%r8) epilogue -E FFI_TYPE_SINT8 +E(0b, FFI_TYPE_SINT8) movsbq %al, %rax jmp 98f -E FFI_TYPE_UINT16 +E(0b, FFI_TYPE_UINT16) movzwl %ax, %eax movq %rax, (%r8) epilogue -E FFI_TYPE_SINT16 +E(0b, FFI_TYPE_SINT16) movswq %ax, %rax jmp 98f -E FFI_TYPE_UINT32 +E(0b, FFI_TYPE_UINT32) movl %eax, %eax movq %rax, (%r8) epilogue -E FFI_TYPE_SINT32 +E(0b, FFI_TYPE_SINT32) movslq %eax, %rax movq %rax, (%r8) epilogue -E FFI_TYPE_UINT64 +E(0b, FFI_TYPE_UINT64) 98: movq %rax, (%r8) epilogue -E FFI_TYPE_SINT64 +E(0b, FFI_TYPE_SINT64) movq %rax, (%r8) epilogue -E FFI_TYPE_STRUCT +E(0b, FFI_TYPE_STRUCT) epilogue -E FFI_TYPE_POINTER +E(0b, FFI_TYPE_POINTER) movq %rax, (%r8) epilogue -E FFI_TYPE_COMPLEX - call abort -E FFI_TYPE_SMALL_STRUCT_1B +E(0b, FFI_TYPE_COMPLEX) + call PLT(C(abort)) +E(0b, FFI_TYPE_SMALL_STRUCT_1B) movb %al, (%r8) epilogue -E FFI_TYPE_SMALL_STRUCT_2B +E(0b, FFI_TYPE_SMALL_STRUCT_2B) movw %ax, (%r8) epilogue -E FFI_TYPE_SMALL_STRUCT_4B +E(0b, FFI_TYPE_SMALL_STRUCT_4B) movl %eax, (%r8) epilogue .align 8 -99: call abort +99: call PLT(C(abort)) -.purgem epilogue + epilogue cfi_endproc - .seh_endproc + SEH(.seh_endproc) /* 32 bytes of outgoing register stack space, 8 bytes of alignment, @@ -159,44 +172,48 @@ E FFI_TYPE_SMALL_STRUCT_4B #define ffi_clo_OFF_X (32+8+16) .align 8 - .globl ffi_go_closure_win64 + .globl C(ffi_go_closure_win64) + FFI_HIDDEN(C(ffi_go_closure_win64)) - .seh_proc ffi_go_closure_win64 -ffi_go_closure_win64: + SEH(.seh_proc ffi_go_closure_win64) +C(ffi_go_closure_win64): cfi_startproc + _CET_ENDBR /* Save all integer arguments into the incoming reg stack space. */ - movq arg0, 8(%rsp) - movq arg1, 16(%rsp) - movq arg2, 24(%rsp) - movq arg3, 32(%rsp) - - movq 8(%r10), arg0 /* load cif */ - movq 16(%r10), arg1 /* load fun */ - movq %r10, arg2 /* closure is user_data */ + movq %rcx, 8(%rsp) + movq %rdx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) + + movq 8(%r10), %rcx /* load cif */ + movq 16(%r10), %rdx /* load fun */ + movq %r10, %r8 /* closure is user_data */ jmp 0f cfi_endproc - .seh_endproc + SEH(.seh_endproc) .align 8 - .globl ffi_closure_win64 + .globl C(ffi_closure_win64) + FFI_HIDDEN(C(ffi_closure_win64)) - .seh_proc ffi_closure_win64 -ffi_closure_win64: + SEH(.seh_proc ffi_closure_win64) +C(ffi_closure_win64): cfi_startproc + _CET_ENDBR /* Save all integer arguments into the incoming reg stack space. */ - movq arg0, 8(%rsp) - movq arg1, 16(%rsp) - movq arg2, 24(%rsp) - movq arg3, 32(%rsp) - - movq FFI_TRAMPOLINE_SIZE(%r10), arg0 /* load cif */ - movq FFI_TRAMPOLINE_SIZE+8(%r10), arg1 /* load fun */ - movq FFI_TRAMPOLINE_SIZE+16(%r10), arg2 /* load user_data */ + movq %rcx, 8(%rsp) + movq %rdx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) + + movq FFI_TRAMPOLINE_SIZE(%r10), %rcx /* load cif */ + movq FFI_TRAMPOLINE_SIZE+8(%r10), %rdx /* load fun */ + movq FFI_TRAMPOLINE_SIZE+16(%r10), %r8 /* load user_data */ 0: subq $ffi_clo_FS, %rsp cfi_adjust_cfa_offset(ffi_clo_FS) - .seh_stackalloc ffi_clo_FS - .seh_endprologue + SEH(.seh_stackalloc ffi_clo_FS) + SEH(.seh_endprologue) /* Save all sse arguments into the stack frame. */ movsd %xmm0, ffi_clo_OFF_X(%rsp) @@ -204,8 +221,8 @@ ffi_closure_win64: movsd %xmm2, ffi_clo_OFF_X+16(%rsp) movsd %xmm3, ffi_clo_OFF_X+24(%rsp) - leaq ffi_clo_OFF_R(%rsp), arg3 - call ffi_closure_win64_inner + leaq ffi_clo_OFF_R(%rsp), %r9 + call PLT(C(ffi_closure_win64_inner)) /* Load the result into both possible result registers. */ movq ffi_clo_OFF_R(%rsp), %rax @@ -216,4 +233,23 @@ ffi_closure_win64: ret cfi_endproc - .seh_endproc + SEH(.seh_endproc) + +#if defined(FFI_EXEC_STATIC_TRAMP) + .align 8 + .globl C(ffi_closure_win64_alt) + FFI_HIDDEN(C(ffi_closure_win64_alt)) + + SEH(.seh_proc ffi_closure_win64_alt) +C(ffi_closure_win64_alt): + _CET_ENDBR + movq 8(%rsp), %r10 + addq $16, %rsp + jmp C(ffi_closure_win64) + SEH(.seh_endproc) +#endif +#endif /* __x86_64__ */ + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/libffi/src/x86/win64_intel.S b/libffi/src/x86/win64_intel.S new file mode 100644 index 0000000..970a4f9 --- /dev/null +++ b/libffi/src/x86/win64_intel.S @@ -0,0 +1,238 @@ +#define LIBFFI_ASM +#include <fficonfig.h> +#include <ffi.h> +#include <ffi_cfi.h> +#include "asmnames.h" + +#if defined(HAVE_AS_CFI_PSEUDO_OP) + .cfi_sections .debug_frame +#endif + +#ifdef X86_WIN64 +#define SEH(...) __VA_ARGS__ +#define arg0 rcx +#define arg1 rdx +#define arg2 r8 +#define arg3 r9 +#else +#define SEH(...) +#define arg0 rdi +#define arg1 rsi +#define arg2 rdx +#define arg3 rcx +#endif + +/* This macro allows the safe creation of jump tables without an + actual table. The entry points into the table are all 8 bytes. + The use of ORG asserts that we're at the correct location. */ +/* ??? The clang assembler doesn't handle .org with symbolic expressions. */ +#if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__)) +# define E(BASE, X) ALIGN 8 +#else +# define E(BASE, X) ALIGN 8; ORG BASE + (X) * 8 +#endif + + .CODE + extern PLT(C(abort)):near + extern C(ffi_closure_win64_inner):near + +/* ffi_call_win64 (void *stack, struct win64_call_frame *frame, void *r10) + + Bit o trickiness here -- FRAME is the base of the stack frame + for this function. This has been allocated by ffi_call. We also + deallocate some of the stack that has been alloca'd. */ + + ALIGN 8 + PUBLIC C(ffi_call_win64) + + ; SEH(.safesh ffi_call_win64) +C(ffi_call_win64) proc SEH(frame) + cfi_startproc + /* Set up the local stack frame and install it in rbp/rsp. */ + mov RAX, [RSP] ; movq (%rsp), %rax + mov [arg1], RBP ; movq %rbp, (arg1) + mov [arg1 + 8], RAX; movq %rax, 8(arg1) + mov RBP, arg1; movq arg1, %rbp + cfi_def_cfa(rbp, 16) + cfi_rel_offset(rbp, 0) + SEH(.pushreg rbp) + SEH(.setframe rbp, 0) + SEH(.endprolog) + mov RSP, arg0 ; movq arg0, %rsp + + mov R10, arg2 ; movq arg2, %r10 + + /* Load all slots into both general and xmm registers. */ + mov RCX, [RSP] ; movq (%rsp), %rcx + movsd XMM0, qword ptr [RSP] ; movsd (%rsp), %xmm0 + mov RDX, [RSP + 8] ;movq 8(%rsp), %rdx + movsd XMM1, qword ptr [RSP + 8]; movsd 8(%rsp), %xmm1 + mov R8, [RSP + 16] ; movq 16(%rsp), %r8 + movsd XMM2, qword ptr [RSP + 16] ; movsd 16(%rsp), %xmm2 + mov R9, [RSP + 24] ; movq 24(%rsp), %r9 + movsd XMM3, qword ptr [RSP + 24] ;movsd 24(%rsp), %xmm3 + + CALL qword ptr [RBP + 16] ; call *16(%rbp) + + mov ECX, [RBP + 24] ; movl 24(%rbp), %ecx + mov R8, [RBP + 32] ; movq 32(%rbp), %r8 + LEA R10, ffi_call_win64_tab ; leaq 0f(%rip), %r10 + CMP ECX, FFI_TYPE_SMALL_STRUCT_4B ; cmpl $FFI_TYPE_SMALL_STRUCT_4B, %ecx + LEA R10, [R10 + RCX*8] ; leaq (%r10, %rcx, 8), %r10 + JA L99 ; ja 99f + JMP R10 ; jmp *%r10 + +/* Below, we're space constrained most of the time. Thus we eschew the + modern "mov, pop, ret" sequence (5 bytes) for "leave, ret" (2 bytes). */ +epilogue macro + LEAVE + cfi_remember_state + cfi_def_cfa(rsp, 8) + cfi_restore(rbp) + RET + cfi_restore_state +endm + + ALIGN 8 +ffi_call_win64_tab LABEL NEAR +E(0b, FFI_TYPE_VOID) + epilogue +E(0b, FFI_TYPE_INT) + movsxd rax, eax ; movslq %eax, %rax + mov qword ptr [r8], rax; movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_FLOAT) + movss dword ptr [r8], xmm0 ; movss %xmm0, (%r8) + epilogue +E(0b, FFI_TYPE_DOUBLE) + movsd qword ptr[r8], xmm0; movsd %xmm0, (%r8) + epilogue +// FFI_TYPE_LONGDOUBLE may be FFI_TYPE_DOUBLE but we need a different value here. +E(0b, FFI_TYPE_DOUBLE + 1) + call PLT(C(abort)) +E(0b, FFI_TYPE_UINT8) + movzx eax, al ;movzbl %al, %eax + mov qword ptr[r8], rax; movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_SINT8) + movsx rax, al ; movsbq %al, %rax + jmp L98 +E(0b, FFI_TYPE_UINT16) + movzx eax, ax ; movzwl %ax, %eax + mov qword ptr[r8], rax; movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_SINT16) + movsx rax, ax; movswq %ax, %rax + jmp L98 +E(0b, FFI_TYPE_UINT32) + mov eax, eax; movl %eax, %eax + mov qword ptr[r8], rax ; movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_SINT32) + movsxd rax, eax; movslq %eax, %rax + mov qword ptr [r8], rax; movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_UINT64) +L98 LABEL near + mov qword ptr [r8], rax ; movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_SINT64) + mov qword ptr [r8], rax;movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_STRUCT) + epilogue +E(0b, FFI_TYPE_POINTER) + mov qword ptr [r8], rax ;movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_COMPLEX) + call PLT(C(abort)) +E(0b, FFI_TYPE_SMALL_STRUCT_1B) + mov byte ptr [r8], al ; movb %al, (%r8) + epilogue +E(0b, FFI_TYPE_SMALL_STRUCT_2B) + mov word ptr [r8], ax ; movw %ax, (%r8) + epilogue +E(0b, FFI_TYPE_SMALL_STRUCT_4B) + mov dword ptr [r8], eax ; movl %eax, (%r8) + epilogue + + align 8 +L99 LABEL near + call PLT(C(abort)) + + epilogue + + cfi_endproc + C(ffi_call_win64) endp + + +/* 32 bytes of outgoing register stack space, 8 bytes of alignment, + 16 bytes of result, 32 bytes of xmm registers. */ +#define ffi_clo_FS (32+8+16+32) +#define ffi_clo_OFF_R (32+8) +#define ffi_clo_OFF_X (32+8+16) + + align 8 + PUBLIC C(ffi_go_closure_win64) + +C(ffi_go_closure_win64) proc + cfi_startproc + /* Save all integer arguments into the incoming reg stack space. */ + mov qword ptr [rsp + 8], rcx; movq %rcx, 8(%rsp) + mov qword ptr [rsp + 16], rdx; movq %rdx, 16(%rsp) + mov qword ptr [rsp + 24], r8; movq %r8, 24(%rsp) + mov qword ptr [rsp + 32], r9 ;movq %r9, 32(%rsp) + + mov rcx, qword ptr [r10 + 8]; movq 8(%r10), %rcx /* load cif */ + mov rdx, qword ptr [r10 + 16]; movq 16(%r10), %rdx /* load fun */ + mov r8, r10 ; movq %r10, %r8 /* closure is user_data */ + jmp ffi_closure_win64_2 + cfi_endproc + C(ffi_go_closure_win64) endp + + align 8 + +PUBLIC C(ffi_closure_win64) +C(ffi_closure_win64) PROC FRAME + cfi_startproc + /* Save all integer arguments into the incoming reg stack space. */ + mov qword ptr [rsp + 8], rcx; movq %rcx, 8(%rsp) + mov qword ptr [rsp + 16], rdx; movq %rdx, 16(%rsp) + mov qword ptr [rsp + 24], r8; movq %r8, 24(%rsp) + mov qword ptr [rsp + 32], r9; movq %r9, 32(%rsp) + + mov rcx, qword ptr [FFI_TRAMPOLINE_SIZE + r10] ;movq FFI_TRAMPOLINE_SIZE(%r10), %rcx /* load cif */ + mov rdx, qword ptr [FFI_TRAMPOLINE_SIZE + 8 + r10] ; movq FFI_TRAMPOLINE_SIZE+8(%r10), %rdx /* load fun */ + mov r8, qword ptr [FFI_TRAMPOLINE_SIZE+16+r10] ;movq FFI_TRAMPOLINE_SIZE+16(%r10), %r8 /* load user_data */ +ffi_closure_win64_2 LABEL near + sub rsp, ffi_clo_FS ;subq $ffi_clo_FS, %rsp + cfi_adjust_cfa_offset(ffi_clo_FS) + SEH(.allocstack ffi_clo_FS) + SEH(.endprolog) + + /* Save all sse arguments into the stack frame. */ + movsd qword ptr [ffi_clo_OFF_X + rsp], xmm0 ; movsd %xmm0, ffi_clo_OFF_X(%rsp) + movsd qword ptr [ffi_clo_OFF_X+8+rsp], xmm1 ; movsd %xmm1, ffi_clo_OFF_X+8(%rsp) + movsd qword ptr [ffi_clo_OFF_X+16+rsp], xmm2 ; movsd %xmm2, ffi_clo_OFF_X+16(%rsp) + movsd qword ptr [ffi_clo_OFF_X+24+rsp], xmm3 ; movsd %xmm3, ffi_clo_OFF_X+24(%rsp) + + lea r9, [ffi_clo_OFF_R + rsp] ; leaq ffi_clo_OFF_R(%rsp), %r9 + call C(ffi_closure_win64_inner) + + /* Load the result into both possible result registers. */ + + mov rax, qword ptr [ffi_clo_OFF_R + rsp] ;movq ffi_clo_OFF_R(%rsp), %rax + movsd xmm0, qword ptr [rsp + ffi_clo_OFF_R] ;movsd ffi_clo_OFF_R(%rsp), %xmm0 + + add rsp, ffi_clo_FS ;addq $ffi_clo_FS, %rsp + cfi_adjust_cfa_offset(-ffi_clo_FS) + ret + + cfi_endproc + C(ffi_closure_win64) endp + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",@progbits +#endif +_text ends +end
\ No newline at end of file diff --git a/libffi/src/xtensa/ffi.c b/libffi/src/xtensa/ffi.c index fd94daf..9a0575f 100644 --- a/libffi/src/xtensa/ffi.c +++ b/libffi/src/xtensa/ffi.c @@ -89,7 +89,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) /* Round the stack up to a full 4 register frame, just in case (we use this size in movsp). This way, it's also a multiple of 8 bytes for 64-bit arguments. */ - cif->bytes = ALIGN(cif->bytes, 16); + cif->bytes = FFI_ALIGN(cif->bytes, 16); return FFI_OK; } @@ -205,7 +205,7 @@ void ffi_call(ffi_cif* cif, void(*fn)(void), void *rvalue, void **avalue) if (flags == FFI_TYPE_STRUCT && (rsize <= 16 || rvalue == NULL)) { - alloc = alloca(ALIGN(rsize, 4)); + alloc = alloca(FFI_ALIGN(rsize, 4)); ecif.rvalue = alloc; } else diff --git a/libffi/src/xtensa/sysv.S b/libffi/src/xtensa/sysv.S index 64e6a09..e942179 100644 --- a/libffi/src/xtensa/sysv.S +++ b/libffi/src/xtensa/sysv.S @@ -169,8 +169,13 @@ ENTRY(ffi_cacheflush) entry a1, 16 -1: dhwbi a2, 0 +1: +#if XCHAL_DCACHE_SIZE + dhwbi a2, 0 +#endif +#if XCHAL_ICACHE_SIZE ihi a2, 0 +#endif addi a2, a2, 4 blt a2, a3, 1b diff --git a/libffi/testsuite/Makefile.am b/libffi/testsuite/Makefile.am index 88509fc..1e4b35a 100644 --- a/libffi/testsuite/Makefile.am +++ b/libffi/testsuite/Makefile.am @@ -2,95 +2,125 @@ AUTOMAKE_OPTIONS = foreign dejagnu -# Setup the testing framework, if you have one -EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \ - echo $(top_builddir)/../expect/expect ; \ - else echo expect ; fi` - -RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \ - echo $(top_srcdir)/../dejagnu/runtest ; \ - else echo runtest; fi` - -AM_RUNTESTFLAGS = - EXTRA_DEJAGNU_SITE_CONFIG=../local.exp CLEANFILES = *.exe core* *.log *.sum -EXTRA_DIST = config/default.exp libffi.call/cls_19byte.c \ -libffi.call/cls_align_longdouble_split.c \ -libffi.call/closure_loc_fn0.c libffi.call/cls_schar.c \ -libffi.call/closure_fn1.c \ -libffi.call/return_ul.c libffi.call/cls_align_double.c \ -libffi.call/return_fl2.c libffi.call/cls_1_1byte.c \ -libffi.call/cls_64byte.c libffi.call/nested_struct7.c \ -libffi.call/cls_align_sint32.c libffi.call/nested_struct2.c \ -libffi.call/ffitest.h libffi.call/nested_struct4.c \ -libffi.call/cls_multi_ushort.c libffi.call/struct3.c \ -libffi.call/cls_3byte1.c libffi.call/cls_16byte.c \ -libffi.call/struct8.c libffi.call/nested_struct8.c \ -libffi.call/cls_multi_sshort.c libffi.call/cls_3byte2.c \ -libffi.call/cls_pointer.c \ -libffi.call/err_bad_typedef.c libffi.call/cls_4_1byte.c \ -libffi.call/cls_9byte2.c libffi.call/cls_multi_schar.c \ -libffi.call/stret_medium2.c libffi.call/cls_5_1_byte.c \ -libffi.call/call.exp libffi.call/cls_double.c \ -libffi.call/cls_align_sint16.c libffi.call/cls_uint.c \ -libffi.call/return_ll1.c libffi.call/nested_struct3.c \ -libffi.call/cls_20byte1.c libffi.call/closure_fn4.c \ -libffi.call/cls_uchar.c libffi.call/struct2.c libffi.call/cls_7byte.c \ -libffi.call/strlen.c libffi.call/many.c libffi.call/testclosure.c \ -libffi.call/return_fl.c libffi.call/struct5.c \ -libffi.call/cls_12byte.c libffi.call/cls_multi_sshortchar.c \ -libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c \ -libffi.call/return_fl3.c libffi.call/stret_medium.c \ -libffi.call/nested_struct6.c libffi.call/closure_fn3.c \ -libffi.call/float3.c libffi.call/many2.c \ -libffi.call/closure_simple.c libffi.call/cls_align_uint16.c \ -libffi.call/cls_9byte1.c libffi.call/closure_fn6.c \ -libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c \ -libffi.call/cls_align_longdouble.c libffi.call/closure_fn2.c \ -libffi.call/cls_sshort.c \ -libffi.call/nested_struct.c libffi.call/cls_20byte.c \ -libffi.call/cls_longdouble.c libffi.call/cls_multi_uchar.c \ -libffi.call/return_uc.c \ -libffi.call/cls_18byte.c libffi.call/cls_8byte.c \ -libffi.call/promotion.c \ -libffi.call/return_dbl.c libffi.call/cls_24byte.c \ -libffi.call/struct4.c libffi.call/cls_6byte.c \ -libffi.call/cls_align_uint32.c libffi.call/float.c \ -libffi.call/float1.c libffi.call/float_va.c libffi.call/negint.c \ -libffi.call/return_dbl1.c libffi.call/cls_3_1byte.c \ -libffi.call/cls_align_float.c libffi.call/return_fl1.c \ -libffi.call/nested_struct10.c libffi.call/nested_struct5.c \ -libffi.call/cls_align_sint64.c \ -libffi.call/stret_large2.c libffi.call/return_sl.c \ -libffi.call/closure_fn0.c libffi.call/cls_5byte.c \ -libffi.call/cls_2byte.c libffi.call/float2.c \ -libffi.call/cls_dbls_struct.c libffi.call/cls_sint.c \ -libffi.call/stret_large.c libffi.call/cls_ulonglong.c \ -libffi.call/cls_ushort.c libffi.call/nested_struct1.c \ -libffi.call/err_bad_abi.c libffi.call/cls_longdouble_va.c \ -libffi.call/cls_float.c libffi.call/cls_pointer_stack.c \ -libffi.call/pyobjc-tc.c libffi.call/cls_multi_ushortchar.c \ -libffi.call/struct1.c libffi.call/nested_struct9.c \ -libffi.call/huge_struct.c libffi.call/problem1.c \ -libffi.call/float4.c \ -libffi.call/return_ldl.c \ -libffi.call/closure_fn5.c \ -libffi.call/struct6.c libffi.call/return_ll.c libffi.call/struct9.c \ -libffi.call/return_sc.c libffi.call/struct7.c \ -libffi.call/cls_align_uint64.c libffi.call/cls_4byte.c \ -libffi.call/cls_6_1_byte.c \ -libffi.call/cls_7_1_byte.c libffi.call/unwindtest.cc \ -libffi.call/unwindtest_ffi_call.cc \ -lib/wrapper.exp lib/target-libpath.exp \ -lib/libffi.exp libffi.call/cls_struct_va1.c \ -libffi.call/cls_uchar_va.c libffi.call/cls_uint_va.c \ -libffi.call/cls_ulong_va.c libffi.call/cls_ushort_va.c \ -libffi.call/nested_struct11.c libffi.call/uninitialized.c \ -libffi.call/va_1.c libffi.call/va_struct1.c libffi.call/va_struct2.c \ -libffi.call/va_struct3.c \ -libffi.call/strlen2.c \ -libffi.call/strlen3.c \ -libffi.call/strlen4.c +EXTRA_DIST = lib/target-libpath.exp lib/libffi.exp lib/wrapper.exp \ +libffi.call/strlen4.c libffi.call/struct10.c libffi.call/many_mixed.c \ +libffi.call/float.c libffi.call/struct5.c libffi.call/return_fl3.c \ +libffi.call/return_fl1.c libffi.call/call.exp libffi.call/pyobjc-tc.c \ +libffi.call/float_va.c libffi.call/struct8.c libffi.call/pr1172638.c \ +libffi.call/return_sc.c libffi.call/va_struct1.c \ +libffi.call/align_stdcall.c libffi.call/struct9.c libffi.call/va_1.c \ +libffi.call/va_2.c libffi.call/va_struct2.c libffi.call/return_fl2.c \ +libffi.call/align_mixed.c libffi.call/ffitest.h libffi.call/struct4.c \ +libffi.call/return_ldl.c libffi.call/float3.c libffi.call/return_sl.c \ +libffi.call/return_dbl1.c libffi.call/err_bad_typedef.c \ +libffi.call/return_ll1.c libffi.call/return_dbl2.c \ +libffi.call/negint.c libffi.closures/nested_struct3.c \ +libffi.call/struct2.c libffi.call/struct3.c libffi.call/return_fl.c \ +libffi.call/offsets.c libffi.call/struct7.c libffi.call/va_struct3.c \ +libffi.call/float1.c libffi.call/uninitialized.c libffi.call/many2.c \ +libffi.call/struct6.c libffi.call/strlen2.c libffi.call/float2.c \ +libffi.call/return_ul.c libffi.call/struct1.c libffi.call/strlen3.c \ +libffi.call/return_dbl.c libffi.call/float4.c libffi.call/many.c \ +libffi.call/strlen.c libffi.call/return_uc.c libffi.call/many_double.c \ +libffi.call/return_ll.c libffi.call/promotion.c \ +libffi.complex/complex_defs_longdouble.inc \ +libffi.complex/cls_align_complex_float.c \ +libffi.complex/cls_complex_va_float.c \ +libffi.complex/cls_complex_struct_float.c \ +libffi.complex/return_complex2_longdouble.c \ +libffi.complex/cls_complex_float.c \ +libffi.complex/return_complex_longdouble.c \ +libffi.complex/return_complex2_float.c libffi.complex/cls_complex.inc \ +libffi.complex/cls_complex_va_longdouble.c \ +libffi.complex/return_complex_double.c \ +libffi.complex/return_complex.inc libffi.complex/many_complex.inc \ +libffi.complex/complex_float.c libffi.complex/cls_align_complex.inc \ +libffi.complex/return_complex2_double.c \ +libffi.complex/many_complex_float.c libffi.complex/ffitest.h \ +libffi.complex/return_complex1_double.c \ +libffi.complex/cls_complex_struct_longdouble.c \ +libffi.complex/complex_defs_double.inc \ +libffi.complex/cls_complex_va_double.c \ +libffi.complex/many_complex_double.c \ +libffi.complex/return_complex2.inc \ +libffi.complex/return_complex1_float.c \ +libffi.complex/complex_longdouble.c \ +libffi.complex/complex_defs_float.inc \ +libffi.complex/cls_complex_double.c \ +libffi.complex/cls_align_complex_double.c \ +libffi.complex/cls_align_complex_longdouble.c \ +libffi.complex/complex_double.c libffi.complex/cls_complex_va.inc \ +libffi.complex/many_complex_longdouble.c libffi.complex/complex.inc \ +libffi.complex/return_complex1_longdouble.c \ +libffi.complex/complex_int.c libffi.complex/cls_complex_longdouble.c \ +libffi.complex/cls_complex_struct_double.c \ +libffi.complex/return_complex1.inc libffi.complex/complex.exp \ +libffi.complex/cls_complex_struct.inc \ +libffi.complex/return_complex_float.c libffi.go/closure1.c \ +libffi.go/aa-direct.c libffi.go/ffitest.h libffi.go/go.exp \ +libffi.go/static-chain.h libffi.bhaible/bhaible.exp \ +libffi.bhaible/test-call.c libffi.bhaible/alignof.h \ +libffi.bhaible/testcases.c libffi.bhaible/test-callback.c \ +libffi.bhaible/Makefile libffi.bhaible/README config/default.exp \ +libffi.closures/cls_multi_sshort.c \ +libffi.closures/cls_align_longdouble_split2.c \ +libffi.closures/cls_1_1byte.c libffi.closures/cls_uint_va.c \ +libffi.closures/cls_3_1byte.c libffi.closures/cls_many_mixed_args.c \ +libffi.closures/cls_20byte1.c libffi.closures/cls_pointer_stack.c \ +libffi.closures/cls_align_float.c libffi.closures/cls_5_1_byte.c \ +libffi.closures/cls_9byte1.c libffi.closures/cls_align_uint32.c \ +libffi.closures/stret_medium.c libffi.closures/cls_3byte1.c \ +libffi.closures/cls_align_uint64.c libffi.closures/cls_longdouble_va.c \ +libffi.closures/cls_align_pointer.c libffi.closures/cls_19byte.c \ +libffi.closures/cls_ushort.c libffi.closures/cls_align_sint32.c \ +libffi.closures/cls_ulonglong.c libffi.closures/cls_struct_va1.c \ +libffi.closures/cls_9byte2.c libffi.closures/closure_fn5.c \ +libffi.closures/cls_5byte.c libffi.closures/cls_3float.c \ +libffi.closures/closure.exp libffi.closures/cls_schar.c \ +libffi.closures/closure_fn4.c \ +libffi.closures/closure_fn0.c libffi.closures/huge_struct.c \ +libffi.closures/cls_64byte.c libffi.closures/cls_longdouble.c \ +libffi.closures/cls_ulong_va.c libffi.closures/cls_6_1_byte.c \ +libffi.closures/cls_align_uint16.c libffi.closures/closure_fn2.c \ +libffi.closures/unwindtest_ffi_call.cc \ +libffi.closures/cls_multi_ushortchar.c libffi.closures/cls_8byte.c \ +libffi.closures/ffitest.h libffi.closures/nested_struct8.c \ +libffi.closures/cls_pointer.c libffi.closures/nested_struct2.c \ +libffi.closures/nested_struct.c libffi.closures/cls_multi_schar.c \ +libffi.closures/cls_align_longdouble_split.c \ +libffi.closures/cls_uchar.c libffi.closures/nested_struct9.c \ +libffi.closures/cls_float.c libffi.closures/stret_medium2.c \ +libffi.closures/closure_loc_fn0.c libffi.closures/cls_6byte.c \ +libffi.closures/closure_simple.c libffi.closures/cls_align_double.c \ +libffi.closures/cls_multi_uchar.c libffi.closures/cls_4_1byte.c \ +libffi.closures/closure_fn3.c libffi.closures/cls_align_sint64.c \ +libffi.closures/nested_struct1.c libffi.closures/unwindtest.cc \ +libffi.closures/nested_struct5.c libffi.closures/cls_multi_ushort.c \ +libffi.closures/nested_struct11.c \ +libffi.closures/nested_struct12.c \ +libffi.closures/nested_struct13.c \ +libffi.closures/cls_multi_sshortchar.c \ +libffi.closures/cls_align_longdouble.c \ +libffi.closures/cls_dbls_struct.c \ +libffi.closures/cls_many_mixed_float_double.c \ +libffi.closures/stret_large.c libffi.closures/stret_large2.c \ +libffi.closures/cls_align_sint16.c libffi.closures/cls_2byte.c \ +libffi.closures/nested_struct4.c libffi.closures/problem1.c \ +libffi.closures/testclosure.c libffi.closures/nested_struct6.c \ +libffi.closures/cls_4byte.c libffi.closures/cls_24byte.c \ +libffi.closures/nested_struct10.c libffi.closures/cls_uint.c \ +libffi.closures/cls_12byte.c libffi.closures/cls_sint.c \ +libffi.closures/cls_7_1_byte.c libffi.closures/cls_sshort.c \ +libffi.closures/cls_16byte.c libffi.closures/nested_struct7.c \ +libffi.closures/cls_double_va.c libffi.closures/cls_3byte2.c \ +libffi.closures/cls_double.c libffi.closures/cls_7byte.c \ +libffi.closures/closure_fn6.c libffi.closures/closure_fn1.c \ +libffi.closures/cls_20byte.c libffi.closures/cls_18byte.c \ +libffi.closures/err_bad_abi.c \ +libffi.closures/single_entry_structs1.c \ +libffi.closures/single_entry_structs2.c \ +libffi.closures/single_entry_structs3.c diff --git a/libffi/testsuite/Makefile.in b/libffi/testsuite/Makefile.in index 8b574da..3e9e937 100644 --- a/libffi/testsuite/Makefile.in +++ b/libffi/testsuite/Makefile.in @@ -129,12 +129,14 @@ am__can_run_installinfo = \ am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DEJATOOL = $(PACKAGE) RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir +EXPECT = expect +RUNTEST = runtest ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LTLDFLAGS = @AM_LTLDFLAGS@ -AM_RUNTESTFLAGS = +AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -199,6 +201,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ +READELF = @READELF@ SECTION_LDFLAGS = @SECTION_LDFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -269,95 +272,126 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign dejagnu - -# Setup the testing framework, if you have one -EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \ - echo $(top_builddir)/../expect/expect ; \ - else echo expect ; fi` - -RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \ - echo $(top_srcdir)/../dejagnu/runtest ; \ - else echo runtest; fi` - EXTRA_DEJAGNU_SITE_CONFIG = ../local.exp CLEANFILES = *.exe core* *.log *.sum -EXTRA_DIST = config/default.exp libffi.call/cls_19byte.c \ -libffi.call/cls_align_longdouble_split.c \ -libffi.call/closure_loc_fn0.c libffi.call/cls_schar.c \ -libffi.call/closure_fn1.c \ -libffi.call/return_ul.c libffi.call/cls_align_double.c \ -libffi.call/return_fl2.c libffi.call/cls_1_1byte.c \ -libffi.call/cls_64byte.c libffi.call/nested_struct7.c \ -libffi.call/cls_align_sint32.c libffi.call/nested_struct2.c \ -libffi.call/ffitest.h libffi.call/nested_struct4.c \ -libffi.call/cls_multi_ushort.c libffi.call/struct3.c \ -libffi.call/cls_3byte1.c libffi.call/cls_16byte.c \ -libffi.call/struct8.c libffi.call/nested_struct8.c \ -libffi.call/cls_multi_sshort.c libffi.call/cls_3byte2.c \ -libffi.call/cls_pointer.c \ -libffi.call/err_bad_typedef.c libffi.call/cls_4_1byte.c \ -libffi.call/cls_9byte2.c libffi.call/cls_multi_schar.c \ -libffi.call/stret_medium2.c libffi.call/cls_5_1_byte.c \ -libffi.call/call.exp libffi.call/cls_double.c \ -libffi.call/cls_align_sint16.c libffi.call/cls_uint.c \ -libffi.call/return_ll1.c libffi.call/nested_struct3.c \ -libffi.call/cls_20byte1.c libffi.call/closure_fn4.c \ -libffi.call/cls_uchar.c libffi.call/struct2.c libffi.call/cls_7byte.c \ -libffi.call/strlen.c libffi.call/many.c libffi.call/testclosure.c \ -libffi.call/return_fl.c libffi.call/struct5.c \ -libffi.call/cls_12byte.c libffi.call/cls_multi_sshortchar.c \ -libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c \ -libffi.call/return_fl3.c libffi.call/stret_medium.c \ -libffi.call/nested_struct6.c libffi.call/closure_fn3.c \ -libffi.call/float3.c libffi.call/many2.c \ -libffi.call/closure_simple.c libffi.call/cls_align_uint16.c \ -libffi.call/cls_9byte1.c libffi.call/closure_fn6.c \ -libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c \ -libffi.call/cls_align_longdouble.c libffi.call/closure_fn2.c \ -libffi.call/cls_sshort.c \ -libffi.call/nested_struct.c libffi.call/cls_20byte.c \ -libffi.call/cls_longdouble.c libffi.call/cls_multi_uchar.c \ -libffi.call/return_uc.c \ -libffi.call/cls_18byte.c libffi.call/cls_8byte.c \ -libffi.call/promotion.c \ -libffi.call/return_dbl.c libffi.call/cls_24byte.c \ -libffi.call/struct4.c libffi.call/cls_6byte.c \ -libffi.call/cls_align_uint32.c libffi.call/float.c \ -libffi.call/float1.c libffi.call/float_va.c libffi.call/negint.c \ -libffi.call/return_dbl1.c libffi.call/cls_3_1byte.c \ -libffi.call/cls_align_float.c libffi.call/return_fl1.c \ -libffi.call/nested_struct10.c libffi.call/nested_struct5.c \ -libffi.call/cls_align_sint64.c \ -libffi.call/stret_large2.c libffi.call/return_sl.c \ -libffi.call/closure_fn0.c libffi.call/cls_5byte.c \ -libffi.call/cls_2byte.c libffi.call/float2.c \ -libffi.call/cls_dbls_struct.c libffi.call/cls_sint.c \ -libffi.call/stret_large.c libffi.call/cls_ulonglong.c \ -libffi.call/cls_ushort.c libffi.call/nested_struct1.c \ -libffi.call/err_bad_abi.c libffi.call/cls_longdouble_va.c \ -libffi.call/cls_float.c libffi.call/cls_pointer_stack.c \ -libffi.call/pyobjc-tc.c libffi.call/cls_multi_ushortchar.c \ -libffi.call/struct1.c libffi.call/nested_struct9.c \ -libffi.call/huge_struct.c libffi.call/problem1.c \ -libffi.call/float4.c \ -libffi.call/return_ldl.c \ -libffi.call/closure_fn5.c \ -libffi.call/struct6.c libffi.call/return_ll.c libffi.call/struct9.c \ -libffi.call/return_sc.c libffi.call/struct7.c \ -libffi.call/cls_align_uint64.c libffi.call/cls_4byte.c \ -libffi.call/cls_6_1_byte.c \ -libffi.call/cls_7_1_byte.c libffi.call/unwindtest.cc \ -libffi.call/unwindtest_ffi_call.cc \ -lib/wrapper.exp lib/target-libpath.exp \ -lib/libffi.exp libffi.call/cls_struct_va1.c \ -libffi.call/cls_uchar_va.c libffi.call/cls_uint_va.c \ -libffi.call/cls_ulong_va.c libffi.call/cls_ushort_va.c \ -libffi.call/nested_struct11.c libffi.call/uninitialized.c \ -libffi.call/va_1.c libffi.call/va_struct1.c libffi.call/va_struct2.c \ -libffi.call/va_struct3.c \ -libffi.call/strlen2.c \ -libffi.call/strlen3.c \ -libffi.call/strlen4.c +EXTRA_DIST = lib/target-libpath.exp lib/libffi.exp lib/wrapper.exp \ +libffi.call/strlen4.c libffi.call/struct10.c libffi.call/many_mixed.c \ +libffi.call/float.c libffi.call/struct5.c libffi.call/return_fl3.c \ +libffi.call/return_fl1.c libffi.call/call.exp libffi.call/pyobjc-tc.c \ +libffi.call/float_va.c libffi.call/struct8.c libffi.call/pr1172638.c \ +libffi.call/return_sc.c libffi.call/va_struct1.c \ +libffi.call/align_stdcall.c libffi.call/struct9.c libffi.call/va_1.c \ +libffi.call/va_2.c libffi.call/va_struct2.c libffi.call/return_fl2.c \ +libffi.call/align_mixed.c libffi.call/ffitest.h libffi.call/struct4.c \ +libffi.call/return_ldl.c libffi.call/float3.c libffi.call/return_sl.c \ +libffi.call/return_dbl1.c libffi.call/err_bad_typedef.c \ +libffi.call/return_ll1.c libffi.call/return_dbl2.c \ +libffi.call/negint.c libffi.closures/nested_struct3.c \ +libffi.call/struct2.c libffi.call/struct3.c libffi.call/return_fl.c \ +libffi.call/offsets.c libffi.call/struct7.c libffi.call/va_struct3.c \ +libffi.call/float1.c libffi.call/uninitialized.c libffi.call/many2.c \ +libffi.call/struct6.c libffi.call/strlen2.c libffi.call/float2.c \ +libffi.call/return_ul.c libffi.call/struct1.c libffi.call/strlen3.c \ +libffi.call/return_dbl.c libffi.call/float4.c libffi.call/many.c \ +libffi.call/strlen.c libffi.call/return_uc.c libffi.call/many_double.c \ +libffi.call/return_ll.c libffi.call/promotion.c \ +libffi.complex/complex_defs_longdouble.inc \ +libffi.complex/cls_align_complex_float.c \ +libffi.complex/cls_complex_va_float.c \ +libffi.complex/cls_complex_struct_float.c \ +libffi.complex/return_complex2_longdouble.c \ +libffi.complex/cls_complex_float.c \ +libffi.complex/return_complex_longdouble.c \ +libffi.complex/return_complex2_float.c libffi.complex/cls_complex.inc \ +libffi.complex/cls_complex_va_longdouble.c \ +libffi.complex/return_complex_double.c \ +libffi.complex/return_complex.inc libffi.complex/many_complex.inc \ +libffi.complex/complex_float.c libffi.complex/cls_align_complex.inc \ +libffi.complex/return_complex2_double.c \ +libffi.complex/many_complex_float.c libffi.complex/ffitest.h \ +libffi.complex/return_complex1_double.c \ +libffi.complex/cls_complex_struct_longdouble.c \ +libffi.complex/complex_defs_double.inc \ +libffi.complex/cls_complex_va_double.c \ +libffi.complex/many_complex_double.c \ +libffi.complex/return_complex2.inc \ +libffi.complex/return_complex1_float.c \ +libffi.complex/complex_longdouble.c \ +libffi.complex/complex_defs_float.inc \ +libffi.complex/cls_complex_double.c \ +libffi.complex/cls_align_complex_double.c \ +libffi.complex/cls_align_complex_longdouble.c \ +libffi.complex/complex_double.c libffi.complex/cls_complex_va.inc \ +libffi.complex/many_complex_longdouble.c libffi.complex/complex.inc \ +libffi.complex/return_complex1_longdouble.c \ +libffi.complex/complex_int.c libffi.complex/cls_complex_longdouble.c \ +libffi.complex/cls_complex_struct_double.c \ +libffi.complex/return_complex1.inc libffi.complex/complex.exp \ +libffi.complex/cls_complex_struct.inc \ +libffi.complex/return_complex_float.c libffi.go/closure1.c \ +libffi.go/aa-direct.c libffi.go/ffitest.h libffi.go/go.exp \ +libffi.go/static-chain.h libffi.bhaible/bhaible.exp \ +libffi.bhaible/test-call.c libffi.bhaible/alignof.h \ +libffi.bhaible/testcases.c libffi.bhaible/test-callback.c \ +libffi.bhaible/Makefile libffi.bhaible/README config/default.exp \ +libffi.closures/cls_multi_sshort.c \ +libffi.closures/cls_align_longdouble_split2.c \ +libffi.closures/cls_1_1byte.c libffi.closures/cls_uint_va.c \ +libffi.closures/cls_3_1byte.c libffi.closures/cls_many_mixed_args.c \ +libffi.closures/cls_20byte1.c libffi.closures/cls_pointer_stack.c \ +libffi.closures/cls_align_float.c libffi.closures/cls_5_1_byte.c \ +libffi.closures/cls_9byte1.c libffi.closures/cls_align_uint32.c \ +libffi.closures/stret_medium.c libffi.closures/cls_3byte1.c \ +libffi.closures/cls_align_uint64.c libffi.closures/cls_longdouble_va.c \ +libffi.closures/cls_align_pointer.c libffi.closures/cls_19byte.c \ +libffi.closures/cls_ushort.c libffi.closures/cls_align_sint32.c \ +libffi.closures/cls_ulonglong.c libffi.closures/cls_struct_va1.c \ +libffi.closures/cls_9byte2.c libffi.closures/closure_fn5.c \ +libffi.closures/cls_5byte.c libffi.closures/cls_3float.c \ +libffi.closures/closure.exp libffi.closures/cls_schar.c \ +libffi.closures/closure_fn4.c \ +libffi.closures/closure_fn0.c libffi.closures/huge_struct.c \ +libffi.closures/cls_64byte.c libffi.closures/cls_longdouble.c \ +libffi.closures/cls_ulong_va.c libffi.closures/cls_6_1_byte.c \ +libffi.closures/cls_align_uint16.c libffi.closures/closure_fn2.c \ +libffi.closures/unwindtest_ffi_call.cc \ +libffi.closures/cls_multi_ushortchar.c libffi.closures/cls_8byte.c \ +libffi.closures/ffitest.h libffi.closures/nested_struct8.c \ +libffi.closures/cls_pointer.c libffi.closures/nested_struct2.c \ +libffi.closures/nested_struct.c libffi.closures/cls_multi_schar.c \ +libffi.closures/cls_align_longdouble_split.c \ +libffi.closures/cls_uchar.c libffi.closures/nested_struct9.c \ +libffi.closures/cls_float.c libffi.closures/stret_medium2.c \ +libffi.closures/closure_loc_fn0.c libffi.closures/cls_6byte.c \ +libffi.closures/closure_simple.c libffi.closures/cls_align_double.c \ +libffi.closures/cls_multi_uchar.c libffi.closures/cls_4_1byte.c \ +libffi.closures/closure_fn3.c libffi.closures/cls_align_sint64.c \ +libffi.closures/nested_struct1.c libffi.closures/unwindtest.cc \ +libffi.closures/nested_struct5.c libffi.closures/cls_multi_ushort.c \ +libffi.closures/nested_struct11.c \ +libffi.closures/nested_struct12.c \ +libffi.closures/nested_struct13.c \ +libffi.closures/cls_multi_sshortchar.c \ +libffi.closures/cls_align_longdouble.c \ +libffi.closures/cls_dbls_struct.c \ +libffi.closures/cls_many_mixed_float_double.c \ +libffi.closures/stret_large.c libffi.closures/stret_large2.c \ +libffi.closures/cls_align_sint16.c libffi.closures/cls_2byte.c \ +libffi.closures/nested_struct4.c libffi.closures/problem1.c \ +libffi.closures/testclosure.c libffi.closures/nested_struct6.c \ +libffi.closures/cls_4byte.c libffi.closures/cls_24byte.c \ +libffi.closures/nested_struct10.c libffi.closures/cls_uint.c \ +libffi.closures/cls_12byte.c libffi.closures/cls_sint.c \ +libffi.closures/cls_7_1_byte.c libffi.closures/cls_sshort.c \ +libffi.closures/cls_16byte.c libffi.closures/nested_struct7.c \ +libffi.closures/cls_double_va.c libffi.closures/cls_3byte2.c \ +libffi.closures/cls_double.c libffi.closures/cls_7byte.c \ +libffi.closures/closure_fn6.c libffi.closures/closure_fn1.c \ +libffi.closures/cls_20byte.c libffi.closures/cls_18byte.c \ +libffi.closures/err_bad_abi.c \ +libffi.closures/single_entry_structs1.c \ +libffi.closures/single_entry_structs2.c \ +libffi.closures/single_entry_structs3.c all: all-am diff --git a/libffi/testsuite/lib/libffi.exp b/libffi/testsuite/lib/libffi.exp index a0f6ab3..7dc7b5d 100644 --- a/libffi/testsuite/lib/libffi.exp +++ b/libffi/testsuite/lib/libffi.exp @@ -1,4 +1,4 @@ -# Copyright (C) 2003, 2005, 2008, 2009, 2010, 2011, 2014 Free Software Foundation, Inc. +# Copyright (C) 2003, 2005, 2008, 2009, 2010, 2011, 2014, 2019 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,7 +16,6 @@ proc load_gcc_lib { filename } { global srcdir loaded_libs - load_file $srcdir/../../gcc/testsuite/lib/$filename set loaded_libs($filename) "" } @@ -28,6 +27,183 @@ load_gcc_lib target-supports-dg.exp load_gcc_lib target-libpath.exp load_gcc_lib wrapper.exp +proc check_effective_target_gccbug { } { + global has_gccbug + return $has_gccbug +} + +# Return 1 if the target matches the effective target 'arg', 0 otherwise. +# This can be used with any check_* proc that takes no argument and +# returns only 1 or 0. It could be used with check_* procs that take +# arguments with keywords that pass particular arguments. + +proc is-effective-target { arg } { + global et_index + set selected 0 + if { ![info exists et_index] } { + # Initialize the effective target index that is used in some + # check_effective_target_* procs. + set et_index 0 + } + if { [info procs check_effective_target_${arg}] != [list] } { + set selected [check_effective_target_${arg}] + } else { + error "unknown effective target keyword `$arg'" + } + verbose "is-effective-target: $arg $selected" 2 + return $selected +} + +proc is-effective-target-keyword { arg } { + if { [info procs check_effective_target_${arg}] != [list] } { + return 1 + } else { + return 0 + } +} + +# Intercept the call to the DejaGnu version of dg-process-target to +# support use of an effective-target keyword in place of a list of +# target triplets to xfail or skip a test. +# +# The argument to dg-process-target is the keyword "target" or "xfail" +# followed by a selector: +# target-triplet-1 ... +# effective-target-keyword +# selector-expression +# +# For a target list the result is "S" if the target is selected, "N" otherwise. +# For an xfail list the result is "F" if the target is affected, "P" otherwise. + +# In contexts that allow either "target" or "xfail" the argument can be +# target selector1 xfail selector2 +# which returns "N" if selector1 is not selected, otherwise the result of +# "xfail selector2". +# +# A selector expression appears within curly braces and uses a single logical +# operator: !, &&, or ||. An operand is another selector expression, an +# effective-target keyword, or a list of target triplets within quotes or +# curly braces. + +if { [info procs saved-dg-process-target] == [list] } { + rename dg-process-target saved-dg-process-target + + # Evaluate an operand within a selector expression. + proc selector_opd { op } { + set selector "target" + lappend selector $op + set answer [ expr { [dg-process-target $selector] == "S" } ] + verbose "selector_opd: `$op' $answer" 2 + return $answer + } + + # Evaluate a target triplet list within a selector expression. + # Unlike other operands, this needs to be expanded from a list to + # the same string as "target". + proc selector_list { op } { + set selector "target [join $op]" + set answer [ expr { [dg-process-target $selector] == "S" } ] + verbose "selector_list: `$op' $answer" 2 + return $answer + } + + # Evaluate a selector expression. + proc selector_expression { exp } { + if { [llength $exp] == 2 } { + if [string match "!" [lindex $exp 0]] { + set op1 [lindex $exp 1] + set answer [expr { ! [selector_opd $op1] }] + } else { + # Assume it's a list of target triplets. + set answer [selector_list $exp] + } + } elseif { [llength $exp] == 3 } { + set op1 [lindex $exp 0] + set opr [lindex $exp 1] + set op2 [lindex $exp 2] + if [string match "&&" $opr] { + set answer [expr { [selector_opd $op1] && [selector_opd $op2] }] + } elseif [string match "||" $opr] { + set answer [expr { [selector_opd $op1] || [selector_opd $op2] }] + } else { + # Assume it's a list of target triplets. + set answer [selector_list $exp] + } + } else { + # Assume it's a list of target triplets. + set answer [selector_list $exp] + } + + verbose "selector_expression: `$exp' $answer" 2 + return $answer + } + + # Evaluate "target selector" or "xfail selector". + + proc dg-process-target-1 { args } { + verbose "dg-process-target-1: `$args'" 2 + + # Extract the 'what' keyword from the argument list. + set selector [string trim [lindex $args 0]] + if [regexp "^xfail " $selector] { + set what "xfail" + } elseif [regexp "^target " $selector] { + set what "target" + } else { + error "syntax error in target selector \"$selector\"" + } + + # Extract the rest of the list, which might be a keyword. + regsub "^${what}" $selector "" rest + set rest [string trim $rest] + + if [is-effective-target-keyword $rest] { + # The selector is an effective target keyword. + if [is-effective-target $rest] { + return [expr { $what == "xfail" ? "F" : "S" }] + } else { + return [expr { $what == "xfail" ? "P" : "N" }] + } + } + + if [string match "{*}" $rest] { + if [selector_expression [lindex $rest 0]] { + return [expr { $what == "xfail" ? "F" : "S" }] + } else { + return [expr { $what == "xfail" ? "P" : "N" }] + } + } + + # The selector is not an effective-target keyword, so process + # the list of target triplets. + return [saved-dg-process-target $selector] + } + + # Intercept calls to the DejaGnu function. In addition to + # processing "target selector" or "xfail selector", handle + # "target selector1 xfail selector2". + + proc dg-process-target { args } { + verbose "replacement dg-process-target: `$args'" 2 + + set selector [string trim [lindex $args 0]] + + # If the argument list contains both 'target' and 'xfail', + # process 'target' and, if that succeeds, process 'xfail'. + if [regexp "^target .* xfail .*" $selector] { + set xfail_index [string first "xfail" $selector] + set xfail_selector [string range $selector $xfail_index end] + set target_selector [string range $selector 0 [expr $xfail_index-1]] + set target_selector [string trim $target_selector] + if { [dg-process-target-1 $target_selector] == "N" } { + return "N" + } + return [dg-process-target-1 $xfail_selector] + + } + return [dg-process-target-1 $selector] + } +} # Define libffi callbacks for dg.exp. @@ -93,6 +269,12 @@ proc libffi-dg-test { prog do_what extra_tool_flags } { return [libffi-dg-test-1 target_compile $prog $do_what $extra_tool_flags] } +proc libffi-dg-prune { target_triplet text } { + # We get this with some qemu emulated systems (eg. ppc64le-linux-gnu) + regsub -all "(^|\n)\[^\n\]*unable to perform all requested operations" $text "" text + return $text +} + proc libffi-init { args } { global gluefile wrap_flags; global srcdir @@ -114,28 +296,30 @@ proc libffi-init { args } { set compiler_vendor "gnu" - set gccdir [lookfor_file $tool_root_dir gcc/libgcc.a] - if {$gccdir != ""} { - set gccdir [file dirname $gccdir] - } - verbose "gccdir $gccdir" - - set ld_library_path "." - append ld_library_path ":${gccdir}" - - set compiler "${gccdir}/xgcc" - if { [is_remote host] == 0 && [which $compiler] != 0 } { - foreach i "[exec $compiler --print-multi-lib]" { - set mldir "" - regexp -- "\[a-z0-9=_/\.-\]*;" $i mldir - set mldir [string trimright $mldir "\;@"] - if { "$mldir" == "." } { - continue - } - if { [llength [glob -nocomplain ${gccdir}/${mldir}/libgcc_s*.so.*]] >= 1 } { - append ld_library_path ":${gccdir}/${mldir}" + if { [string match $compiler_vendor "gnu"] } { + set gccdir [lookfor_file $tool_root_dir gcc/libgcc.a] + if {$gccdir != ""} { + set gccdir [file dirname $gccdir] + } + verbose "gccdir $gccdir" + + set ld_library_path "." + append ld_library_path ":${gccdir}" + + set compiler "${gccdir}/xgcc" + if { [is_remote host] == 0 && [which $compiler] != 0 } { + foreach i "[exec $compiler --print-multi-lib]" { + set mldir "" + regexp -- "\[a-z0-9=_/\.-\]*;" $i mldir + set mldir [string trimright $mldir "\;@"] + if { "$mldir" == "." } { + continue + } + if { [llength [glob -nocomplain ${gccdir}/${mldir}/libgcc_s*.so.*]] >= 1 } { + append ld_library_path ":${gccdir}/${mldir}" + } } - } + } } # add the library path for libffi. @@ -178,7 +362,7 @@ proc libffi_target_compile { source dest type options } { global libffi_link_flags global libffi_include global target_triplet - + global compiler_vendor if { [target_info needs_status_wrapper]!="" && [info exists gluefile] } { lappend options "libs=${gluefile}" @@ -188,7 +372,7 @@ proc libffi_target_compile { source dest type options } { # TOOL_OPTIONS must come first, so that it doesn't override testcase # specific options. if [info exists TOOL_OPTIONS] { - lappend options [concat "additional_flags=$TOOL_OPTIONS" $options]; + lappend options "additional_flags=$TOOL_OPTIONS" } # search for ffi_mips.h in srcdir, too @@ -221,6 +405,14 @@ proc libffi_target_compile { source dest type options } { lappend options "libs= -lpthread" } + if { [string match "*.cc" $source] } { + lappend options "ldflags=-shared-libgcc -lstdc++" + } + + if { [string match "arc*-*-linux*" $target_triplet] } { + lappend options "libs= -lpthread" + } + verbose "options: $options" return [target_compile $source $dest $type $options] } @@ -293,32 +485,54 @@ proc libffi-dg-runtest { testcases default-extra-flags } { proc run-many-tests { testcases extra_flags } { global compiler_vendor + global has_gccbug + global env switch $compiler_vendor { "clang" { - set common "-W -Wall" - set optimizations { "-O0" "-O1" "-O2" "-O3" "-Os" } + set common "-W -Wall" + if [info exists env(LIBFFI_TEST_OPTIMIZATION)] { + set optimizations [ list $env(LIBFFI_TEST_OPTIMIZATION) ] + } else { + set optimizations { "-O0" "-O2" } + } } "gnu" { set common "-W -Wall -Wno-psabi" - set optimizations { "-O0" "-O2" "-O3" "-Os" "-O2 -fomit-frame-pointer" } + if [info exists env(LIBFFI_TEST_OPTIMIZATION)] { + set optimizations [ list $env(LIBFFI_TEST_OPTIMIZATION) ] + } else { + set optimizations { "-O0" "-O2" } + } } default { # Assume we are using the vendor compiler. set common "" - set optimizations { "" } + if [info exists env(LIBFFI_TEST_OPTIMIZATION)] { + set optimizations [ list $env(LIBFFI_TEST_OPTIMIZATION) ] + } else { + set optimizations { "" } + } } } + info exists env(LD_LIBRARY_PATH) + set targetabis { "" } if [string match $compiler_vendor "gnu"] { - if { ([istarget "i?86-*-*"] || [istarget "x86_64-*-*"]) - && [is-effective-target ia32] && ![istarget "*-*-darwin*"] } { + if [libffi_feature_test "#ifdef __i386__"] { set targetabis { "" "-DABI_NUM=FFI_STDCALL -DABI_ATTR=__STDCALL__" "-DABI_NUM=FFI_THISCALL -DABI_ATTR=__THISCALL__" "-DABI_NUM=FFI_FASTCALL -DABI_ATTR=__FASTCALL__" } + } elseif { [istarget "x86_64-*-*"] \ + && [libffi_feature_test "#if !defined __ILP32__ \ + && !defined __i386__"] } { + set targetabis { + "" + "-DABI_NUM=FFI_GNUW64 -DABI_ATTR=__MSABI__" + } } } @@ -333,8 +547,22 @@ proc run-many-tests { testcases extra_flags } { foreach opt $optimizations { foreach abi $abis { set options [concat $common $opt $abi] - verbose "Testing $testname, $options" 1 - dg-test $test $options "" + set has_gccbug false; + if { [string match $compiler_vendor "gnu"] \ + && [string match "*MSABI*" $abi] \ + && ( ( [string match "*DGTEST=57 *" $common] \ + && [string match "*call.c*" $testname] ) \ + || ( [string match "*DGTEST=54 *" $common] \ + && [string match "*callback*" $testname] ) \ + || [string match "*DGTEST=55 *" $common] \ + || [string match "*DGTEST=56 *" $common] ) } then { + if [libffi_feature_test "#if (__GNUC__ < 9) || ((__GNUC__ == 9) && (__GNUC_MINOR__ < 3))"] { + set has_gccbug true; + } + } + verbose "Testing $testname, $options" 1 + verbose "has_gccbug = $has_gccbug" 1 + dg-test $test $options "" } } } diff --git a/libffi/testsuite/libffi.bhaible/Makefile b/libffi/testsuite/libffi.bhaible/Makefile new file mode 100644 index 0000000..3322de9 --- /dev/null +++ b/libffi/testsuite/libffi.bhaible/Makefile @@ -0,0 +1,28 @@ +CC = gcc +CFLAGS = -O2 -Wall +prefix = +includedir = $(prefix)/include +libdir = $(prefix)/lib +CPPFLAGS = -I$(includedir) +LDFLAGS = -L$(libdir) -Wl,-rpath,$(libdir) + +all: check-call check-callback + +test-call: test-call.c testcases.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o test-call test-call.c -lffi + +test-callback: test-callback.c testcases.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o test-callback test-callback.c -lffi + +check-call: test-call + ./test-call > test-call.out + LC_ALL=C uniq -u < test-call.out > failed-call + test '!' -s failed-call + +check-callback: test-callback + ./test-callback > test-callback.out + LC_ALL=C uniq -u < test-callback.out > failed-callback + test '!' -s failed-callback + +clean: + rm -f test-call test-callback test-call.out test-callback.out failed-call failed-callback diff --git a/libffi/testsuite/libffi.bhaible/README b/libffi/testsuite/libffi.bhaible/README new file mode 100644 index 0000000..be8540b --- /dev/null +++ b/libffi/testsuite/libffi.bhaible/README @@ -0,0 +1,78 @@ +This package contains a test suite for libffi. + +This test suite can be compiled with a C compiler. No need for 'expect' +or some other package that is often not installed. + +The test suite consists of 81 C functions, each with a different signature. +* test-call verifies that calling each function directly produces the same + results as calling the function indirectly through 'ffi_call'. +* test-callback verifies that calling each function directly produces the same + results as calling a function that is a callback (object build by + 'ffi_prep_closure_loc') and simulates the original function. + +Each direct or indirect invocation should produce one line of output to +stdout. A correct output consists of paired lines, such as + +void f(void): +void f(void): +int f(void):->99 +int f(void):->99 +int f(int):(1)->2 +int f(int):(1)->2 +int f(2*int):(1,2)->3 +int f(2*int):(1,2)->3 +... + +The Makefile then creates two files: +* failed-call, which consists of the non-paired lines of output of + 'test-call', +* failed-callback, which consists of the non-paired lines of output of + 'test-callback'. + +The test suite passes if both failed-call and failed-callback come out +as empty. + + +How to use the test suite +------------------------- + +1. Modify the Makefile's variables + prefix = the directory in which libffi was installed + CC = the C compiler, often with options such as "-m32" or "-m64" + that enforce a certain ABI, + CFLAGS = optimization options (need to change them only for non-GCC + compilers) +2. Run "make". If it fails already in "test-call", run also + "make check-callback". +3. If this failed, inspect the output files. + + +How to interpret the results +---------------------------- + +The failed-call and failed-callback files consist of paired lines: +The first line is the result of the direct invocation. +The second line is the result of invocation through libffi. + +For example, this output + +uchar f(uchar,ushort,uint,ulong):(97,2,3,4)->255 +uchar f(uchar,ushort,uint,ulong):(97,2,3,4)->0 + +indicates that the arguments were passed correctly, but the return +value came out wrong. + +And this output + +float f(17*float,3*int,L):(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,6,7,8,561,1105,1729,2465,2821,6601)->15319.1 +float f(17*float,3*int,L):(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,-140443648,10,268042216,-72537980,-140443648,-140443648,-140443648,-140443648,-140443648)->-6.47158e+08 + +indicates that integer arguments that come after 17 floating-point arguments +were not passed correctly. + + +Credits +------- + +The test suite is based on the one of GNU libffcall-2.0. +Authors: Bill Triggs, Bruno Haible diff --git a/libffi/testsuite/libffi.bhaible/alignof.h b/libffi/testsuite/libffi.bhaible/alignof.h new file mode 100644 index 0000000..00604a5 --- /dev/null +++ b/libffi/testsuite/libffi.bhaible/alignof.h @@ -0,0 +1,50 @@ +/* Determine alignment of types. + Copyright (C) 2003-2004, 2006, 2009-2017 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _ALIGNOF_H +#define _ALIGNOF_H + +#include <stddef.h> + +/* alignof_slot (TYPE) + Determine the alignment of a structure slot (field) of a given type, + at compile time. Note that the result depends on the ABI. + This is the same as alignof (TYPE) and _Alignof (TYPE), defined in + <stdalign.h> if __alignof_is_defined is 1. + Note: The result cannot be used as a value for an 'enum' constant, + due to bugs in HP-UX 10.20 cc and AIX 3.2.5 xlc. */ +#if defined __cplusplus + template <class type> struct alignof_helper { char __slot1; type __slot2; }; +# define alignof_slot(type) offsetof (alignof_helper<type>, __slot2) +#else +# define alignof_slot(type) offsetof (struct { char __slot1; type __slot2; }, __slot2) +#endif + +/* alignof_type (TYPE) + Determine the good alignment of an object of the given type at compile time. + Note that this is not necessarily the same as alignof_slot(type). + For example, with GNU C on x86 platforms: alignof_type(double) = 8, but + - when -malign-double is not specified: alignof_slot(double) = 4, + - when -malign-double is specified: alignof_slot(double) = 8. + Note: The result cannot be used as a value for an 'enum' constant, + due to bugs in HP-UX 10.20 cc and AIX 3.2.5 xlc. */ +#if defined __GNUC__ || defined __IBM__ALIGNOF__ +# define alignof_type __alignof__ +#else +# define alignof_type alignof_slot +#endif + +#endif /* _ALIGNOF_H */ diff --git a/libffi/testsuite/libffi.bhaible/bhaible.exp b/libffi/testsuite/libffi.bhaible/bhaible.exp new file mode 100644 index 0000000..44aebc5 --- /dev/null +++ b/libffi/testsuite/libffi.bhaible/bhaible.exp @@ -0,0 +1,63 @@ +# Copyright (C) 2003, 2006, 2009, 2010, 2014, 2018 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +dg-init +libffi-init + +global srcdir subdir +global compiler_vendor + +# The conversion of this testsuite into a dejagnu compatible testsuite +# was done in a pretty lazy fashion, and requires the use of compiler +# flags to disable warnings for now. +if { [string match $compiler_vendor "gnu"] } { + set warning_options "-Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -Wno-uninitialized"; +} +if { [string match $compiler_vendor "microsoft"] } { + # -wd4996 suggest use of vsprintf_s instead of vsprintf + # -wd4116 unnamed type definition + # -wd4101 unreferenced local variable + # -wd4244 warning about implicit double to float conversion + set warning_options "-wd4996 -wd4116 -wd4101 -wd4244"; +} +if { ![string match $compiler_vendor "microsoft"] && ![string match $compiler_vendor "gnu"] } { + set warning_options "-Wno-unused-variable -Wno-unused-parameter -Wno-uninitialized"; +} + + +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/test-call.c]] + +for {set i 1} {$i < 82} {incr i} { + run-many-tests $tlist [format "-DDGTEST=%d %s" $i $warning_options] +} + +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/test-callback.c]] + +for {set i 1} {$i < 81} {incr i} { + if { [libffi_feature_test "#if FFI_CLOSURES"] } { + run-many-tests $tlist [format "-DDGTEST=%d %s" $i $warning_options] + } else { + foreach test $tlist { + unsupported [format "%s -DDGTEST=%d %s" $test $i $warning_options] + } + } +} + +dg-finish + +# Local Variables: +# tcl-indent-level:4 +# End: diff --git a/libffi/testsuite/libffi.bhaible/test-call.c b/libffi/testsuite/libffi.bhaible/test-call.c new file mode 100644 index 0000000..cf9219e --- /dev/null +++ b/libffi/testsuite/libffi.bhaible/test-call.c @@ -0,0 +1,1745 @@ +/** + Copyright 1993 Bill Triggs <Bill.Triggs@inrialpes.fr> + Copyright 1995-2017 Bruno Haible <bruno@clisp.org> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +**/ + +/* { dg-do run { xfail gccbug } } */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ffi.h> +#include "alignof.h" +#include <stdarg.h> + +/* libffi testsuite local changes -------------------------------- */ +#ifdef DGTEST +/* Redefine exit(1) as a test failure */ +#define exit(V) (void)((V) ? (abort(), 1) : exit(0)) +int count = 0; +char rbuf1[2048]; +char rbuf2[2048]; +int _fprintf(FILE *stream, const char *format, ...) +{ + va_list args; + va_start(args, format); + + switch (count++) + { + case 0: + case 1: + vsprintf(&rbuf1[strlen(rbuf1)], format, args); + break; + case 2: + printf("%s", rbuf1); + vsprintf(rbuf2, format, args); + break; + case 3: + vsprintf(&rbuf2[strlen(rbuf2)], format, args); + printf("%s", rbuf2); + if (strcmp (rbuf1, rbuf2)) abort(); + break; + } + + va_end(args); + + return 0; +} +#define fprintf _fprintf +#endif +/* --------------------------------------------------------------- */ + +#include "testcases.c" + +#ifndef ABI_NUM +#define ABI_NUM FFI_DEFAULT_ABI +#endif + +/* Definitions that ought to be part of libffi. */ +static ffi_type ffi_type_char; +#define ffi_type_slonglong ffi_type_sint64 +#define ffi_type_ulonglong ffi_type_uint64 + +/* libffi does not support arrays inside structs. */ +#define SKIP_EXTRA_STRUCTS + +#define FFI_PREP_CIF(cif,argtypes,rettype) \ + if (ffi_prep_cif(&(cif),ABI_NUM,sizeof(argtypes)/sizeof(argtypes[0]),&rettype,argtypes) != FFI_OK) abort() +#define FFI_PREP_CIF_NOARGS(cif,rettype) \ + if (ffi_prep_cif(&(cif),ABI_NUM,0,&rettype,NULL) != FFI_OK) abort() +#define FFI_CALL(cif,fn,args,retaddr) \ + ffi_call(&(cif),(void(*)(void))(fn),retaddr,args) + +long clear_traces_i (long a, long b, long c, long d, long e, long f, long g, long h, + long i, long j, long k, long l, long m, long n, long o, long p) +{ return 0; } +float clear_traces_f (float a, float b, float c, float d, float e, float f, float g, + float h, float i, float j, float k, float l, float m, float n, + float o, float p) +{ return 0.0; } +double clear_traces_d (double a, double b, double c, double d, double e, double f, double g, + double h, double i, double j, double k, double l, double m, double n, + double o, double p) +{ return 0.0; } +J clear_traces_J (void) +{ J j; j.l1 = j.l2 = 0; return j; } +void clear_traces (void) +{ clear_traces_i(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + clear_traces_f(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0); + clear_traces_d(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0); + clear_traces_J(); +} + +void + void_tests (void) +{ +#if (!defined(DGTEST)) || DGTEST == 1 + v_v(); + clear_traces(); + { + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_void); + { + FFI_CALL(cif,v_v,NULL,NULL); + } + } +#endif + return; +} +void + int_tests (void) +{ + int ir; + ffi_arg retvalue; +#if (!defined(DGTEST)) || DGTEST == 2 + ir = i_v(); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + { + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_sint); + { + FFI_CALL(cif,i_v,NULL,&retvalue); + ir = retvalue; + } + } + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 3 + ir = i_i(i1); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + { + /*const*/ void* args[] = { &i1 }; + FFI_CALL(cif,i_i,args,&retvalue); + ir = retvalue; + } + } + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 4 + ir = i_i2(i1,i2); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + { + /*const*/ void* args[] = { &i1, &i2 }; + FFI_CALL(cif,i_i2,args,&retvalue); + ir = retvalue; + } + } + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 5 + ir = i_i4(i1,i2,i3,i4); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + { + /*const*/ void* args[] = { &i1, &i2, &i3, &i4 }; + FFI_CALL(cif,i_i4,args,&retvalue); + ir = retvalue; + } + } + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 6 + ir = i_i8(i1,i2,i3,i4,i5,i6,i7,i8); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + { + /*const*/ void* args[] = { &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8 }; + FFI_CALL(cif,i_i8,args,&retvalue); + ir = retvalue; + } + } + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 7 + ir = i_i16(i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + { + /*const*/ void* args[] = { &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8, &i9, &i10, &i11, &i12, &i13, &i14, &i15, &i16 }; + FFI_CALL(cif,i_i16,args,&retvalue); + ir = retvalue; + } + } + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + + return; +} +void + float_tests (void) +{ + float fr; + +#if (!defined(DGTEST)) || DGTEST == 8 + fr = f_f(f1); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1 }; + FFI_CALL(cif,f_f,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 9 + fr = f_f2(f1,f2); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2 }; + FFI_CALL(cif,f_f2,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 10 + fr = f_f4(f1,f2,f3,f4); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4 }; + FFI_CALL(cif,f_f4,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 11 + fr = f_f8(f1,f2,f3,f4,f5,f6,f7,f8); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8 }; + FFI_CALL(cif,f_f8,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 12 + fr = f_f16(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9, &f10, &f11, &f12, &f13, &f14, &f15, &f16 }; + FFI_CALL(cif,f_f16,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 13 + fr = f_f24(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9, &f10, &f11, &f12, &f13, &f14, &f15, &f16, &f17, &f18, &f19, &f20, &f21, &f22, &f23, &f24 }; + FFI_CALL(cif,f_f24,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif +} +void + double_tests (void) +{ + double dr; + +#if (!defined(DGTEST)) || DGTEST == 14 + + dr = d_d(d1); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1 }; + FFI_CALL(cif,d_d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 15 + dr = d_d2(d1,d2); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2 }; + FFI_CALL(cif,d_d2,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 16 + dr = d_d4(d1,d2,d3,d4); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4 }; + FFI_CALL(cif,d_d4,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 17 + dr = d_d8(d1,d2,d3,d4,d5,d6,d7,d8); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8 }; + FFI_CALL(cif,d_d8,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 18 + dr = d_d16(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9, &d10, &d11, &d12, &d13, &d14, &d15, &d16 }; + FFI_CALL(cif,d_d16,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + return; +} +void + pointer_tests (void) +{ + void* vpr; + +#if (!defined(DGTEST)) || DGTEST == 19 + vpr = vp_vpdpcpsp(&uc1,&d2,str3,&I4); + fprintf(out,"->0x%p\n",vpr); + fflush(out); + vpr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_pointer, &ffi_type_pointer, &ffi_type_pointer, &ffi_type_pointer }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_pointer); + { + void* puc1 = &uc1; + void* pd2 = &d2; + void* pstr3 = str3; + void* pI4 = &I4; + /*const*/ void* args[] = { &puc1, &pd2, &pstr3, &pI4 }; + FFI_CALL(cif,vp_vpdpcpsp,args,&vpr); + } + } + fprintf(out,"->0x%p\n",vpr); + fflush(out); +#endif + return; +} +void + mixed_number_tests (void) +{ + uchar ucr; + ushort usr; + float fr; + double dr; + long long llr; + + /* Unsigned types. + */ +#if (!defined(DGTEST)) || DGTEST == 20 + ucr = uc_ucsil(uc1, us2, ui3, ul4); + fprintf(out,"->%u\n",ucr); + fflush(out); + ucr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_uchar, &ffi_type_ushort, &ffi_type_uint, &ffi_type_ulong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_uchar); + { + ffi_arg r; + /*const*/ void* args[] = { &uc1, &us2, &ui3, &ul4 }; + FFI_CALL(cif,uc_ucsil,args,&r); + ucr = (uchar) r; + } + } + fprintf(out,"->%u\n",ucr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 21 + /* Mixed int & float types. + */ + dr = d_iidd(i1,i2,d3,d4); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &i1, &i2, &d3, &d4 }; + FFI_CALL(cif,d_iidd,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 22 + dr = d_iiidi(i1,i2,i3,d4,i5); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &i1, &i2, &i3, &d4, &i5 }; + FFI_CALL(cif,d_iiidi,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 23 + dr = d_idid(i1,d2,i3,d4); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_double, &ffi_type_sint, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &i1, &d2, &i3, &d4 }; + FFI_CALL(cif,d_idid,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 24 + dr = d_fdi(f1,d2,i3); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &f1, &d2, &i3 }; + FFI_CALL(cif,d_fdi,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 25 + usr = us_cdcd(c1,d2,c3,d4); + fprintf(out,"->%u\n",usr); + fflush(out); + usr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_char, &ffi_type_double, &ffi_type_char, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_ushort); + { + ffi_arg rint; + /*const*/ void* args[] = { &c1, &d2, &c3, &d4 }; + FFI_CALL(cif,us_cdcd,args,&rint); + usr = (ushort) rint; + } + } + fprintf(out,"->%u\n",usr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 26 + /* Long long types. + */ + llr = ll_iiilli(i1,i2,i3,ll1,i13); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_slonglong, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &i1, &i2, &i3, &ll1, &i13 }; + FFI_CALL(cif,ll_iiilli,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 27 + llr = ll_flli(f13,ll1,i13); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_slonglong, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &f13, &ll1, &i13 }; + FFI_CALL(cif,ll_flli,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 28 + fr = f_fi(f1,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &i9 }; + FFI_CALL(cif,f_fi,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 29 + fr = f_f2i(f1,f2,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &i9 }; + FFI_CALL(cif,f_f2i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 30 + fr = f_f3i(f1,f2,f3,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &i9 }; + FFI_CALL(cif,f_f3i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 31 + fr = f_f4i(f1,f2,f3,f4,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &i9 }; + FFI_CALL(cif,f_f4i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 32 + fr = f_f7i(f1,f2,f3,f4,f5,f6,f7,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &i9 }; + FFI_CALL(cif,f_f7i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 33 + fr = f_f8i(f1,f2,f3,f4,f5,f6,f7,f8,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &i9 }; + FFI_CALL(cif,f_f8i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 34 + fr = f_f12i(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9, &f10, &f11, &f12, &i9 }; + FFI_CALL(cif,f_f12i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 35 + fr = f_f13i(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9, &f10, &f11, &f12, &f13, &i9 }; + FFI_CALL(cif,f_f13i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 36 + dr = d_di(d1,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &i9 }; + FFI_CALL(cif,d_di,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 37 + dr = d_d2i(d1,d2,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &i9 }; + FFI_CALL(cif,d_d2i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 38 + dr = d_d3i(d1,d2,d3,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &i9 }; + FFI_CALL(cif,d_d3i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 39 + dr = d_d4i(d1,d2,d3,d4,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &i9 }; + FFI_CALL(cif,d_d4i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 40 + dr = d_d7i(d1,d2,d3,d4,d5,d6,d7,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &i9 }; + FFI_CALL(cif,d_d7i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 41 + dr = d_d8i(d1,d2,d3,d4,d5,d6,d7,d8,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &i9 }; + FFI_CALL(cif,d_d8i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 42 + dr = d_d12i(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9, &d10, &d11, &d12, &i9 }; + FFI_CALL(cif,d_d12i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 43 + dr = d_d13i(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9, &d10, &d11, &d12, &d13, &i9 }; + FFI_CALL(cif,d_d13i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + return; +} +void + small_structure_return_tests (void) +{ +#if (!defined(DGTEST)) || DGTEST == 44 + { + Size1 r = S1_v(); + fprintf(out,"->{%c}\n",r.x1); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size1_elements[] = { &ffi_type_char, NULL }; + ffi_type ffi_type_Size1; + ffi_type_Size1.type = FFI_TYPE_STRUCT; + ffi_type_Size1.size = sizeof(Size1); + ffi_type_Size1.alignment = alignof_slot(Size1); + ffi_type_Size1.elements = ffi_type_Size1_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size1); + { + FFI_CALL(cif,S1_v,NULL,&r); + } + } + fprintf(out,"->{%c}\n",r.x1); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 45 + { + Size2 r = S2_v(); + fprintf(out,"->{%c%c}\n",r.x1,r.x2); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size2_elements[] = { &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size2; + ffi_type_Size2.type = FFI_TYPE_STRUCT; + ffi_type_Size2.size = sizeof(Size2); + ffi_type_Size2.alignment = alignof_slot(Size2); + ffi_type_Size2.elements = ffi_type_Size2_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size2); + { + FFI_CALL(cif,S2_v,NULL,&r); + } + } + fprintf(out,"->{%c%c}\n",r.x1,r.x2); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 46 + { + Size3 r = S3_v(); + fprintf(out,"->{%c%c%c}\n",r.x1,r.x2,r.x3); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size3_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size3; + ffi_type_Size3.type = FFI_TYPE_STRUCT; + ffi_type_Size3.size = sizeof(Size3); + ffi_type_Size3.alignment = alignof_slot(Size3); + ffi_type_Size3.elements = ffi_type_Size3_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size3); + { + FFI_CALL(cif,S3_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c}\n",r.x1,r.x2,r.x3); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 47 + { + Size4 r = S4_v(); + fprintf(out,"->{%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size4_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size4; + ffi_type_Size4.type = FFI_TYPE_STRUCT; + ffi_type_Size4.size = sizeof(Size4); + ffi_type_Size4.alignment = alignof_slot(Size4); + ffi_type_Size4.elements = ffi_type_Size4_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size4); + { + FFI_CALL(cif,S4_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 48 + { + Size7 r = S7_v(); + fprintf(out,"->{%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size7_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size7; + ffi_type_Size7.type = FFI_TYPE_STRUCT; + ffi_type_Size7.size = sizeof(Size7); + ffi_type_Size7.alignment = alignof_slot(Size7); + ffi_type_Size7.elements = ffi_type_Size7_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size7); + { + FFI_CALL(cif,S7_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 49 + { + Size8 r = S8_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size8_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size8; + ffi_type_Size8.type = FFI_TYPE_STRUCT; + ffi_type_Size8.size = sizeof(Size8); + ffi_type_Size8.alignment = alignof_slot(Size8); + ffi_type_Size8.elements = ffi_type_Size8_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size8); + { + FFI_CALL(cif,S8_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 50 + { + Size12 r = S12_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size12_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size12; + ffi_type_Size12.type = FFI_TYPE_STRUCT; + ffi_type_Size12.size = sizeof(Size12); + ffi_type_Size12.alignment = alignof_slot(Size12); + ffi_type_Size12.elements = ffi_type_Size12_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size12); + { + FFI_CALL(cif,S12_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 51 + { + Size15 r = S15_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size15_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size15; + ffi_type_Size15.type = FFI_TYPE_STRUCT; + ffi_type_Size15.size = sizeof(Size15); + ffi_type_Size15.alignment = alignof_slot(Size15); + ffi_type_Size15.elements = ffi_type_Size15_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size15); + { + FFI_CALL(cif,S15_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 52 + { + Size16 r = S16_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15,r.x16); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size16_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size16; + ffi_type_Size16.type = FFI_TYPE_STRUCT; + ffi_type_Size16.size = sizeof(Size16); + ffi_type_Size16.alignment = alignof_slot(Size16); + ffi_type_Size16.elements = ffi_type_Size16_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size16); + { + FFI_CALL(cif,S16_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15,r.x16); + fflush(out); + } +#endif +} +void + structure_tests (void) +{ + Int Ir; + Char Cr; + Float Fr; + Double Dr; + J Jr; +#ifndef SKIP_EXTRA_STRUCTS + T Tr; + X Xr; +#endif + +#if (!defined(DGTEST)) || DGTEST == 53 + Ir = I_III(I1,I2,I3); + fprintf(out,"->{%d}\n",Ir.x); + fflush(out); + Ir.x = 0; clear_traces(); + { + ffi_type* ffi_type_Int_elements[] = { &ffi_type_sint, NULL }; + ffi_type ffi_type_Int; + ffi_type_Int.type = FFI_TYPE_STRUCT; + ffi_type_Int.size = sizeof(Int); + ffi_type_Int.alignment = alignof_slot(Int); + ffi_type_Int.elements = ffi_type_Int_elements; + ffi_type* argtypes[] = { &ffi_type_Int, &ffi_type_Int, &ffi_type_Int }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Int); + { + /*const*/ void* args[] = { &I1, &I2, &I3 }; + FFI_CALL(cif,I_III,args,&Ir); + } + } + fprintf(out,"->{%d}\n",Ir.x); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 54 + Cr = C_CdC(C1,d2,C3); + fprintf(out,"->{'%c'}\n",Cr.x); + fflush(out); + Cr.x = '\0'; clear_traces(); + { + ffi_type* ffi_type_Char_elements[] = { &ffi_type_char, NULL }; + ffi_type ffi_type_Char; + ffi_type_Char.type = FFI_TYPE_STRUCT; + ffi_type_Char.size = sizeof(Char); + ffi_type_Char.alignment = alignof_slot(Char); + ffi_type_Char.elements = ffi_type_Char_elements; + ffi_type* argtypes[] = { &ffi_type_Char, &ffi_type_double, &ffi_type_Char }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Char); + { + /*const*/ void* args[] = { &C1, &d2, &C3 }; + FFI_CALL(cif,C_CdC,args,&Cr); + } + } + fprintf(out,"->{'%c'}\n",Cr.x); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 55 + Fr = F_Ffd(F1,f2,d3); + fprintf(out,"->{%g}\n",Fr.x); + fflush(out); + Fr.x = 0.0; clear_traces(); + { + ffi_type* ffi_type_Float_elements[] = { &ffi_type_float, NULL }; + ffi_type ffi_type_Float; + ffi_type_Float.type = FFI_TYPE_STRUCT; + ffi_type_Float.size = sizeof(Float); + ffi_type_Float.alignment = alignof_slot(Float); + ffi_type_Float.elements = ffi_type_Float_elements; + ffi_type* argtypes[] = { &ffi_type_Float, &ffi_type_float, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Float); + { + /*const*/ void* args[] = { &F1, &f2, &d3 }; + FFI_CALL(cif,F_Ffd,args,&Fr); + } + } + fprintf(out,"->{%g}\n",Fr.x); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 56 + Dr = D_fDd(f1,D2,d3); + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); + Dr.x = 0.0; clear_traces(); + { + ffi_type* ffi_type_Double_elements[] = { &ffi_type_double, NULL }; + ffi_type ffi_type_Double; + ffi_type_Double.type = FFI_TYPE_STRUCT; + ffi_type_Double.size = sizeof(Double); + ffi_type_Double.alignment = alignof_slot(Double); + ffi_type_Double.elements = ffi_type_Double_elements; + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_Double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Double); + { + /*const*/ void* args[] = { &f1, &D2, &d3 }; + FFI_CALL(cif,D_fDd,args,&Dr); + } + } + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 57 + Dr = D_Dfd(D1,f2,d3); + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); + Dr.x = 0.0; clear_traces(); + { + ffi_type* ffi_type_Double_elements[] = { &ffi_type_double, NULL }; + ffi_type ffi_type_Double; + ffi_type_Double.type = FFI_TYPE_STRUCT; + ffi_type_Double.size = sizeof(Double); + ffi_type_Double.alignment = alignof_slot(Double); + ffi_type_Double.elements = ffi_type_Double_elements; + ffi_type* argtypes[] = { &ffi_type_Double, &ffi_type_float, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Double); + { + /*const*/ void* args[] = { &D1, &f2, &d3 }; + FFI_CALL(cif,D_Dfd,args,&Dr); + } + } + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 58 + Jr = J_JiJ(J1,i2,J2); + fprintf(out,"->{%ld,%ld}\n",Jr.l1,Jr.l2); + fflush(out); + Jr.l1 = Jr.l2 = 0; clear_traces(); + { + ffi_type* ffi_type_J_elements[] = { &ffi_type_slong, &ffi_type_slong, NULL }; + ffi_type ffi_type_J; + ffi_type_J.type = FFI_TYPE_STRUCT; + ffi_type_J.size = sizeof(J); + ffi_type_J.alignment = alignof_slot(J); + ffi_type_J.elements = ffi_type_J_elements; + ffi_type* argtypes[] = { &ffi_type_J, &ffi_type_sint, &ffi_type_J }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_J); + { + /*const*/ void* args[] = { &J1, &i2, &J2 }; + FFI_CALL(cif,J_JiJ,args,&Jr); + } + } + fprintf(out,"->{%ld,%ld}\n",Jr.l1,Jr.l2); + fflush(out); +#endif +#ifndef SKIP_EXTRA_STRUCTS +#if (!defined(DGTEST)) || DGTEST == 59 + Tr = T_TcT(T1,' ',T2); + fprintf(out,"->{\"%c%c%c\"}\n",Tr.c[0],Tr.c[1],Tr.c[2]); + fflush(out); + Tr.c[0] = Tr.c[1] = Tr.c[2] = 0; clear_traces(); + { + ffi_type* ffi_type_T_elements[] = { ??, NULL }; + ffi_type ffi_type_T; + ffi_type_T.type = FFI_TYPE_STRUCT; + ffi_type_T.size = sizeof(T); + ffi_type_T.alignment = alignof_slot(T); + ffi_type_T.elements = ffi_type_T_elements; + ffi_type* argtypes[] = { &ffi_type_T, &ffi_type_char, &ffi_type_T }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_T); + { + char space = ' '; + /*const*/ void* args[] = { &T1, &space, &T2 }; + FFI_CALL(cif,T_TcT,args,&Tr); + } + } + fprintf(out,"->{\"%c%c%c\"}\n",Tr.c[0],Tr.c[1],Tr.c[2]); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 60 + Xr = X_BcdB(B1,c2,d3,B2); + fprintf(out,"->{\"%s\",'%c'}\n",Xr.c,Xr.c1); + fflush(out); + Xr.c[0]=Xr.c1='\0'; clear_traces(); + { + ffi_type* ffi_type_X_elements[] = { ??, NULL }; + ffi_type ffi_type_X; + ffi_type_X.type = FFI_TYPE_STRUCT; + ffi_type_X.size = sizeof(X); + ffi_type_X.alignment = alignof_slot(X); + ffi_type_X.elements = ffi_type_X_elements; + ffi_type* argtypes[] = { &ffi_type_X, &ffi_type_char, &ffi_type_double, &ffi_type_X }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_X); + { + /*const*/ void* args[] = { &B1, &c2, &d3, &B2 }; + FFI_CALL(cif,X_BcdB,args,&Xr); + } + } + fprintf(out,"->{\"%s\",'%c'}\n",Xr.c,Xr.c1); + fflush(out); +#endif +#endif + + return; +} + +void + gpargs_boundary_tests (void) +{ + ffi_type* ffi_type_K_elements[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, NULL }; + ffi_type ffi_type_K; + ffi_type* ffi_type_L_elements[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, NULL }; + ffi_type ffi_type_L; + long lr; + long long llr; + float fr; + double dr; + + ffi_type_K.type = FFI_TYPE_STRUCT; + ffi_type_K.size = sizeof(K); + ffi_type_K.alignment = alignof_slot(K); + ffi_type_K.elements = ffi_type_K_elements; + + ffi_type_L.type = FFI_TYPE_STRUCT; + ffi_type_L.size = sizeof(L); + ffi_type_L.alignment = alignof_slot(L); + ffi_type_L.elements = ffi_type_L_elements; + +#if (!defined(DGTEST)) || DGTEST == 61 + lr = l_l0K(K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &K1, &l9 }; + FFI_CALL(cif,l_l0K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 62 + lr = l_l1K(l1,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &l1, &K1, &l9 }; + FFI_CALL(cif,l_l1K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 63 + lr = l_l2K(l1,l2,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &l1, &l2, &K1, &l9 }; + FFI_CALL(cif,l_l2K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 64 + lr = l_l3K(l1,l2,l3,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &K1, &l9 }; + FFI_CALL(cif,l_l3K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 65 + lr = l_l4K(l1,l2,l3,l4,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &K1, &l9 }; + FFI_CALL(cif,l_l4K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 66 + lr = l_l5K(l1,l2,l3,l4,l5,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &K1, &l9 }; + FFI_CALL(cif,l_l5K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 67 + lr = l_l6K(l1,l2,l3,l4,l5,l6,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &l6, &K1, &l9 }; + FFI_CALL(cif,l_l6K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 68 + fr = f_f17l3L(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,l6,l7,l8,L1); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_L }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9, &f10, &f11, &f12, &f13, &f14, &f15, &f16, &f17, &l6, &l7, &l8, &L1 }; + FFI_CALL(cif,f_f17l3L,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 69 + dr = d_d17l3L(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17,l6,l7,l8,L1); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_L }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9, &d10, &d11, &d12, &d13, &d14, &d15, &d16, &d17, &l6, &l7, &l8, &L1 }; + FFI_CALL(cif,d_d17l3L,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 70 + llr = ll_l2ll(l1,l2,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &l1, &l2, &ll1, &l9 }; + FFI_CALL(cif,ll_l2ll,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 71 + llr = ll_l3ll(l1,l2,l3,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &ll1, &l9 }; + FFI_CALL(cif,ll_l3ll,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 72 + llr = ll_l4ll(l1,l2,l3,l4,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &ll1, &l9 }; + FFI_CALL(cif,ll_l4ll,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 73 + llr = ll_l5ll(l1,l2,l3,l4,l5,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &ll1, &l9 }; + FFI_CALL(cif,ll_l5ll,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 74 + llr = ll_l6ll(l1,l2,l3,l4,l5,l6,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &l6, &ll1, &l9 }; + FFI_CALL(cif,ll_l6ll,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 75 + llr = ll_l7ll(l1,l2,l3,l4,l5,l6,l7,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &l6, &l7, &ll1, &l9 }; + FFI_CALL(cif,ll_l7ll,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 76 + dr = d_l2d(l1,l2,d2,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &l1, &l2, &d2, &l9 }; + FFI_CALL(cif,d_l2d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 77 + dr = d_l3d(l1,l2,l3,d2,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &d2, &l9 }; + FFI_CALL(cif,d_l3d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 78 + dr = d_l4d(l1,l2,l3,l4,d2,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &d2, &l9 }; + FFI_CALL(cif,d_l4d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 79 + dr = d_l5d(l1,l2,l3,l4,l5,d2,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &d2, &l9 }; + FFI_CALL(cif,d_l5d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 80 + dr = d_l6d(l1,l2,l3,l4,l5,l6,d2,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &l6, &d2, &l9 }; + FFI_CALL(cif,d_l6d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 81 + dr = d_l7d(l1,l2,l3,l4,l5,l6,l7,d2,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &l6, &l7, &d2, &l9 }; + FFI_CALL(cif,d_l7d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + return; +} + +int + main (void) +{ + ffi_type_char = (char)(-1) < 0 ? ffi_type_schar : ffi_type_uchar; + out = stdout; + + void_tests(); + int_tests(); + float_tests(); + double_tests(); + pointer_tests(); + mixed_number_tests(); + small_structure_return_tests(); + structure_tests(); + gpargs_boundary_tests(); + + exit(0); +} diff --git a/libffi/testsuite/libffi.bhaible/test-callback.c b/libffi/testsuite/libffi.bhaible/test-callback.c new file mode 100644 index 0000000..0b16799 --- /dev/null +++ b/libffi/testsuite/libffi.bhaible/test-callback.c @@ -0,0 +1,2885 @@ +/* + * Copyright 1993 Bill Triggs <Bill.Triggs@inrialpes.fr> + * Copyright 1995-2017 Bruno Haible <bruno@clisp.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* { dg-do run { xfail gccbug } } */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ffi.h> +#include "alignof.h" +#include <stdarg.h> + +/* libffi testsuite local changes -------------------------------- */ +#ifdef DGTEST +/* Redefine exit(1) as a test failure */ +#define exit(V) (void)((V) ? (abort(), 1) : exit(0)) +int count = 0; +char rbuf1[2048]; +char rbuf2[2048]; +int _fprintf(FILE *stream, const char *format, ...) +{ + va_list args; + va_start(args, format); + + switch (count++) + { + case 0: + case 1: + vsprintf(&rbuf1[strlen(rbuf1)], format, args); + break; + case 2: + printf("%s", rbuf1); + vsprintf(rbuf2, format, args); + break; + case 3: + vsprintf(&rbuf2[strlen(rbuf2)], format, args); + printf("%s", rbuf2); + if (strcmp (rbuf1, rbuf2)) abort(); + break; + } + + va_end(args); + + return 0; +} +#define fprintf _fprintf +#endif +/* --------------------------------------------------------------- */ + +#include "testcases.c" + +#ifndef ABI_NUM +#define ABI_NUM FFI_DEFAULT_ABI +#endif + +/* Definitions that ought to be part of libffi. */ +static ffi_type ffi_type_char; +#define ffi_type_slonglong ffi_type_sint64 +#define ffi_type_ulonglong ffi_type_uint64 + +/* libffi does not support arrays inside structs. */ +#define SKIP_EXTRA_STRUCTS + +#define FFI_PREP_CIF(cif,argtypes,rettype) \ + if (ffi_prep_cif(&(cif),ABI_NUM,sizeof(argtypes)/sizeof(argtypes[0]),&rettype,argtypes) != FFI_OK) abort() +#define FFI_PREP_CIF_NOARGS(cif,rettype) \ + if (ffi_prep_cif(&(cif),ABI_NUM,0,&rettype,NULL) != FFI_OK) abort() + +#if defined(__sparc__) && defined(__sun) && defined(__SUNPRO_C) /* SUNWspro cc */ +/* SunPRO cc miscompiles the simulator function for X_BcdB: d.i[1] is + * temporarily stored in %l2 and put onto the stack from %l2, but in between + * the copy of X has used %l2 as a counter without saving and restoring its + * value. + */ +#define SKIP_X +#endif +#if defined(__mipsn32__) && !defined(__GNUC__) +/* The X test crashes for an unknown reason. */ +#define SKIP_X +#endif + + +/* These functions simulate the behaviour of the functions defined in testcases.c. */ + +/* void tests */ +void v_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&v_v) { fprintf(out,"wrong data for v_v\n"); exit(1); } + fprintf(out,"void f(void):\n"); + fflush(out); +} + +/* int tests */ +void i_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&i_v) { fprintf(out,"wrong data for i_v\n"); exit(1); } + {int r=99; + fprintf(out,"int f(void):"); + fflush(out); + *(ffi_arg*)retp = r; +}} +void i_i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&i_i) { fprintf(out,"wrong data for i_i\n"); exit(1); } + int a = *(int*)(*args++); + int r=a+1; + fprintf(out,"int f(int):(%d)",a); + fflush(out); + *(ffi_arg*)retp = r; +} +void i_i2_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&i_i2) { fprintf(out,"wrong data for i_i2\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + int r=a+b; + fprintf(out,"int f(2*int):(%d,%d)",a,b); + fflush(out); + *(ffi_arg*)retp = r; +}} +void i_i4_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&i_i4) { fprintf(out,"wrong data for i_i4\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + int c = *(int*)(*args++); + int d = *(int*)(*args++); + int r=a+b+c+d; + fprintf(out,"int f(4*int):(%d,%d,%d,%d)",a,b,c,d); + fflush(out); + *(ffi_arg*)retp = r; +}} +void i_i8_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&i_i8) { fprintf(out,"wrong data for i_i8\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + int c = *(int*)(*args++); + int d = *(int*)(*args++); + int e = *(int*)(*args++); + int f = *(int*)(*args++); + int g = *(int*)(*args++); + int h = *(int*)(*args++); + int r=a+b+c+d+e+f+g+h; + fprintf(out,"int f(8*int):(%d,%d,%d,%d,%d,%d,%d,%d)",a,b,c,d,e,f,g,h); + fflush(out); + *(ffi_arg*)retp = r; +}} +void i_i16_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&i_i16) { fprintf(out,"wrong data for i_i16\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + int c = *(int*)(*args++); + int d = *(int*)(*args++); + int e = *(int*)(*args++); + int f = *(int*)(*args++); + int g = *(int*)(*args++); + int h = *(int*)(*args++); + int i = *(int*)(*args++); + int j = *(int*)(*args++); + int k = *(int*)(*args++); + int l = *(int*)(*args++); + int m = *(int*)(*args++); + int n = *(int*)(*args++); + int o = *(int*)(*args++); + int p = *(int*)(*args++); + int r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p; + fprintf(out,"int f(16*int):(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)", + a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); + fflush(out); + *(ffi_arg*)retp = r; +}} + +/* float tests */ +void f_f_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f) { fprintf(out,"wrong data for f_f\n"); exit(1); } + {float a = *(float*)(*args++); + float r=a+1.0; + fprintf(out,"float f(float):(%g)",a); + fflush(out); + *(float*)retp = r; +}} +void f_f2_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f2) { fprintf(out,"wrong data for f_f2\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float r=a+b; + fprintf(out,"float f(2*float):(%g,%g)",a,b); + fflush(out); + *(float*)retp = r; +}} +void f_f4_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f4) { fprintf(out,"wrong data for f_f4\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float r=a+b+c+d; + fprintf(out,"float f(4*float):(%g,%g,%g,%g)",a,b,c,d); + fflush(out); + *(float*)retp = r; +}} +void f_f8_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f8) { fprintf(out,"wrong data for f_f8\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + float r=a+b+c+d+e+f+g+h; + fprintf(out,"float f(8*float):(%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h); + fflush(out); + *(float*)retp = r; +}} +void f_f16_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f16) { fprintf(out,"wrong data for f_f16\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + float i = *(float*)(*args++); + float j = *(float*)(*args++); + float k = *(float*)(*args++); + float l = *(float*)(*args++); + float m = *(float*)(*args++); + float n = *(float*)(*args++); + float o = *(float*)(*args++); + float p = *(float*)(*args++); + float r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p; + fprintf(out,"float f(16*float):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); + fflush(out); + *(float*)retp = r; +}} +void f_f24_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f24) { fprintf(out,"wrong data for f_f24\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + float i = *(float*)(*args++); + float j = *(float*)(*args++); + float k = *(float*)(*args++); + float l = *(float*)(*args++); + float m = *(float*)(*args++); + float n = *(float*)(*args++); + float o = *(float*)(*args++); + float p = *(float*)(*args++); + float q = *(float*)(*args++); + float s = *(float*)(*args++); + float t = *(float*)(*args++); + float u = *(float*)(*args++); + float v = *(float*)(*args++); + float w = *(float*)(*args++); + float x = *(float*)(*args++); + float y = *(float*)(*args++); + float r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+s+t+u+v+w+x+y; + fprintf(out,"float f(24*float):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,v,w,x,y); + fflush(out); + *(float*)retp = r; +}} + +/* double tests */ +void d_d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d) { fprintf(out,"wrong data for d_d\n"); exit(1); } + {double a = *(double*)(*args++); + double r=a+1.0; + fprintf(out,"double f(double):(%g)",a); + fflush(out); + *(double*)retp = r; +}} +void d_d2_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d2) { fprintf(out,"wrong data for d_d2\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double r=a+b; + fprintf(out,"double f(2*double):(%g,%g)",a,b); + fflush(out); + *(double*)retp = r; +}} +void d_d4_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d4) { fprintf(out,"wrong data for d_d4\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double r=a+b+c+d; + fprintf(out,"double f(4*double):(%g,%g,%g,%g)",a,b,c,d); + fflush(out); + *(double*)retp = r; +}} +void d_d8_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d8) { fprintf(out,"wrong data for d_d8\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + double h = *(double*)(*args++); + double r=a+b+c+d+e+f+g+h; + fprintf(out,"double f(8*double):(%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h); + fflush(out); + *(double*)retp = r; +}} +void d_d16_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d16) { fprintf(out,"wrong data for d_d16\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + double h = *(double*)(*args++); + double i = *(double*)(*args++); + double j = *(double*)(*args++); + double k = *(double*)(*args++); + double l = *(double*)(*args++); + double m = *(double*)(*args++); + double n = *(double*)(*args++); + double o = *(double*)(*args++); + double p = *(double*)(*args++); + double r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p; + fprintf(out,"double f(16*double):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); + fflush(out); + *(double*)retp = r; +}} + +/* pointer tests */ +void vp_vpdpcpsp_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&vp_vpdpcpsp) { fprintf(out,"wrong data for vp_vpdpcpsp\n"); exit(1); } + {void* a = *(void* *)(*args++); + double* b = *(double* *)(*args++); + char* c = *(char* *)(*args++); + Int* d = *(Int* *)(*args++); + void* ret = (char*)b + 1; + fprintf(out,"void* f(void*,double*,char*,Int*):(0x%p,0x%p,0x%p,0x%p)",a,b,c,d); + fflush(out); + *(void* *)retp = ret; +}} + +/* mixed number tests */ +void uc_ucsil_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&uc_ucsil) { fprintf(out,"wrong data for uc_ucsil\n"); exit(1); } + {uchar a = *(unsigned char *)(*args++); + ushort b = *(unsigned short *)(*args++); + uint c = *(unsigned int *)(*args++); + ulong d = *(unsigned long *)(*args++); + uchar r = (uchar)-1; + fprintf(out,"uchar f(uchar,ushort,uint,ulong):(%u,%u,%u,%lu)",a,b,c,d); + fflush(out); + *(ffi_arg *)retp = r; +}} +void d_iidd_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_iidd) { fprintf(out,"wrong data for d_iidd\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double r=a+b+c+d; + fprintf(out,"double f(int,int,double,double):(%d,%d,%g,%g)",a,b,c,d); + fflush(out); + *(double*)retp = r; +}} +void d_iiidi_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_iiidi) { fprintf(out,"wrong data for d_iiidi\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + int c = *(int*)(*args++); + double d = *(double*)(*args++); + int e = *(int*)(*args++); + double r=a+b+c+d+e; + fprintf(out,"double f(int,int,int,double,int):(%d,%d,%d,%g,%d)",a,b,c,d,e); + fflush(out); + *(double*)retp = r; +}} +void d_idid_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_idid) { fprintf(out,"wrong data for d_idid\n"); exit(1); } + {int a = *(int*)(*args++); + double b = *(double*)(*args++); + int c = *(int*)(*args++); + double d = *(double*)(*args++); + double r=a+b+c+d; + fprintf(out,"double f(int,double,int,double):(%d,%g,%d,%g)",a,b,c,d); + fflush(out); + *(double*)retp = r; +}} +void d_fdi_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_fdi) { fprintf(out,"wrong data for d_fdi\n"); exit(1); } + {float a = *(float*)(*args++); + double b = *(double*)(*args++); + int c = *(int*)(*args++); + double r=a+b+c; + fprintf(out,"double f(float,double,int):(%g,%g,%d)",a,b,c); + fflush(out); + *(double*)retp = r; +}} +void us_cdcd_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&us_cdcd) { fprintf(out,"wrong data for us_cdcd\n"); exit(1); } + {char a = *(char*)(*args++); + double b = *(double*)(*args++); + char c = *(char*)(*args++); + double d = *(double*)(*args++); + ushort r = (ushort)(a + b + c + d); + fprintf(out,"ushort f(char,double,char,double):('%c',%g,'%c',%g)",a,b,c,d); + fflush(out); + *(ffi_arg *)retp = r; +}} +void ll_iiilli_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_iiilli) { fprintf(out,"wrong data for ll_iiilli\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + int c = *(int*)(*args++); + long long d = *(long long *)(*args++); + int e = *(int*)(*args++); + long long r = (long long)(int)a + (long long)(int)b + (long long)(int)c + d + (long long)e; + fprintf(out,"long long f(int,int,int,long long,int):(%d,%d,%d,0x%lx%08lx,%d)",a,b,c,(long)(d>>32),(long)(d&0xffffffff),e); + fflush(out); + *(long long *)retp = r; +}} +void ll_flli_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_flli) { fprintf(out,"wrong data for ll_flli\n"); exit(1); } + {float a = *(float*)(*args++); + long long b = *(long long *)(*args++); + int c = *(int*)(*args++); + long long r = (long long)(int)a + b + (long long)c; + fprintf(out,"long long f(float,long long,int):(%g,0x%lx%08lx,0x%lx)",a,(long)(b>>32),(long)(b&0xffffffff),(long)c); + fflush(out); + *(long long *)retp = r; +}} +void f_fi_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_fi) { fprintf(out,"wrong data for f_fi\n"); exit(1); } + {float a = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+z; + fprintf(out,"float f(float,int):(%g,%d)",a,z); + fflush(out); + *(float*)retp = r; +}} +void f_f2i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f2i) { fprintf(out,"wrong data for f_f2i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+z; + fprintf(out,"float f(2*float,int):(%g,%g,%d)",a,b,z); + fflush(out); + *(float*)retp = r; +}} +void f_f3i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f3i) { fprintf(out,"wrong data for f_f3i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+c+z; + fprintf(out,"float f(3*float,int):(%g,%g,%g,%d)",a,b,c,z); + fflush(out); + *(float*)retp = r; +}} +void f_f4i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f4i) { fprintf(out,"wrong data for f_f4i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+c+d+z; + fprintf(out,"float f(4*float,int):(%g,%g,%g,%g,%d)",a,b,c,d,z); + fflush(out); + *(float*)retp = r; +}} +void f_f7i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f7i) { fprintf(out,"wrong data for f_f7i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+c+d+e+f+g+z; + fprintf(out,"float f(7*float,int):(%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,z); + fflush(out); + *(float*)retp = r; +}} +void f_f8i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f8i) { fprintf(out,"wrong data for f_f8i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+c+d+e+f+g+h+z; + fprintf(out,"float f(8*float,int):(%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,z); + fflush(out); + *(float*)retp = r; +}} +void f_f12i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f12i) { fprintf(out,"wrong data for f_f12i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + float i = *(float*)(*args++); + float j = *(float*)(*args++); + float k = *(float*)(*args++); + float l = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+c+d+e+f+g+h+i+j+k+l+z; + fprintf(out,"float f(12*float,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,z); + fflush(out); + *(float*)retp = r; +}} +void f_f13i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f13i) { fprintf(out,"wrong data for f_f13i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + float i = *(float*)(*args++); + float j = *(float*)(*args++); + float k = *(float*)(*args++); + float l = *(float*)(*args++); + float m = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+c+d+e+f+g+h+i+j+k+l+m+z; + fprintf(out,"float f(13*float,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,m,z); + fflush(out); + *(float*)retp = r; +}} +void d_di_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_di) { fprintf(out,"wrong data for d_di\n"); exit(1); } + {double a = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+z; + fprintf(out,"double f(double,int):(%g,%d)",a,z); + fflush(out); + *(double*)retp = r; +}} +void d_d2i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d2i) { fprintf(out,"wrong data for d_d2i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+z; + fprintf(out,"double f(2*double,int):(%g,%g,%d)",a,b,z); + fflush(out); + *(double*)retp = r; +}} +void d_d3i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d3i) { fprintf(out,"wrong data for d_d3i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+c+z; + fprintf(out,"double f(3*double,int):(%g,%g,%g,%d)",a,b,c,z); + fflush(out); + *(double*)retp = r; +}} +void d_d4i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d4i) { fprintf(out,"wrong data for d_d4i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+c+d+z; + fprintf(out,"double f(4*double,int):(%g,%g,%g,%g,%d)",a,b,c,d,z); + fflush(out); + *(double*)retp = r; +}} +void d_d7i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d7i) { fprintf(out,"wrong data for d_d7i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+c+d+e+f+g+z; + fprintf(out,"double f(7*double,int):(%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,z); + fflush(out); + *(double*)retp = r; +}} +void d_d8i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d8i) { fprintf(out,"wrong data for d_d8i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + double h = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+c+d+e+f+g+h+z; + fprintf(out,"double f(8*double,int):(%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,z); + fflush(out); + *(double*)retp = r; +}} +void d_d12i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d12i) { fprintf(out,"wrong data for d_d12i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + double h = *(double*)(*args++); + double i = *(double*)(*args++); + double j = *(double*)(*args++); + double k = *(double*)(*args++); + double l = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+c+d+e+f+g+h+i+j+k+l+z; + fprintf(out,"double f(12*double,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,z); + fflush(out); + *(double*)retp = r; +}} +void d_d13i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d13i) { fprintf(out,"wrong data for d_d13i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + double h = *(double*)(*args++); + double i = *(double*)(*args++); + double j = *(double*)(*args++); + double k = *(double*)(*args++); + double l = *(double*)(*args++); + double m = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+c+d+e+f+g+h+i+j+k+l+m+z; + fprintf(out,"double f(13*double,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,m,z); + fflush(out); + *(double*)retp = r; +}} + +/* small structure return tests */ +void S1_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S1_v) { fprintf(out,"wrong data for S1_v\n"); exit(1); } + {Size1 r = Size1_1; + fprintf(out,"Size1 f(void):"); + fflush(out); + *(Size1*)retp = r; +}} +void S2_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S2_v) { fprintf(out,"wrong data for S2_v\n"); exit(1); } + {Size2 r = Size2_1; + fprintf(out,"Size2 f(void):"); + fflush(out); + *(Size2*)retp = r; +}} +void S3_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S3_v) { fprintf(out,"wrong data for S3_v\n"); exit(1); } + {Size3 r = Size3_1; + fprintf(out,"Size3 f(void):"); + fflush(out); + *(Size3*)retp = r; +}} +void S4_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S4_v) { fprintf(out,"wrong data for S4_v\n"); exit(1); } + {Size4 r = Size4_1; + fprintf(out,"Size4 f(void):"); + fflush(out); + *(Size4*)retp = r; +}} +void S7_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S7_v) { fprintf(out,"wrong data for S7_v\n"); exit(1); } + {Size7 r = Size7_1; + fprintf(out,"Size7 f(void):"); + fflush(out); + *(Size7*)retp = r; +}} +void S8_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S8_v) { fprintf(out,"wrong data for S8_v\n"); exit(1); } + {Size8 r = Size8_1; + fprintf(out,"Size8 f(void):"); + fflush(out); + *(Size8*)retp = r; +}} +void S12_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S12_v) { fprintf(out,"wrong data for S12_v\n"); exit(1); } + {Size12 r = Size12_1; + fprintf(out,"Size12 f(void):"); + fflush(out); + *(Size12*)retp = r; +}} +void S15_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S15_v) { fprintf(out,"wrong data for S15_v\n"); exit(1); } + {Size15 r = Size15_1; + fprintf(out,"Size15 f(void):"); + fflush(out); + *(Size15*)retp = r; +}} +void S16_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S16_v) { fprintf(out,"wrong data for S16_v\n"); exit(1); } + {Size16 r = Size16_1; + fprintf(out,"Size16 f(void):"); + fflush(out); + *(Size16*)retp = r; +}} + +/* structure tests */ +void I_III_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&I_III) { fprintf(out,"wrong data for I_III\n"); exit(1); } + {Int a = *(Int*)(*args++); + Int b = *(Int*)(*args++); + Int c = *(Int*)(*args++); + Int r; + r.x = a.x + b.x + c.x; + fprintf(out,"Int f(Int,Int,Int):({%d},{%d},{%d})",a.x,b.x,c.x); + fflush(out); + *(Int*)retp = r; +}} +void C_CdC_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&C_CdC) { fprintf(out,"wrong data for C_CdC\n"); exit(1); } + {Char a = *(Char*)(*args++); + double b = *(double*)(*args++); + Char c = *(Char*)(*args++); + Char r; + r.x = (a.x + c.x)/2; + fprintf(out,"Char f(Char,double,Char):({'%c'},%g,{'%c'})",a.x,b,c.x); + fflush(out); + *(Char*)retp = r; +}} +void F_Ffd_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&F_Ffd) { fprintf(out,"wrong data for F_Ffd\n"); exit(1); } + {Float a = *(Float*)(*args++); + float b = *(float*)(*args++); + double c = *(double*)(*args++); + Float r; + r.x = a.x + b + c; + fprintf(out,"Float f(Float,float,double):({%g},%g,%g)",a.x,b,c); + fflush(out); + *(Float*)retp = r; +}} +void D_fDd_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&D_fDd) { fprintf(out,"wrong data for D_fDd\n"); exit(1); } + {float a = *(float*)(*args++); + Double b = *(Double*)(*args++); + double c = *(double*)(*args++); + Double r; + r.x = a + b.x + c; + fprintf(out,"Double f(float,Double,double):(%g,{%g},%g)",a,b.x,c); + fflush(out); + *(Double*)retp = r; +}} +void D_Dfd_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&D_Dfd) { fprintf(out,"wrong data for D_Dfd\n"); exit(1); } + {Double a = *(Double*)(*args++); + float b = *(float*)(*args++); + double c = *(double*)(*args++); + Double r; + r.x = a.x + b + c; + fprintf(out,"Double f(Double,float,double):({%g},%g,%g)",a.x,b,c); + fflush(out); + *(Double*)retp = r; +}} +void J_JiJ_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&J_JiJ) { fprintf(out,"wrong data for J_JiJ\n"); exit(1); } + {J a = *(J*)(*args++); + int b= *(int*)(*args++); + J c = *(J*)(*args++); + J r; + r.l1 = a.l1+c.l1; r.l2 = a.l2+b+c.l2; + fprintf(out,"J f(J,int,J):({%ld,%ld},%d,{%ld,%ld})",a.l1,a.l2,b,c.l1,c.l2); + fflush(out); + *(J*)retp = r; +}} +#ifndef SKIP_EXTRA_STRUCTS +void T_TcT_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&T_TcT) { fprintf(out,"wrong data for T_TcT\n"); exit(1); } + {T a = *(T*)(*args++); + char b = *(char*)(*args++); + T c = *(T*)(*args++); + T r; + r.c[0]='b'; r.c[1]=c.c[1]; r.c[2]=c.c[2]; + fprintf(out,"T f(T,char,T):({\"%c%c%c\"},'%c',{\"%c%c%c\"})",a.c[0],a.c[1],a.c[2],b,c.c[0],c.c[1],c.c[2]); + fflush(out); + *(T*)retp = r; +}} +void X_BcdB_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&X_BcdB) { fprintf(out,"wrong data for X_BcdB\n"); exit(1); } + {B a = *(B*)(*args++); + char b = *(char*)(*args++); + double c = *(double*)(*args++); + B d = *(B*)(*args++); + static X xr={"return val",'R'}; + X r; + r = xr; + r.c1 = b; + fprintf(out,"X f(B,char,double,B):({%g,{%d,%d,%d}},'%c',%g,{%g,{%d,%d,%d}})", + a.d,a.i[0],a.i[1],a.i[2],b,c,d.d,d.i[0],d.i[1],d.i[2]); + fflush(out); + *(X*)retp = r; +}} +#endif + +/* gpargs boundary tests */ +void l_l0K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l0K) { fprintf(out,"wrong data for l_l0K\n"); exit(1); } + {K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(K,long):(%ld,%ld,%ld,%ld,%ld)",b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void l_l1K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l1K) { fprintf(out,"wrong data for l_l1K\n"); exit(1); } + {long a1 = *(long*)(*args++); + K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = a1 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld)",a1,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void l_l2K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l2K) { fprintf(out,"wrong data for l_l2K\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = a1 + a2 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(2*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void l_l3K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l3K) { fprintf(out,"wrong data for l_l3K\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = a1 + a2 + a3 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(3*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void l_l4K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l4K) { fprintf(out,"wrong data for l_l4K\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = a1 + a2 + a3 + a4 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(4*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,a4,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void l_l5K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l5K) { fprintf(out,"wrong data for l_l5K\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = a1 + a2 + a3 + a4 + a5 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(5*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,a4,a5,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void l_l6K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l6K) { fprintf(out,"wrong data for l_l6K\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + long a6 = *(long*)(*args++); + K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = a1 + a2 + a3 + a4 + a5 + a6 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(6*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,a4,a5,a6,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void f_f17l3L_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f17l3L) { fprintf(out,"wrong data for f_f17l3L\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + float i = *(float*)(*args++); + float j = *(float*)(*args++); + float k = *(float*)(*args++); + float l = *(float*)(*args++); + float m = *(float*)(*args++); + float n = *(float*)(*args++); + float o = *(float*)(*args++); + float p = *(float*)(*args++); + float q = *(float*)(*args++); + long s = *(long*)(*args++); + long t = *(long*)(*args++); + long u = *(long*)(*args++); + L z = *(L*)(*args++); + float r = a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+s+t+u+z.l1+z.l2+z.l3+z.l4+z.l5+z.l6; + fprintf(out,"float f(17*float,3*int,L):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,z.l1,z.l2,z.l3,z.l4,z.l5,z.l6); + fflush(out); + *(float*)retp = r; +}} +void d_d17l3L_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d17l3L) { fprintf(out,"wrong data for d_d17l3L\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + double h = *(double*)(*args++); + double i = *(double*)(*args++); + double j = *(double*)(*args++); + double k = *(double*)(*args++); + double l = *(double*)(*args++); + double m = *(double*)(*args++); + double n = *(double*)(*args++); + double o = *(double*)(*args++); + double p = *(double*)(*args++); + double q = *(double*)(*args++); + long s = *(long*)(*args++); + long t = *(long*)(*args++); + long u = *(long*)(*args++); + L z = *(L*)(*args++); + double r = a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+s+t+u+z.l1+z.l2+z.l3+z.l4+z.l5+z.l6; + fprintf(out,"double f(17*double,3*int,L):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,z.l1,z.l2,z.l3,z.l4,z.l5,z.l6); + fflush(out); + *(double*)retp = r; +}} +void ll_l2ll_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_l2ll) { fprintf(out,"wrong data for ll_l2ll\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long long b = *(long long *)(*args++); + long c = *(long*)(*args++); + long long r = (long long) (a1 + a2) + b + c; + fprintf(out,"long long f(2*long,long long,long):(%ld,%ld,0x%lx%08lx,%ld)",a1,a2,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + *(long long *)retp = r; +}} +void ll_l3ll_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_l3ll) { fprintf(out,"wrong data for ll_l3ll\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long long b = *(long long *)(*args++); + long c = *(long*)(*args++); + long long r = (long long) (a1 + a2 + a3) + b + c; + fprintf(out,"long long f(3*long,long long,long):(%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + *(long long *)retp = r; +}} +void ll_l4ll_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_l4ll) { fprintf(out,"wrong data for ll_l4ll\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long long b = *(long long *)(*args++); + long c = *(long*)(*args++); + long long r = (long long) (a1 + a2 + a3 + a4) + b + c; + fprintf(out,"long long f(4*long,long long,long):(%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + *(long long *)retp = r; +}} +void ll_l5ll_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_l5ll) { fprintf(out,"wrong data for ll_l5ll\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + long long b = *(long long *)(*args++); + long c = *(long*)(*args++); + long long r = (long long) (a1 + a2 + a3 + a4 + a5) + b + c; + fprintf(out,"long long f(5*long,long long,long):(%ld,%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,a5,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + *(long long *)retp = r; +}} +void ll_l6ll_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_l6ll) { fprintf(out,"wrong data for ll_l6ll\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + long a6 = *(long*)(*args++); + long long b = *(long long *)(*args++); + long c = *(long*)(*args++); + long long r = (long long) (a1 + a2 + a3 + a4 + a5 + a6) + b + c; + fprintf(out,"long long f(6*long,long long,long):(%ld,%ld,%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,a5,a6,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + *(long long *)retp = r; +}} +void ll_l7ll_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_l7ll) { fprintf(out,"wrong data for ll_l7ll\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + long a6 = *(long*)(*args++); + long a7 = *(long*)(*args++); + long long b = *(long long *)(*args++); + long c = *(long*)(*args++); + long long r = (long long) (a1 + a2 + a3 + a4 + a5 + a6 + a7) + b + c; + fprintf(out,"long long f(7*long,long long,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,a5,a6,a7,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + *(long long *)retp = r; +}} +void d_l2d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_l2d) { fprintf(out,"wrong data for d_l2d\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + double b = *(double*)(*args++); + long c = *(long*)(*args++); + double r = (double) (a1 + a2) + b + c; + fprintf(out,"double f(2*long,double,long):(%ld,%ld,%g,%ld)",a1,a2,b,c); + fflush(out); + *(double*)retp = r; +}} +void d_l3d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_l3d) { fprintf(out,"wrong data for d_l3d\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + double b = *(double*)(*args++); + long c = *(long*)(*args++); + double r = (double) (a1 + a2 + a3) + b + c; + fprintf(out,"double f(3*long,double,long):(%ld,%ld,%ld,%g,%ld)",a1,a2,a3,b,c); + fflush(out); + *(double*)retp = r; +}} +void d_l4d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_l4d) { fprintf(out,"wrong data for d_l4d\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + double b = *(double*)(*args++); + long c = *(long*)(*args++); + double r = (double) (a1 + a2 + a3 + a4) + b + c; + fprintf(out,"double f(4*long,double,long):(%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,b,c); + fflush(out); + *(double*)retp = r; +}} +void d_l5d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_l5d) { fprintf(out,"wrong data for d_l5d\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + double b = *(double*)(*args++); + long c = *(long*)(*args++); + double r = (double) (a1 + a2 + a3 + a4 + a5) + b + c; + fprintf(out,"double f(5*long,double,long):(%ld,%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,a5,b,c); + fflush(out); + *(double*)retp = r; +}} +void d_l6d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_l6d) { fprintf(out,"wrong data for d_l6d\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + long a6 = *(long*)(*args++); + double b = *(double*)(*args++); + long c = *(long*)(*args++); + double r = (double) (a1 + a2 + a3 + a4 + a5 + a6) + b + c; + fprintf(out,"double f(6*long,double,long):(%ld,%ld,%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,a5,a6,b,c); + fflush(out); + *(double*)retp = r; +}} +void d_l7d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_l7d) { fprintf(out,"wrong data for d_l7d\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + long a6 = *(long*)(*args++); + long a7 = *(long*)(*args++); + double b = *(double*)(*args++); + long c = *(long*)(*args++); + double r = (double) (a1 + a2 + a3 + a4 + a5 + a6 + a7) + b + c; + fprintf(out,"double f(7*long,double,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,a5,a6,a7,b,c); + fflush(out); + *(double*)retp = r; +}} + + +/* + * The way we run these tests - first call the function directly, then + * through vacall() - there is the danger that arguments or results seem + * to be passed correctly, but what we are seeing are in fact the vestiges + * (traces) or the previous call. This may seriously fake the test. + * Avoid this by clearing the registers between the first and the second call. + */ +long clear_traces_i (long a, long b, long c, long d, long e, long f, long g, long h, + long i, long j, long k, long l, long m, long n, long o, long p) +{ return 0; } +float clear_traces_f (float a, float b, float c, float d, float e, float f, float g, + float h, float i, float j, float k, float l, float m, float n, + float o, float p) +{ return 0.0; } +double clear_traces_d (double a, double b, double c, double d, double e, double f, double g, + double h, double i, double j, double k, double l, double m, double n, + double o, double p) +{ return 0.0; } +J clear_traces_J (void) +{ J j; j.l1 = j.l2 = 0; return j; } +void clear_traces (void) +{ clear_traces_i(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + clear_traces_f(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0); + clear_traces_d(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0); + clear_traces_J(); +} + +int main (void) +{ + void* callback_code; + void* callback_writable; +#define ALLOC_CALLBACK() \ + callback_writable = ffi_closure_alloc(sizeof(ffi_closure),&callback_code); \ + if (!callback_writable) abort() +#define PREP_CALLBACK(cif,simulator,data) \ + if (ffi_prep_closure_loc(callback_writable,&(cif),simulator,data,callback_code) != FFI_OK) abort() +#define FREE_CALLBACK() \ + ffi_closure_free(callback_writable) + + ffi_type_char = (char)(-1) < 0 ? ffi_type_schar : ffi_type_uchar; + out = stdout; + +#if (!defined(DGTEST)) || DGTEST == 1 + /* void tests */ + v_v(); + clear_traces(); + ALLOC_CALLBACK(); + { + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_void); + PREP_CALLBACK(cif,v_v_simulator,(void*)&v_v); + ((void (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); +#endif + + /* int tests */ + { int ir; + +#if (!defined(DGTEST)) || DGTEST == 2 + ir = i_v(); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_sint); + PREP_CALLBACK(cif,i_v_simulator,(void*)&i_v); + ir = ((int (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 3 + ir = i_i(i1); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + PREP_CALLBACK(cif,i_i_simulator,(void*)&i_i); + ir = ((int (ABI_ATTR *) (int)) callback_code) (i1); + } + FREE_CALLBACK(); + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 4 + ir = i_i2(i1,i2); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + PREP_CALLBACK(cif,i_i2_simulator,(void*)&i_i2); + ir = ((int (ABI_ATTR *) (int,int)) callback_code) (i1,i2); + } + FREE_CALLBACK(); + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 5 + ir = i_i4(i1,i2,i3,i4); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + PREP_CALLBACK(cif,i_i4_simulator,(void*)&i_i4); + ir = ((int (ABI_ATTR *) (int,int,int,int)) callback_code) (i1,i2,i3,i4); + } + FREE_CALLBACK(); + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 6 + ir = i_i8(i1,i2,i3,i4,i5,i6,i7,i8); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + PREP_CALLBACK(cif,i_i8_simulator,(void*)&i_i8); + ir = ((int (ABI_ATTR *) (int,int,int,int,int,int,int,int)) callback_code) (i1,i2,i3,i4,i5,i6,i7,i8); + } + FREE_CALLBACK(); + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 7 + ir = i_i16(i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + PREP_CALLBACK(cif,i_i16_simulator,(void*)&i_i16); + ir = ((int (ABI_ATTR *) (int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int)) callback_code) (i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16); + } + FREE_CALLBACK(); + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + } + + /* float tests */ + { float fr; + +#if (!defined(DGTEST)) || DGTEST == 8 + fr = f_f(f1); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f_simulator,(void*)&f_f); + fr = ((float (ABI_ATTR *) (float)) callback_code) (f1); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 9 + fr = f_f2(f1,f2); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f2_simulator,(void*)&f_f2); + fr = ((float (ABI_ATTR *) (float,float)) callback_code) (f1,f2); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 10 + fr = f_f4(f1,f2,f3,f4); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f4_simulator,(void*)&f_f4); + fr = ((float (ABI_ATTR *) (float,float,float,float)) callback_code) (f1,f2,f3,f4); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 11 + fr = f_f8(f1,f2,f3,f4,f5,f6,f7,f8); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f8_simulator,(void*)&f_f8); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,float)) callback_code) (f1,f2,f3,f4,f5,f6,f7,f8); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 12 + fr = f_f16(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f16_simulator,(void*)&f_f16); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float)) callback_code) (f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 13 + fr = f_f24(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f24_simulator,(void*)&f_f24); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float)) callback_code) (f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + + } + + /* double tests */ + { double dr; + +#if (!defined(DGTEST)) || DGTEST == 14 + dr = d_d(d1); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d_simulator,(void*)&d_d); + dr = ((double (ABI_ATTR *) (double)) callback_code) (d1); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 15 + dr = d_d2(d1,d2); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d2_simulator,(void*)&d_d2); + dr = ((double (ABI_ATTR *) (double,double)) callback_code) (d1,d2); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 16 + dr = d_d4(d1,d2,d3,d4); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d4_simulator,(void*)&d_d4); + dr = ((double (ABI_ATTR *) (double,double,double,double)) callback_code) (d1,d2,d3,d4); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 17 + dr = d_d8(d1,d2,d3,d4,d5,d6,d7,d8); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d8_simulator,(void*)&d_d8); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,double)) callback_code) (d1,d2,d3,d4,d5,d6,d7,d8); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 18 + dr = d_d16(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d16_simulator,(void*)&d_d16); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,double,double,double,double,double,double,double,double,double)) callback_code) (d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + } + + /* pointer tests */ + { void* vpr; + +#if (!defined(DGTEST)) || DGTEST == 19 + vpr = vp_vpdpcpsp(&uc1,&d2,str3,&I4); + fprintf(out,"->0x%p\n",vpr); + fflush(out); + vpr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_pointer, &ffi_type_pointer, &ffi_type_pointer, &ffi_type_pointer }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_pointer); + PREP_CALLBACK(cif,vp_vpdpcpsp_simulator,(void*)&vp_vpdpcpsp); + vpr = ((void* (ABI_ATTR *) (void*,double*,char*,Int*)) callback_code) (&uc1,&d2,str3,&I4); + } + FREE_CALLBACK(); + fprintf(out,"->0x%p\n",vpr); + fflush(out); +#endif + } + + /* mixed number tests */ + { uchar ucr; + ushort usr; + float fr; + double dr; + long long llr; + +#if (!defined(DGTEST)) || DGTEST == 20 + ucr = uc_ucsil(uc1,us2,ui3,ul4); + fprintf(out,"->%u\n",ucr); + fflush(out); + ucr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_uchar, &ffi_type_ushort, &ffi_type_uint, &ffi_type_ulong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_uchar); + PREP_CALLBACK(cif,uc_ucsil_simulator,(void*)&uc_ucsil); + ucr = ((uchar (ABI_ATTR *) (uchar,ushort,uint,ulong)) callback_code) (uc1,us2,ui3,ul4); + } + FREE_CALLBACK(); + fprintf(out,"->%u\n",ucr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 21 + dr = d_iidd(i1,i2,d3,d4); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_iidd_simulator,(void*)&d_iidd); + dr = ((double (ABI_ATTR *) (int,int,double,double)) callback_code) (i1,i2,d3,d4); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 22 + dr = d_iiidi(i1,i2,i3,d4,i5); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_iiidi_simulator,(void*)&d_iiidi); + dr = ((double (ABI_ATTR *) (int,int,int,double,int)) callback_code) (i1,i2,i3,d4,i5); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 23 + dr = d_idid(i1,d2,i3,d4); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_double, &ffi_type_sint, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_idid_simulator,(void*)&d_idid); + dr = ((double (ABI_ATTR *) (int,double,int,double)) callback_code) (i1,d2,i3,d4); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 24 + dr = d_fdi(f1,d2,i3); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_fdi_simulator,(void*)&d_fdi); + dr = ((double (ABI_ATTR *) (float,double,int)) callback_code) (f1,d2,i3); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 25 + usr = us_cdcd(c1,d2,c3,d4); + fprintf(out,"->%u\n",usr); + fflush(out); + usr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_char, &ffi_type_double, &ffi_type_char, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_ushort); + PREP_CALLBACK(cif,us_cdcd_simulator,(void*)&us_cdcd); + usr = ((ushort (ABI_ATTR *) (char,double,char,double)) callback_code) (c1,d2,c3,d4); + } + FREE_CALLBACK(); + fprintf(out,"->%u\n",usr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 26 + llr = ll_iiilli(i1,i2,i3,ll1,i13); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_slonglong, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_iiilli_simulator,(void*)&ll_iiilli); + llr = ((long long (ABI_ATTR *) (int,int,int,long long,int)) callback_code) (i1,i2,i3,ll1,i13); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 27 + llr = ll_flli(f13,ll1,i13); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_slonglong, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_flli_simulator,(void*)&ll_flli); + llr = ((long long (ABI_ATTR *) (float,long long,int)) callback_code) (f13,ll1,i13); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 28 + fr = f_fi(f1,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_fi_simulator,(void*)&f_fi); + fr = ((float (ABI_ATTR *) (float,int)) callback_code) (f1,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 29 + fr = f_f2i(f1,f2,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f2i_simulator,(void*)&f_f2i); + fr = ((float (ABI_ATTR *) (float,float,int)) callback_code) (f1,f2,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 30 + fr = f_f3i(f1,f2,f3,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f3i_simulator,(void*)&f_f3i); + fr = ((float (ABI_ATTR *) (float,float,float,int)) callback_code) (f1,f2,f3,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 31 + fr = f_f4i(f1,f2,f3,f4,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f4i_simulator,(void*)&f_f4i); + fr = ((float (ABI_ATTR *) (float,float,float,float,int)) callback_code) (f1,f2,f3,f4,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 32 + fr = f_f7i(f1,f2,f3,f4,f5,f6,f7,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f7i_simulator,(void*)&f_f7i); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,int)) callback_code) (f1,f2,f3,f4,f5,f6,f7,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 33 + fr = f_f8i(f1,f2,f3,f4,f5,f6,f7,f8,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f8i_simulator,(void*)&f_f8i); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,float,int)) callback_code) (f1,f2,f3,f4,f5,f6,f7,f8,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 34 + fr = f_f13i(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f13i_simulator,(void*)&f_f13i); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,float,float,float,float,float,float,int)) callback_code) (f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 35 + dr = d_di(d1,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_di_simulator,(void*)&d_di); + dr = ((double (ABI_ATTR *) (double,int)) callback_code) (d1,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 36 + dr = d_d2i(d1,d2,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d2i_simulator,(void*)&d_d2i); + dr = ((double (ABI_ATTR *) (double,double,int)) callback_code) (d1,d2,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 37 + dr = d_d3i(d1,d2,d3,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d3i_simulator,(void*)&d_d3i); + dr = ((double (ABI_ATTR *) (double,double,double,int)) callback_code) (d1,d2,d3,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 38 + dr = d_d4i(d1,d2,d3,d4,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d4i_simulator,(void*)&d_d4i); + dr = ((double (ABI_ATTR *) (double,double,double,double,int)) callback_code) (d1,d2,d3,d4,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 39 + dr = d_d7i(d1,d2,d3,d4,d5,d6,d7,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d7i_simulator,(void*)&d_d7i); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,int)) callback_code) (d1,d2,d3,d4,d5,d6,d7,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 40 + dr = d_d8i(d1,d2,d3,d4,d5,d6,d7,d8,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d8i_simulator,(void*)&d_d8i); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,double,int)) callback_code) (d1,d2,d3,d4,d5,d6,d7,d8,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 41 + dr = d_d12i(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d12i_simulator,(void*)&d_d12i); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,double,double,double,double,double,int)) callback_code) (d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 42 + dr = d_d13i(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d13i_simulator,(void*)&d_d13i); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,double,double,double,double,double,double,int)) callback_code) (d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + } + + /* small structure return tests */ +#if (!defined(DGTEST)) || DGTEST == 43 + { + Size1 r = S1_v(); + fprintf(out,"->{%c}\n",r.x1); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size1_elements[] = { &ffi_type_char, NULL }; + ffi_type ffi_type_Size1; + ffi_type_Size1.type = FFI_TYPE_STRUCT; + ffi_type_Size1.size = sizeof(Size1); + ffi_type_Size1.alignment = alignof_slot(Size1); + ffi_type_Size1.elements = ffi_type_Size1_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size1); + PREP_CALLBACK(cif,S1_v_simulator,(void*)&S1_v); + r = ((Size1 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c}\n",r.x1); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 44 + { + Size2 r = S2_v(); + fprintf(out,"->{%c%c}\n",r.x1,r.x2); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size2_elements[] = { &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size2; + ffi_type_Size2.type = FFI_TYPE_STRUCT; + ffi_type_Size2.size = sizeof(Size2); + ffi_type_Size2.alignment = alignof_slot(Size2); + ffi_type_Size2.elements = ffi_type_Size2_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size2); + PREP_CALLBACK(cif,S2_v_simulator,(void*)&S2_v); + r = ((Size2 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c}\n",r.x1,r.x2); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 45 + { + Size3 r = S3_v(); + fprintf(out,"->{%c%c%c}\n",r.x1,r.x2,r.x3); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size3_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size3; + ffi_type_Size3.type = FFI_TYPE_STRUCT; + ffi_type_Size3.size = sizeof(Size3); + ffi_type_Size3.alignment = alignof_slot(Size3); + ffi_type_Size3.elements = ffi_type_Size3_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size3); + PREP_CALLBACK(cif,S3_v_simulator,(void*)&S3_v); + r = ((Size3 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c}\n",r.x1,r.x2,r.x3); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 46 + { + Size4 r = S4_v(); + fprintf(out,"->{%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size4_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size4; + ffi_type_Size4.type = FFI_TYPE_STRUCT; + ffi_type_Size4.size = sizeof(Size4); + ffi_type_Size4.alignment = alignof_slot(Size4); + ffi_type_Size4.elements = ffi_type_Size4_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size4); + PREP_CALLBACK(cif,S4_v_simulator,(void*)&S4_v); + r = ((Size4 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 47 + { + Size7 r = S7_v(); + fprintf(out,"->{%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size7_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size7; + ffi_type_Size7.type = FFI_TYPE_STRUCT; + ffi_type_Size7.size = sizeof(Size7); + ffi_type_Size7.alignment = alignof_slot(Size7); + ffi_type_Size7.elements = ffi_type_Size7_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size7); + PREP_CALLBACK(cif,S7_v_simulator,(void*)&S7_v); + r = ((Size7 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 48 + { + Size8 r = S8_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size8_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size8; + ffi_type_Size8.type = FFI_TYPE_STRUCT; + ffi_type_Size8.size = sizeof(Size8); + ffi_type_Size8.alignment = alignof_slot(Size8); + ffi_type_Size8.elements = ffi_type_Size8_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size8); + PREP_CALLBACK(cif,S8_v_simulator,(void*)&S8_v); + r = ((Size8 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 49 + { + Size12 r = S12_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size12_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size12; + ffi_type_Size12.type = FFI_TYPE_STRUCT; + ffi_type_Size12.size = sizeof(Size12); + ffi_type_Size12.alignment = alignof_slot(Size12); + ffi_type_Size12.elements = ffi_type_Size12_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size12); + PREP_CALLBACK(cif,S12_v_simulator,(void*)&S12_v); + r = ((Size12 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 50 + { + Size15 r = S15_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size15_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size15; + ffi_type_Size15.type = FFI_TYPE_STRUCT; + ffi_type_Size15.size = sizeof(Size15); + ffi_type_Size15.alignment = alignof_slot(Size15); + ffi_type_Size15.elements = ffi_type_Size15_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size15); + PREP_CALLBACK(cif,S15_v_simulator,(void*)&S15_v); + r = ((Size15 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 51 + { + Size16 r = S16_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15,r.x16); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size16_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size16; + ffi_type_Size16.type = FFI_TYPE_STRUCT; + ffi_type_Size16.size = sizeof(Size16); + ffi_type_Size16.alignment = alignof_slot(Size16); + ffi_type_Size16.elements = ffi_type_Size16_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size16); + PREP_CALLBACK(cif,S16_v_simulator,(void*)&S16_v); + r = ((Size16 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15,r.x16); + fflush(out); + } +#endif + + + /* structure tests */ + { Int Ir; + Char Cr; + Float Fr; + Double Dr; + J Jr; +#ifndef SKIP_EXTRA_STRUCTS + T Tr; + X Xr; +#endif + +#if (!defined(DGTEST)) || DGTEST == 52 + Ir = I_III(I1,I2,I3); + fprintf(out,"->{%d}\n",Ir.x); + fflush(out); + Ir.x = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Int_elements[] = { &ffi_type_sint, NULL }; + ffi_type ffi_type_Int; + ffi_type_Int.type = FFI_TYPE_STRUCT; + ffi_type_Int.size = sizeof(Int); + ffi_type_Int.alignment = alignof_slot(Int); + ffi_type_Int.elements = ffi_type_Int_elements; + ffi_type* argtypes[] = { &ffi_type_Int, &ffi_type_Int, &ffi_type_Int }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Int); + PREP_CALLBACK(cif,I_III_simulator,(void*)&I_III); + Ir = ((Int (ABI_ATTR *) (Int,Int,Int)) callback_code) (I1,I2,I3); + } + FREE_CALLBACK(); + fprintf(out,"->{%d}\n",Ir.x); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 53 + Cr = C_CdC(C1,d2,C3); + fprintf(out,"->{'%c'}\n",Cr.x); + fflush(out); + Cr.x = '\0'; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Char_elements[] = { &ffi_type_char, NULL }; + ffi_type ffi_type_Char; + ffi_type_Char.type = FFI_TYPE_STRUCT; + ffi_type_Char.size = sizeof(Char); + ffi_type_Char.alignment = alignof_slot(Char); + ffi_type_Char.elements = ffi_type_Char_elements; + ffi_type* argtypes[] = { &ffi_type_Char, &ffi_type_double, &ffi_type_Char }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Char); + PREP_CALLBACK(cif,C_CdC_simulator,(void*)&C_CdC); + Cr = ((Char (ABI_ATTR *) (Char,double,Char)) callback_code) (C1,d2,C3); + } + FREE_CALLBACK(); + fprintf(out,"->{'%c'}\n",Cr.x); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 54 + Fr = F_Ffd(F1,f2,d3); + fprintf(out,"->{%g}\n",Fr.x); + fflush(out); + Fr.x = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Float_elements[] = { &ffi_type_float, NULL }; + ffi_type ffi_type_Float; + ffi_type_Float.type = FFI_TYPE_STRUCT; + ffi_type_Float.size = sizeof(Float); + ffi_type_Float.alignment = alignof_slot(Float); + ffi_type_Float.elements = ffi_type_Float_elements; + ffi_type* argtypes[] = { &ffi_type_Float, &ffi_type_float, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Float); + PREP_CALLBACK(cif,F_Ffd_simulator,(void*)&F_Ffd); + Fr = ((Float (ABI_ATTR *) (Float,float,double)) callback_code) (F1,f2,d3); + } + FREE_CALLBACK(); + fprintf(out,"->{%g}\n",Fr.x); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 55 + Dr = D_fDd(f1,D2,d3); + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); + Dr.x = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Double_elements[] = { &ffi_type_double, NULL }; + ffi_type ffi_type_Double; + ffi_type_Double.type = FFI_TYPE_STRUCT; + ffi_type_Double.size = sizeof(Double); + ffi_type_Double.alignment = alignof_slot(Double); + ffi_type_Double.elements = ffi_type_Double_elements; + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_Double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Double); + PREP_CALLBACK(cif,D_fDd_simulator,(void*)&D_fDd); + Dr = ((Double (ABI_ATTR *) (float,Double,double)) callback_code) (f1,D2,d3); + } + FREE_CALLBACK(); + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 56 + Dr = D_Dfd(D1,f2,d3); + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); + Dr.x = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Double_elements[] = { &ffi_type_double, NULL }; + ffi_type ffi_type_Double; + ffi_type_Double.type = FFI_TYPE_STRUCT; + ffi_type_Double.size = sizeof(Double); + ffi_type_Double.alignment = alignof_slot(Double); + ffi_type_Double.elements = ffi_type_Double_elements; + ffi_type* argtypes[] = { &ffi_type_Double, &ffi_type_float, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Double); + PREP_CALLBACK(cif,D_Dfd_simulator,(void*)&D_Dfd); + Dr = ((Double (ABI_ATTR *) (Double,float,double)) callback_code) (D1,f2,d3); + } + FREE_CALLBACK(); + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 57 + Jr = J_JiJ(J1,i2,J2); + fprintf(out,"->{%ld,%ld}\n",Jr.l1,Jr.l2); + fflush(out); + Jr.l1 = Jr.l2 = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_J_elements[] = { &ffi_type_slong, &ffi_type_slong, NULL }; + ffi_type ffi_type_J; + ffi_type_J.type = FFI_TYPE_STRUCT; + ffi_type_J.size = sizeof(J); + ffi_type_J.alignment = alignof_slot(J); + ffi_type_J.elements = ffi_type_J_elements; + ffi_type* argtypes[] = { &ffi_type_J, &ffi_type_sint, &ffi_type_J }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_J); + PREP_CALLBACK(cif,J_JiJ_simulator,(void*)&J_JiJ); + Jr = ((J (ABI_ATTR *) (J,int,J)) callback_code) (J1,i2,J2); + } + FREE_CALLBACK(); + fprintf(out,"->{%ld,%ld}\n",Jr.l1,Jr.l2); + fflush(out); +#endif + +#ifndef SKIP_EXTRA_STRUCTS +#if (!defined(DGTEST)) || DGTEST == 58 + Tr = T_TcT(T1,' ',T2); + fprintf(out,"->{\"%c%c%c\"}\n",Tr.c[0],Tr.c[1],Tr.c[2]); + fflush(out); + Tr.c[0] = Tr.c[1] = Tr.c[2] = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_T_elements[] = { ??, NULL }; + ffi_type ffi_type_T; + ffi_type_T.type = FFI_TYPE_STRUCT; + ffi_type_T.size = sizeof(T); + ffi_type_T.alignment = alignof_slot(T); + ffi_type_T.elements = ffi_type_T_elements; + ffi_type* argtypes[] = { &ffi_type_T, &ffi_type_char, &ffi_type_T }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_T); + PREP_CALLBACK(cif,T_TcT_simulator,(void*)&T_TcT); + Tr = ((T (ABI_ATTR *) (T,char,T)) callback_code) (T1,' ',T2); + } + FREE_CALLBACK(); + fprintf(out,"->{\"%c%c%c\"}\n",Tr.c[0],Tr.c[1],Tr.c[2]); + fflush(out); +#endif + +#ifndef SKIP_X +#if (!defined(DGTEST)) || DGTEST == 59 + Xr = X_BcdB(B1,c2,d3,B2); + fprintf(out,"->{\"%s\",'%c'}\n",Xr.c,Xr.c1); + fflush(out); + Xr.c[0]=Xr.c1='\0'; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_X_elements[] = { ??, NULL }; + ffi_type ffi_type_X; + ffi_type_X.type = FFI_TYPE_STRUCT; + ffi_type_X.size = sizeof(X); + ffi_type_X.alignment = alignof_slot(X); + ffi_type_X.elements = ffi_type_X_elements; + ffi_type* argtypes[] = { &ffi_type_X, &ffi_type_char, &ffi_type_double, &ffi_type_X }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_X); + PREP_CALLBACK(cif,X_BcdB_simulator,(void*)&X_BcdB); + Xr = ((X (ABI_ATTR *) (B,char,double,B)) callback_code) (B1,c2,d3,B2); + } + FREE_CALLBACK(); + fprintf(out,"->{\"%s\",'%c'}\n",Xr.c,Xr.c1); + fflush(out); +#endif +#endif +#endif + } + + + /* gpargs boundary tests */ + { + ffi_type* ffi_type_K_elements[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, NULL }; + ffi_type ffi_type_K; + ffi_type* ffi_type_L_elements[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, NULL }; + ffi_type ffi_type_L; + long lr; + long long llr; + float fr; + double dr; + + ffi_type_K.type = FFI_TYPE_STRUCT; + ffi_type_K.size = sizeof(K); + ffi_type_K.alignment = alignof_slot(K); + ffi_type_K.elements = ffi_type_K_elements; + + ffi_type_L.type = FFI_TYPE_STRUCT; + ffi_type_L.size = sizeof(L); + ffi_type_L.alignment = alignof_slot(L); + ffi_type_L.elements = ffi_type_L_elements; + +#if (!defined(DGTEST)) || DGTEST == 60 + lr = l_l0K(K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l0K_simulator,(void*)l_l0K); + lr = ((long (ABI_ATTR *) (K,long)) callback_code) (K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 61 + lr = l_l1K(l1,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l1K_simulator,(void*)l_l1K); + lr = ((long (ABI_ATTR *) (long,K,long)) callback_code) (l1,K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 62 + lr = l_l2K(l1,l2,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l2K_simulator,(void*)l_l2K); + lr = ((long (ABI_ATTR *) (long,long,K,long)) callback_code) (l1,l2,K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 63 + lr = l_l3K(l1,l2,l3,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l3K_simulator,(void*)l_l3K); + lr = ((long (ABI_ATTR *) (long,long,long,K,long)) callback_code) (l1,l2,l3,K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 64 + lr = l_l4K(l1,l2,l3,l4,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l4K_simulator,(void*)l_l4K); + lr = ((long (ABI_ATTR *) (long,long,long,long,K,long)) callback_code) (l1,l2,l3,l4,K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 65 + lr = l_l5K(l1,l2,l3,l4,l5,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l5K_simulator,(void*)l_l5K); + lr = ((long (ABI_ATTR *) (long,long,long,long,long,K,long)) callback_code) (l1,l2,l3,l4,l5,K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 66 + lr = l_l6K(l1,l2,l3,l4,l5,l6,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l6K_simulator,(void*)l_l6K); + lr = ((long (ABI_ATTR *) (long,long,long,long,long,long,K,long)) callback_code) (l1,l2,l3,l4,l5,l6,K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 67 + fr = f_f17l3L(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,l6,l7,l8,L1); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_L }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f17l3L_simulator,(void*)&f_f17l3L); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,long,long,long,L)) callback_code) (f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,l6,l7,l8,L1); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 68 + dr = d_d17l3L(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17,l6,l7,l8,L1); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_L }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d17l3L_simulator,(void*)&d_d17l3L); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,double,double,double,double,double,double,double,double,double,double,long,long,long,L)) callback_code) (d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17,l6,l7,l8,L1); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 69 + llr = ll_l2ll(l1,l2,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_l2ll_simulator,(void*)ll_l2ll); + llr = ((long long (ABI_ATTR *) (long,long,long long,long)) callback_code) (l1,l2,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 70 + llr = ll_l3ll(l1,l2,l3,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_l3ll_simulator,(void*)ll_l3ll); + llr = ((long long (ABI_ATTR *) (long,long,long,long long,long)) callback_code) (l1,l2,l3,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 71 + llr = ll_l4ll(l1,l2,l3,l4,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_l4ll_simulator,(void*)ll_l4ll); + llr = ((long long (ABI_ATTR *) (long,long,long,long,long long,long)) callback_code) (l1,l2,l3,l4,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 72 + llr = ll_l5ll(l1,l2,l3,l4,l5,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_l5ll_simulator,(void*)ll_l5ll); + llr = ((long long (ABI_ATTR *) (long,long,long,long,long,long long,long)) callback_code) (l1,l2,l3,l4,l5,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 73 + llr = ll_l6ll(l1,l2,l3,l4,l5,l6,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_l6ll_simulator,(void*)ll_l6ll); + llr = ((long long (ABI_ATTR *) (long,long,long,long,long,long,long long,long)) callback_code) (l1,l2,l3,l4,l5,l6,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 74 + llr = ll_l7ll(l1,l2,l3,l4,l5,l6,l7,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_l7ll_simulator,(void*)ll_l7ll); + llr = ((long long (ABI_ATTR *) (long,long,long,long,long,long,long,long long,long)) callback_code) (l1,l2,l3,l4,l5,l6,l7,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 75 + dr = d_l2d(l1,l2,ll1,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_l2d_simulator,(void*)d_l2d); + dr = ((double (ABI_ATTR *) (long,long,double,long)) callback_code) (l1,l2,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 76 + dr = d_l3d(l1,l2,l3,ll1,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_l3d_simulator,(void*)d_l3d); + dr = ((double (ABI_ATTR *) (long,long,long,double,long)) callback_code) (l1,l2,l3,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 77 + dr = d_l4d(l1,l2,l3,l4,ll1,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_l4d_simulator,(void*)d_l4d); + dr = ((double (ABI_ATTR *) (long,long,long,long,double,long)) callback_code) (l1,l2,l3,l4,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 78 + dr = d_l5d(l1,l2,l3,l4,l5,ll1,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_l5d_simulator,(void*)d_l5d); + dr = ((double (ABI_ATTR *) (long,long,long,long,long,double,long)) callback_code) (l1,l2,l3,l4,l5,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 79 + dr = d_l6d(l1,l2,l3,l4,l5,l6,ll1,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_l6d_simulator,(void*)d_l6d); + dr = ((double (ABI_ATTR *) (long,long,long,long,long,long,double,long)) callback_code) (l1,l2,l3,l4,l5,l6,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 80 + dr = d_l7d(l1,l2,l3,l4,l5,l6,l7,ll1,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_l7d_simulator,(void*)d_l7d); + dr = ((double (ABI_ATTR *) (long,long,long,long,long,long,long,double,long)) callback_code) (l1,l2,l3,l4,l5,l6,l7,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + + } + + exit(0); +} + diff --git a/libffi/testsuite/libffi.bhaible/testcases.c b/libffi/testsuite/libffi.bhaible/testcases.c new file mode 100644 index 0000000..23a6f46 --- /dev/null +++ b/libffi/testsuite/libffi.bhaible/testcases.c @@ -0,0 +1,747 @@ +/* + * Copyright 1993 Bill Triggs <Bill.Triggs@inrialpes.fr> + * Copyright 1995-2017 Bruno Haible <bruno@clisp.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* This file defines test functions of selected signatures, that exercise + dark corners of the various ABIs. */ + +#include <stdio.h> + +FILE* out; + +#define uchar unsigned char +#define ushort unsigned short +#define uint unsigned int +#define ulong unsigned long + +typedef struct { char x; } Char; +typedef struct { short x; } Short; +typedef struct { int x; } Int; +typedef struct { long x; } Long; +typedef struct { float x; } Float; +typedef struct { double x; } Double; +typedef struct { char c; float f; } A; +typedef struct { double d; int i[3]; } B; +typedef struct { long l1; long l2; } J; +typedef struct { long l1; long l2; long l3; long l4; } K; +typedef struct { long l1; long l2; long l3; long l4; long l5; long l6; } L; +typedef struct { char x1; } Size1; +typedef struct { char x1; char x2; } Size2; +typedef struct { char x1; char x2; char x3; } Size3; +typedef struct { char x1; char x2; char x3; char x4; } Size4; +typedef struct { + char x1; char x2; char x3; char x4; char x5; char x6; char x7; +} Size7; +typedef struct { + char x1; char x2; char x3; char x4; char x5; char x6; char x7; char x8; +} Size8; +typedef struct { + char x1; char x2; char x3; char x4; char x5; char x6; char x7; char x8; + char x9; char x10; char x11; char x12; +} Size12; +typedef struct { + char x1; char x2; char x3; char x4; char x5; char x6; char x7; char x8; + char x9; char x10; char x11; char x12; char x13; char x14; char x15; +} Size15; +typedef struct { + char x1; char x2; char x3; char x4; char x5; char x6; char x7; char x8; + char x9; char x10; char x11; char x12; char x13; char x14; char x15; char x16; +} Size16; +typedef struct { char c[3]; } T; +typedef struct { char c[33],c1; } X; + +/* Don't use a number over 127, as some systems use signed chars and + the test case 25 doesn't account for this, resulting in undefined + behavior. See https://github.com/libffi/libffi/issues/598. */ +char c1='a', c2=127, c3=(char)1; + +short s1=32767, s2=(short)32768, s3=3, s4=4, s5=5, s6=6, s7=7, s8=8, s9=9; +int i1=1, i2=2, i3=3, i4=4, i5=5, i6=6, i7=7, i8=8, i9=9, + i10=11, i11=12, i12=13, i13=14, i14=15, i15=16, i16=17; +long l1=1, l2=2, l3=3, l4=4, l5=5, l6=6, l7=7, l8=8, l9=9; +long long ll1 = 3875056143130689530LL; +float f1=0.1f, f2=0.2f, f3=0.3f, f4=0.4f, f5=0.5f, f6=0.6f, f7=0.7f, f8=0.8f, f9=0.9f, + f10=1.1f, f11=1.2f, f12=1.3f, f13=1.4f, f14=1.5f, f15=1.6f, f16=1.7f, f17=1.8f, + f18=1.9f, f19=2.1f, f20=2.2f, f21=2.3f, f22=2.4f, f23=2.5f, f24=2.6f; +double d1=0.1, d2=0.2, d3=0.3, d4=0.4, d5=0.5, d6=0.6, d7=0.7, d8=0.8, d9=0.9, + d10=1.1, d11=1.2, d12=1.3, d13=1.4, d14=1.5, d15=1.6, d16=1.7, d17=1.8; + +uchar uc1='a', uc2=127, uc3=128, uc4=255, uc5=(uchar)-1; +ushort us1=1, us2=2, us3=3, us4=4, us5=5, us6=6, us7=7, us8=8, us9=9; +uint ui1=1, ui2=2, ui3=3, ui4=4, ui5=5, ui6=6, ui7=7, ui8=8, ui9=9; +ulong ul1=1, ul2=2, ul3=3, ul4=4, ul5=5, ul6=6, ul7=7, ul8=8, ul9=9; + +char *str1="hello",str2[]="goodbye",*str3="still here?"; +Char C1={'A'}, C2={'B'}, C3={'C'}, C4={'\377'}, C5={(char)(-1)}; +Short S1={1}, S2={2}, S3={3}, S4={4}, S5={5}, S6={6}, S7={7}, S8={8}, S9={9}; +Int I1={1}, I2={2}, I3={3}, I4={4}, I5={5}, I6={6}, I7={7}, I8={8}, I9={9}; +Float F1={0.1f}, F2={0.2f}, F3={0.3f}, F4={0.4f}, F5={0.5f}, F6={0.6f}, F7={0.7f}, F8={0.8f}, F9={0.9f}; +Double D1={0.1}, D2={0.2}, D3={0.3}, D4={0.4}, D5={0.5}, D6={0.6}, D7={0.7}, D8={0.8}, D9={0.9}; + +A A1={'a',0.1f},A2={'b',0.2f},A3={'\377',0.3f}; +B B1={0.1,{1,2,3}},B2={0.2,{5,4,3}}; +J J1={47,11},J2={73,55}; +K K1={19,69,12,28}; +L L1={561,1105,1729,2465,2821,6601}; /* A002997 */ +Size1 Size1_1={'a'}; +Size2 Size2_1={'a','b'}; +Size3 Size3_1={'a','b','c'}; +Size4 Size4_1={'a','b','c','d'}; +Size7 Size7_1={'a','b','c','d','e','f','g'}; +Size8 Size8_1={'a','b','c','d','e','f','g','h'}; +Size12 Size12_1={'a','b','c','d','e','f','g','h','i','j','k','l'}; +Size15 Size15_1={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o'}; +Size16 Size16_1={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'}; +T T1={{'t','h','e'}},T2={{'f','o','x'}}; +X X1={"abcdefghijklmnopqrstuvwxyzABCDEF",'G'}, X2={"123",'9'}, X3={"return-return-return",'R'}; + +#if defined(__GNUC__) +#define __STDCALL__ __attribute__((stdcall)) +#define __THISCALL__ __attribute__((thiscall)) +#define __FASTCALL__ __attribute__((fastcall)) +#define __MSABI__ __attribute__((ms_abi)) +#else +#define __STDCALL__ __stdcall +#define __THISCALL__ __thiscall +#define __FASTCALL__ __fastcall +#endif + +#ifndef ABI_ATTR +#define ABI_ATTR +#endif + +/* void tests */ +void ABI_ATTR v_v (void) +{ + fprintf(out,"void f(void):\n"); + fflush(out); +} + +/* int tests */ +int ABI_ATTR i_v (void) +{ + int r=99; + fprintf(out,"int f(void):"); + fflush(out); + return r; +} +int ABI_ATTR i_i (int a) +{ + int r=a+1; + fprintf(out,"int f(int):(%d)",a); + fflush(out); + return r; +} +int ABI_ATTR i_i2 (int a, int b) +{ + int r=a+b; + fprintf(out,"int f(2*int):(%d,%d)",a,b); + fflush(out); + return r; +} +int ABI_ATTR i_i4 (int a, int b, int c, int d) +{ + int r=a+b+c+d; + fprintf(out,"int f(4*int):(%d,%d,%d,%d)",a,b,c,d); + fflush(out); + return r; +} +int ABI_ATTR i_i8 (int a, int b, int c, int d, int e, int f, int g, int h) +{ + int r=a+b+c+d+e+f+g+h; + fprintf(out,"int f(8*int):(%d,%d,%d,%d,%d,%d,%d,%d)",a,b,c,d,e,f,g,h); + fflush(out); + return r; +} +int ABI_ATTR i_i16 (int a, int b, int c, int d, int e, int f, int g, int h, + int i, int j, int k, int l, int m, int n, int o, int p) +{ + int r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p; + fprintf(out,"int f(16*int):(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)", + a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); + fflush(out); + return r; +} + +/* float tests */ +float ABI_ATTR f_f (float a) +{ + float r=a+1.0f; + fprintf(out,"float f(float):(%g)",a); + fflush(out); + return r; +} +float ABI_ATTR f_f2 (float a, float b) +{ + float r=a+b; + fprintf(out,"float f(2*float):(%g,%g)",a,b); + fflush(out); + return r; +} +float ABI_ATTR f_f4 (float a, float b, float c, float d) +{ + float r=a+b+c+d; + fprintf(out,"float f(4*float):(%g,%g,%g,%g)",a,b,c,d); + fflush(out); + return r; +} +float ABI_ATTR f_f8 (float a, float b, float c, float d, float e, float f, + float g, float h) +{ + float r=a+b+c+d+e+f+g+h; + fprintf(out,"float f(8*float):(%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h); + fflush(out); + return r; +} +float ABI_ATTR f_f16 (float a, float b, float c, float d, float e, float f, float g, float h, + float i, float j, float k, float l, float m, float n, float o, float p) +{ + float r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p; + fprintf(out,"float f(16*float):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); + fflush(out); + return r; +} +float ABI_ATTR f_f24 (float a, float b, float c, float d, float e, float f, float g, float h, + float i, float j, float k, float l, float m, float n, float o, float p, + float q, float s, float t, float u, float v, float w, float x, float y) +{ + float r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+s+t+u+v+w+x+y; + fprintf(out,"float f(24*float):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,v,w,x,y); + fflush(out); + return r; +} + +/* double tests */ +double ABI_ATTR d_d (double a) +{ + double r=a+1.0; + fprintf(out,"double f(double):(%g)",a); + fflush(out); + return r; +} +double ABI_ATTR d_d2 (double a, double b) +{ + double r=a+b; + fprintf(out,"double f(2*double):(%g,%g)",a,b); + fflush(out); + return r; +} +double ABI_ATTR d_d4 (double a, double b, double c, double d) +{ + double r=a+b+c+d; + fprintf(out,"double f(4*double):(%g,%g,%g,%g)",a,b,c,d); + fflush(out); + return r; +} +double ABI_ATTR d_d8 (double a, double b, double c, double d, double e, double f, + double g, double h) +{ + double r=a+b+c+d+e+f+g+h; + fprintf(out,"double f(8*double):(%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h); + fflush(out); + return r; +} +double ABI_ATTR d_d16 (double a, double b, double c, double d, double e, double f, + double g, double h, double i, double j, double k, double l, + double m, double n, double o, double p) +{ + double r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p; + fprintf(out,"double f(16*double):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); + fflush(out); + return r; +} + +/* pointer tests */ +void* ABI_ATTR vp_vpdpcpsp (void* a, double* b, char* c, Int* d) +{ + void* ret = (char*)b + 1; + fprintf(out,"void* f(void*,double*,char*,Int*):(0x%p,0x%p,0x%p,0x%p)",a,b,c,d); + fflush(out); + return ret; +} + +/* mixed number tests */ +uchar ABI_ATTR uc_ucsil (uchar a, ushort b, uint c, ulong d) +{ + uchar r = (uchar)-1; + fprintf(out,"uchar f(uchar,ushort,uint,ulong):(%u,%u,%u,%lu)",a,b,c,d); + fflush(out); + return r; +} +double ABI_ATTR d_iidd (int a, int b, double c, double d) +{ + double r = a+b+c+d; + fprintf(out,"double f(int,int,double,double):(%d,%d,%g,%g)",a,b,c,d); + fflush(out); + return r; +} +double ABI_ATTR d_iiidi (int a, int b, int c, double d, int e) +{ + double r = a+b+c+d+e; + fprintf(out,"double f(int,int,int,double,int):(%d,%d,%d,%g,%d)",a,b,c,d,e); + fflush(out); + return r; +} +double ABI_ATTR d_idid (int a, double b, int c, double d) +{ + double r = a+b+c+d; + fprintf(out,"double f(int,double,int,double):(%d,%g,%d,%g)",a,b,c,d); + fflush(out); + return r; +} +double ABI_ATTR d_fdi (float a, double b, int c) +{ + double r = a+b+c; + fprintf(out,"double f(float,double,int):(%g,%g,%d)",a,b,c); + fflush(out); + return r; +} +ushort ABI_ATTR us_cdcd (char a, double b, char c, double d) +{ + ushort r = (ushort)(a + b + c + d); + fprintf(out,"ushort f(char,double,char,double):('%c',%g,'%c',%g)",a,b,c,d); + fflush(out); + return r; +} + +long long ABI_ATTR ll_iiilli (int a, int b, int c, long long d, int e) +{ + long long r = (long long)(int)a+(long long)(int)b+(long long)(int)c+d+(long long)(int)e; + fprintf(out,"long long f(int,int,int,long long,int):(%d,%d,%d,0x%lx%08lx,%d)",a,b,c,(long)(d>>32),(long)(d&0xffffffff),e); + fflush(out); + return r; +} +long long ABI_ATTR ll_flli (float a, long long b, int c) +{ + long long r = (long long)(int)a + b + (long long)c; + fprintf(out,"long long f(float,long long,int):(%g,0x%lx%08lx,0x%lx)",a,(long)(b>>32),(long)(b&0xffffffff),(long)c); + fflush(out); + return r; +} + +float ABI_ATTR f_fi (float a, int z) +{ + float r = a+z; + fprintf(out,"float f(float,int):(%g,%d)",a,z); + fflush(out); + return r; +} +float ABI_ATTR f_f2i (float a, float b, int z) +{ + float r = a+b+z; + fprintf(out,"float f(2*float,int):(%g,%g,%d)",a,b,z); + fflush(out); + return r; +} +float ABI_ATTR f_f3i (float a, float b, float c, int z) +{ + float r = a+b+c+z; + fprintf(out,"float f(3*float,int):(%g,%g,%g,%d)",a,b,c,z); + fflush(out); + return r; +} +float ABI_ATTR f_f4i (float a, float b, float c, float d, int z) +{ + float r = a+b+c+d+z; + fprintf(out,"float f(4*float,int):(%g,%g,%g,%g,%d)",a,b,c,d,z); + fflush(out); + return r; +} +float ABI_ATTR f_f7i (float a, float b, float c, float d, float e, float f, float g, + int z) +{ + float r = a+b+c+d+e+f+g+z; + fprintf(out,"float f(7*float,int):(%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,z); + fflush(out); + return r; +} +float ABI_ATTR f_f8i (float a, float b, float c, float d, float e, float f, float g, + float h, int z) +{ + float r = a+b+c+d+e+f+g+h+z; + fprintf(out,"float f(8*float,int):(%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,z); + fflush(out); + return r; +} +float ABI_ATTR f_f12i (float a, float b, float c, float d, float e, float f, float g, + float h, float i, float j, float k, float l, int z) +{ + float r = a+b+c+d+e+f+g+h+i+j+k+l+z; + fprintf(out,"float f(12*float,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,z); + fflush(out); + return r; +} +float ABI_ATTR f_f13i (float a, float b, float c, float d, float e, float f, float g, + float h, float i, float j, float k, float l, float m, int z) +{ + float r = a+b+c+d+e+f+g+h+i+j+k+l+m+z; + fprintf(out,"float f(13*float,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,m,z); + fflush(out); + return r; +} + +double ABI_ATTR d_di (double a, int z) +{ + double r = a+z; + fprintf(out,"double f(double,int):(%g,%d)",a,z); + fflush(out); + return r; +} +double ABI_ATTR d_d2i (double a, double b, int z) +{ + double r = a+b+z; + fprintf(out,"double f(2*double,int):(%g,%g,%d)",a,b,z); + fflush(out); + return r; +} +double ABI_ATTR d_d3i (double a, double b, double c, int z) +{ + double r = a+b+c+z; + fprintf(out,"double f(3*double,int):(%g,%g,%g,%d)",a,b,c,z); + fflush(out); + return r; +} +double ABI_ATTR d_d4i (double a, double b, double c, double d, int z) +{ + double r = a+b+c+d+z; + fprintf(out,"double f(4*double,int):(%g,%g,%g,%g,%d)",a,b,c,d,z); + fflush(out); + return r; +} +double ABI_ATTR d_d7i (double a, double b, double c, double d, double e, double f, + double g, int z) +{ + double r = a+b+c+d+e+f+g+z; + fprintf(out,"double f(7*double,int):(%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,z); + fflush(out); + return r; +} +double ABI_ATTR d_d8i (double a, double b, double c, double d, double e, double f, + double g, double h, int z) +{ + double r = a+b+c+d+e+f+g+h+z; + fprintf(out,"double f(8*double,int):(%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,z); + fflush(out); + return r; +} +double ABI_ATTR d_d12i (double a, double b, double c, double d, double e, double f, + double g, double h, double i, double j, double k, double l, + int z) +{ + double r = a+b+c+d+e+f+g+h+i+j+k+l+z; + fprintf(out,"double f(12*double,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,z); + fflush(out); + return r; +} +double ABI_ATTR d_d13i (double a, double b, double c, double d, double e, double f, + double g, double h, double i, double j, double k, double l, + double m, int z) +{ + double r = a+b+c+d+e+f+g+h+i+j+k+l+m+z; + fprintf(out,"double f(13*double,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,m,z); + fflush(out); + return r; +} + +/* small structure return tests */ +Size1 ABI_ATTR S1_v (void) +{ + fprintf(out,"Size1 f(void):"); + fflush(out); + return Size1_1; +} +Size2 ABI_ATTR S2_v (void) +{ + fprintf(out,"Size2 f(void):"); + fflush(out); + return Size2_1; +} +Size3 ABI_ATTR S3_v (void) +{ + fprintf(out,"Size3 f(void):"); + fflush(out); + return Size3_1; +} +Size4 ABI_ATTR S4_v (void) +{ + fprintf(out,"Size4 f(void):"); + fflush(out); + return Size4_1; +} +Size7 ABI_ATTR S7_v (void) +{ + fprintf(out,"Size7 f(void):"); + fflush(out); + return Size7_1; +} +Size8 ABI_ATTR S8_v (void) +{ + fprintf(out,"Size8 f(void):"); + fflush(out); + return Size8_1; +} +Size12 ABI_ATTR S12_v (void) +{ + fprintf(out,"Size12 f(void):"); + fflush(out); + return Size12_1; +} +Size15 ABI_ATTR S15_v (void) +{ + fprintf(out,"Size15 f(void):"); + fflush(out); + return Size15_1; +} +Size16 ABI_ATTR S16_v (void) +{ + fprintf(out,"Size16 f(void):"); + fflush(out); + return Size16_1; +} + +/* structure tests */ +Int ABI_ATTR I_III (Int a, Int b, Int c) +{ + Int r; + r.x = a.x + b.x + c.x; + fprintf(out,"Int f(Int,Int,Int):({%d},{%d},{%d})",a.x,b.x,c.x); + fflush(out); + return r; +} +Char ABI_ATTR C_CdC (Char a, double b, Char c) +{ + Char r; + r.x = (a.x + c.x)/2; + fprintf(out,"Char f(Char,double,Char):({'%c'},%g,{'%c'})",a.x,b,c.x); + fflush(out); + return r; +} +Float ABI_ATTR F_Ffd (Float a, float b, double c) +{ + Float r; + r.x = (float) (a.x + b + c); + fprintf(out,"Float f(Float,float,double):({%g},%g,%g)",a.x,b,c); + fflush(out); + return r; +} +Double ABI_ATTR D_fDd (float a, Double b, double c) +{ + Double r; + r.x = a + b.x + c; + fprintf(out,"Double f(float,Double,double):(%g,{%g},%g)",a,b.x,c); + fflush(out); + return r; +} +Double ABI_ATTR D_Dfd (Double a, float b, double c) +{ + Double r; + r.x = a.x + b + c; + fprintf(out,"Double f(Double,float,double):({%g},%g,%g)",a.x,b,c); + fflush(out); + return r; +} +J ABI_ATTR J_JiJ (J a, int b, J c) +{ + J r; + r.l1 = a.l1+c.l1; r.l2 = a.l2+b+c.l2; + fprintf(out,"J f(J,int,J):({%ld,%ld},%d,{%ld,%ld})",a.l1,a.l2,b,c.l1,c.l2); + fflush(out); + return r; +} +T ABI_ATTR T_TcT (T a, char b, T c) +{ + T r; + r.c[0]='b'; r.c[1]=c.c[1]; r.c[2]=c.c[2]; + fprintf(out,"T f(T,char,T):({\"%c%c%c\"},'%c',{\"%c%c%c\"})",a.c[0],a.c[1],a.c[2],b,c.c[0],c.c[1],c.c[2]); + fflush(out); + return r; +} +X ABI_ATTR X_BcdB (B a, char b, double c, B d) +{ + static X xr={"return val",'R'}; + X r; + r = xr; + r.c1 = b; + fprintf(out,"X f(B,char,double,B):({%g,{%d,%d,%d}},'%c',%g,{%g,{%d,%d,%d}})", + a.d,a.i[0],a.i[1],a.i[2],b,c,d.d,d.i[0],d.i[1],d.i[2]); + fflush(out); + return r; +} + +/* Test for cases where some argument (especially structure, 'long long', or + 'double') may be passed partially in general-purpose argument registers + and partially on the stack. Different ABIs pass between 4 and 8 arguments + (or none) in general-purpose argument registers. */ + +long ABI_ATTR l_l0K (K b, long c) +{ + long r = b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(K,long):(%ld,%ld,%ld,%ld,%ld)",b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +long ABI_ATTR l_l1K (long a1, K b, long c) +{ + long r = a1 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld)",a1,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +long ABI_ATTR l_l2K (long a1, long a2, K b, long c) +{ + long r = a1 + a2 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(2*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +long ABI_ATTR l_l3K (long a1, long a2, long a3, K b, long c) +{ + long r = a1 + a2 + a3 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(3*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +long ABI_ATTR l_l4K (long a1, long a2, long a3, long a4, K b, long c) +{ + long r = a1 + a2 + a3 + a4 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(4*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,a4,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +long ABI_ATTR l_l5K (long a1, long a2, long a3, long a4, long a5, K b, long c) +{ + long r = a1 + a2 + a3 + a4 + a5 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(5*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,a4,a5,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +long ABI_ATTR l_l6K (long a1, long a2, long a3, long a4, long a5, long a6, K b, long c) +{ + long r = a1 + a2 + a3 + a4 + a5 + a6 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(6*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,a4,a5,a6,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +/* These tests is crafted on the knowledge that for all known ABIs: + * 17 > number of floating-point argument registers, + * 3 < number of general-purpose argument registers < 3 + 6. */ +float ABI_ATTR f_f17l3L (float a, float b, float c, float d, float e, float f, float g, + float h, float i, float j, float k, float l, float m, float n, + float o, float p, float q, + long s, long t, long u, L z) +{ + float r = a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+s+t+u+z.l1+z.l2+z.l3+z.l4+z.l5+z.l6; + fprintf(out,"float f(17*float,3*int,L):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,z.l1,z.l2,z.l3,z.l4,z.l5,z.l6); + fflush(out); + return r; +} +double ABI_ATTR d_d17l3L (double a, double b, double c, double d, double e, double f, + double g, double h, double i, double j, double k, double l, + double m, double n, double o, double p, double q, + long s, long t, long u, L z) +{ + double r = a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+s+t+u+z.l1+z.l2+z.l3+z.l4+z.l5+z.l6; + fprintf(out,"double f(17*double,3*int,L):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,z.l1,z.l2,z.l3,z.l4,z.l5,z.l6); + fflush(out); + return r; +} + +long long ABI_ATTR ll_l2ll (long a1, long a2, long long b, long c) +{ + long long r = (long long) (a1 + a2) + b + c; + fprintf(out,"long long f(2*long,long long,long):(%ld,%ld,0x%lx%08lx,%ld)",a1,a2,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + return r; +} +long long ABI_ATTR ll_l3ll (long a1, long a2, long a3, long long b, long c) +{ + long long r = (long long) (a1 + a2 + a3) + b + c; + fprintf(out,"long long f(3*long,long long,long):(%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + return r; +} +long long ABI_ATTR ll_l4ll (long a1, long a2, long a3, long a4, long long b, long c) +{ + long long r = (long long) (a1 + a2 + a3 + a4) + b + c; + fprintf(out,"long long f(4*long,long long,long):(%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + return r; +} +long long ABI_ATTR ll_l5ll (long a1, long a2, long a3, long a4, long a5, long long b, long c) +{ + long long r = (long long) (a1 + a2 + a3 + a4 + a5) + b + c; + fprintf(out,"long long f(5*long,long long,long):(%ld,%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,a5,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + return r; +} +long long ABI_ATTR ll_l6ll (long a1, long a2, long a3, long a4, long a5, long a6, long long b, long c) +{ + long long r = (long long) (a1 + a2 + a3 + a4 + a5 + a6) + b + c; + fprintf(out,"long long f(6*long,long long,long):(%ld,%ld,%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,a5,a6,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + return r; +} +long long ABI_ATTR ll_l7ll (long a1, long a2, long a3, long a4, long a5, long a6, long a7, long long b, long c) +{ + long long r = (long long) (a1 + a2 + a3 + a4 + a5 + a6 + a7) + b + c; + fprintf(out,"long long f(7*long,long long,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,a5,a6,a7,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + return r; +} + +double ABI_ATTR d_l2d (long a1, long a2, double b, long c) +{ + double r = (double) (a1 + a2) + b + c; + fprintf(out,"double f(2*long,double,long):(%ld,%ld,%g,%ld)",a1,a2,b,c); + fflush(out); + return r; +} +double ABI_ATTR d_l3d (long a1, long a2, long a3, double b, long c) +{ + double r = (double) (a1 + a2 + a3) + b + c; + fprintf(out,"double f(3*long,double,long):(%ld,%ld,%ld,%g,%ld)",a1,a2,a3,b,c); + fflush(out); + return r; +} +double ABI_ATTR d_l4d (long a1, long a2, long a3, long a4, double b, long c) +{ + double r = (double) (a1 + a2 + a3 + a4) + b + c; + fprintf(out,"double f(4*long,double,long):(%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,b,c); + fflush(out); + return r; +} +double ABI_ATTR d_l5d (long a1, long a2, long a3, long a4, long a5, double b, long c) +{ + double r = (double) (a1 + a2 + a3 + a4 + a5) + b + c; + fprintf(out,"double f(5*long,double,long):(%ld,%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,a5,b,c); + fflush(out); + return r; +} +double ABI_ATTR d_l6d (long a1, long a2, long a3, long a4, long a5, long a6, double b, long c) +{ + double r = (double) (a1 + a2 + a3 + a4 + a5 + a6) + b + c; + fprintf(out,"double f(6*long,double,long):(%ld,%ld,%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,a5,a6,b,c); + fflush(out); + return r; +} +double ABI_ATTR d_l7d (long a1, long a2, long a3, long a4, long a5, long a6, long a7, double b, long c) +{ + double r = (double) (a1 + a2 + a3 + a4 + a5 + a6 + a7) + b + c; + fprintf(out,"double f(7*long,double,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,a5,a6,a7,b,c); + fflush(out); + return r; +} diff --git a/libffi/testsuite/libffi.call/align_mixed.c b/libffi/testsuite/libffi.call/align_mixed.c new file mode 100644 index 0000000..5d4959c --- /dev/null +++ b/libffi/testsuite/libffi.call/align_mixed.c @@ -0,0 +1,46 @@ +/* Area: ffi_call + Purpose: Check for proper argument alignment. + Limitations: none. + PR: none. + Originator: <twalljava@java.net> (from many_win32.c) */ + +/* { dg-do run } */ + +#include "ffitest.h" + +static float ABI_ATTR align_arguments(int i1, + double f2, + int i3, + double f4) +{ + return i1+f2+i3+f4; +} + +int main(void) +{ + ffi_cif cif; + ffi_type *args[4] = { + &ffi_type_sint, + &ffi_type_double, + &ffi_type_sint, + &ffi_type_double + }; + double fa[2] = {1,2}; + int ia[2] = {1,2}; + void *values[4] = {&ia[0], &fa[0], &ia[1], &fa[1]}; + float f, ff; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, ABI_NUM, 4, + &ffi_type_float, args) == FFI_OK); + + ff = align_arguments(ia[0], fa[0], ia[1], fa[1]); + + ffi_call(&cif, FFI_FN(align_arguments), &f, values); + + if (f == ff) + printf("align arguments tests ok!\n"); + else + CHECK(0); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/align_stdcall.c b/libffi/testsuite/libffi.call/align_stdcall.c new file mode 100644 index 0000000..5e5cb86 --- /dev/null +++ b/libffi/testsuite/libffi.call/align_stdcall.c @@ -0,0 +1,46 @@ +/* Area: ffi_call + Purpose: Check for proper argument alignment. + Limitations: none. + PR: none. + Originator: <twalljava@java.net> (from many_win32.c) */ + +/* { dg-do run } */ + +#include "ffitest.h" + +static float ABI_ATTR align_arguments(int i1, + double f2, + int i3, + double f4) +{ + return i1+f2+i3+f4; +} + +int main(void) +{ + ffi_cif cif; + ffi_type *args[4] = { + &ffi_type_sint, + &ffi_type_double, + &ffi_type_sint, + &ffi_type_double + }; + double fa[2] = {1,2}; + int ia[2] = {1,2}; + void *values[4] = {&ia[0], &fa[0], &ia[1], &fa[1]}; + float f, ff; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, ABI_NUM, 4, + &ffi_type_float, args) == FFI_OK); + + ff = align_arguments(ia[0], fa[0], ia[1], fa[1]);; + + ffi_call(&cif, FFI_FN(align_arguments), &f, values); + + if (f == ff) + printf("align arguments tests ok!\n"); + else + CHECK(0); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/call.exp b/libffi/testsuite/libffi.call/call.exp index 46fb1eb..13ba2bd 100644 --- a/libffi/testsuite/libffi.call/call.exp +++ b/libffi/testsuite/libffi.call/call.exp @@ -19,9 +19,33 @@ libffi-init global srcdir subdir -set tlist [lsearch -inline -all -not -glob [lsort [glob -nocomplain -- $srcdir/$subdir/*.{c,cc}]] *complex*] +if { [string match $compiler_vendor "microsoft"] } { + # -wd4005 macro redefinition + # -wd4244 implicit conversion to type of smaller size + # -wd4305 truncation to smaller type + # -wd4477 printf %lu of uintptr_t + # -wd4312 implicit conversion to type of greater size + # -wd4311 pointer truncation to unsigned long + # -EHsc C++ Exception Handling (no SEH exceptions) + set additional_options "-wd4005 -wd4244 -wd4305 -wd4477 -wd4312 -wd4311 -EHsc"; +} else { + set additional_options ""; +} -run-many-tests $tlist "" +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.c]] + +run-many-tests $tlist $additional_options + +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.cc]] + +# No C++ for or1k +if { [istarget "or1k-*-*"] } { + foreach test $tlist { + unsupported "$test" + } +} else { + run-many-tests $tlist $additional_options +} dg-finish diff --git a/libffi/testsuite/libffi.call/cls_uchar_va.c b/libffi/testsuite/libffi.call/cls_uchar_va.c deleted file mode 100644 index 6491c5b..0000000 --- a/libffi/testsuite/libffi.call/cls_uchar_va.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Area: closure_call - Purpose: Test anonymous unsigned char argument. - Limitations: none. - PR: none. - Originator: ARM Ltd. */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef unsigned char T; - -static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) - { - *(ffi_arg *)resp = *(T *)args[0]; - - printf("%d: %d %d\n", (int)(*(ffi_arg *)resp), *(T *)args[0], *(T *)args[1]); - } - -typedef T (*cls_ret_T)(T, ...); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[3]; - T res; - - cl_arg_types[0] = &ffi_type_uchar; - cl_arg_types[1] = &ffi_type_uchar; - cl_arg_types[2] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, - &ffi_type_uchar, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code) == FFI_OK); - res = ((((cls_ret_T)code)(67, 4))); - /* { dg-output "67: 67 4" } */ - printf("res: %d\n", res); - /* { dg-output "\nres: 67" } */ - exit(0); -} diff --git a/libffi/testsuite/libffi.call/cls_ushort_va.c b/libffi/testsuite/libffi.call/cls_ushort_va.c deleted file mode 100644 index 37aa106..0000000 --- a/libffi/testsuite/libffi.call/cls_ushort_va.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Area: closure_call - Purpose: Test anonymous unsigned short argument. - Limitations: none. - PR: none. - Originator: ARM Ltd. */ - -/* { dg-do run } */ -#include "ffitest.h" - -typedef unsigned short T; - -static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, - void* userdata __UNUSED__) - { - *(ffi_arg *)resp = *(T *)args[0]; - - printf("%d: %d %d\n", (int)(*(ffi_arg *)resp), *(T *)args[0], *(T *)args[1]); - } - -typedef T (*cls_ret_T)(T, ...); - -int main (void) -{ - ffi_cif cif; - void *code; - ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); - ffi_type * cl_arg_types[3]; - T res; - - cl_arg_types[0] = &ffi_type_ushort; - cl_arg_types[1] = &ffi_type_ushort; - cl_arg_types[2] = NULL; - - /* Initialize the cif */ - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, - &ffi_type_ushort, cl_arg_types) == FFI_OK); - - CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code) == FFI_OK); - res = ((((cls_ret_T)code)(67, 4))); - /* { dg-output "67: 67 4" } */ - printf("res: %d\n", res); - /* { dg-output "\nres: 67" } */ - exit(0); -} diff --git a/libffi/testsuite/libffi.call/ffitest.h b/libffi/testsuite/libffi.call/ffitest.h index 15d5e44..95d96a8 100644 --- a/libffi/testsuite/libffi.call/ffitest.h +++ b/libffi/testsuite/libffi.call/ffitest.h @@ -15,7 +15,13 @@ #define MAX_ARGS 256 -#define CHECK(x) (void)(!(x) ? (abort(), 1) : 0) +#define CHECK(x) \ + do { \ + if(!(x)){ \ + printf("Check failed:\n%s\n", #x); \ + abort(); \ + } \ + } while(0) /* Define macros so that compilers other than gcc can run the tests. */ #undef __UNUSED__ @@ -24,6 +30,7 @@ #define __STDCALL__ __attribute__((stdcall)) #define __THISCALL__ __attribute__((thiscall)) #define __FASTCALL__ __attribute__((fastcall)) +#define __MSABI__ __attribute__((ms_abi)) #else #define __UNUSED__ #define __STDCALL__ __stdcall @@ -63,7 +70,7 @@ #endif /* MinGW kludge. */ -#ifdef _WIN64 +#if defined(_WIN64) | defined(_WIN32) #define PRIdLL "I64d" #define PRIuLL "I64u" #else @@ -123,12 +130,14 @@ /* MSVC kludge. */ #if defined _MSC_VER +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) #define PRIuPTR "lu" #define PRIu8 "u" #define PRId8 "d" #define PRIu64 "I64u" #define PRId64 "I64d" #endif +#endif #ifndef PRIuPTR #define PRIuPTR "u" diff --git a/libffi/testsuite/libffi.call/float2.c b/libffi/testsuite/libffi.call/float2.c index 55b9fba..57cd9e3 100644 --- a/libffi/testsuite/libffi.call/float2.c +++ b/libffi/testsuite/libffi.call/float2.c @@ -3,7 +3,7 @@ Limitations: none. PR: none. Originator: From the original ffitest.c */ -/* { dg-do run { target { ! hppa*-*-hpux* } } } */ +/* { dg-do run } */ #include "ffitest.h" #include "float.h" @@ -22,6 +22,7 @@ int main (void) void *values[MAX_ARGS]; float f; long double ld; + long double original; args[0] = &ffi_type_float; values[0] = &f; @@ -32,24 +33,26 @@ int main (void) f = 3.14159; -#if 1 - /* This is ifdef'd out for now. long double support under SunOS/gcc - is pretty much non-existent. You'll get the odd bus error in library - routines like printf(). */ +#if defined(__sun) && defined(__GNUC__) + /* long double support under SunOS/gcc is pretty much non-existent. + You'll get the odd bus error in library routines like printf() */ +#else printf ("%Lf\n", ldblit(f)); #endif + ld = 666; ffi_call(&cif, FFI_FN(ldblit), &ld, values); -#if 1 - /* This is ifdef'd out for now. long double support under SunOS/gcc - is pretty much non-existent. You'll get the odd bus error in library - routines like printf(). */ +#if defined(__sun) && defined(__GNUC__) + /* long double support under SunOS/gcc is pretty much non-existent. + You'll get the odd bus error in library routines like printf() */ +#else printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON); #endif /* These are not always the same!! Check for a reasonable delta */ - if (fabsl(ld - ldblit(f)) < LDBL_EPSILON) + original = ldblit(f); + if (((ld > original) ? (ld - original) : (original - ld)) < LDBL_EPSILON) puts("long double return value tests ok!"); else CHECK(0); diff --git a/libffi/testsuite/libffi.call/offsets.c b/libffi/testsuite/libffi.call/offsets.c new file mode 100644 index 0000000..23d88b3 --- /dev/null +++ b/libffi/testsuite/libffi.call/offsets.c @@ -0,0 +1,46 @@ +/* Area: Struct layout + Purpose: Test ffi_get_struct_offsets + Limitations: none. + PR: none. + Originator: Tom Tromey. */ + +/* { dg-do run } */ +#include "ffitest.h" +#include <stddef.h> + +struct test_1 +{ + char c; + float f; + char c2; + int i; +}; + +int +main (void) +{ + ffi_type test_1_type; + ffi_type *test_1_elements[5]; + size_t test_1_offsets[4]; + + test_1_elements[0] = &ffi_type_schar; + test_1_elements[1] = &ffi_type_float; + test_1_elements[2] = &ffi_type_schar; + test_1_elements[3] = &ffi_type_sint; + test_1_elements[4] = NULL; + + test_1_type.size = 0; + test_1_type.alignment = 0; + test_1_type.type = FFI_TYPE_STRUCT; + test_1_type.elements = test_1_elements; + + CHECK (ffi_get_struct_offsets (FFI_DEFAULT_ABI, &test_1_type, test_1_offsets) + == FFI_OK); + CHECK (test_1_type.size == sizeof (struct test_1)); + CHECK (offsetof (struct test_1, c) == test_1_offsets[0]); + CHECK (offsetof (struct test_1, f) == test_1_offsets[1]); + CHECK (offsetof (struct test_1, c2) == test_1_offsets[2]); + CHECK (offsetof (struct test_1, i) == test_1_offsets[3]); + + return 0; +} diff --git a/libffi/testsuite/libffi.call/struct10.c b/libffi/testsuite/libffi.call/struct10.c new file mode 100644 index 0000000..17b1377 --- /dev/null +++ b/libffi/testsuite/libffi.call/struct10.c @@ -0,0 +1,57 @@ +/* Area: ffi_call + Purpose: Check structures. + Limitations: none. + PR: none. + Originator: Sergei Trofimovich <slyfox@gentoo.org> + + The test originally discovered in ruby's bindings + for ffi in https://bugs.gentoo.org/634190 */ + +/* { dg-do run } */ +#include "ffitest.h" + +struct s { + int s32; + float f32; + signed char s8; +}; + +struct s make_s(void) { + struct s r; + r.s32 = 0x1234; + r.f32 = 7.0; + r.s8 = 0x78; + return r; +} + +int main() { + ffi_cif cif; + struct s r; + ffi_type rtype; + ffi_type* s_fields[] = { + &ffi_type_sint, + &ffi_type_float, + &ffi_type_schar, + NULL, + }; + + rtype.size = 0; + rtype.alignment = 0, + rtype.type = FFI_TYPE_STRUCT, + rtype.elements = s_fields, + + r.s32 = 0xbad; + r.f32 = 999.999; + r.s8 = 0x51; + + // Here we emulate the following call: + //r = make_s(); + + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &rtype, NULL) == FFI_OK); + ffi_call(&cif, FFI_FN(make_s), &r, NULL); + + CHECK(r.s32 == 0x1234); + CHECK(r.f32 == 7.0); + CHECK(r.s8 == 0x78); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/va_1.c b/libffi/testsuite/libffi.call/va_1.c index 7f96809..ccc6faf 100644 --- a/libffi/testsuite/libffi.call/va_1.c +++ b/libffi/testsuite/libffi.call/va_1.c @@ -5,7 +5,6 @@ Originator: ARM Ltd. */ /* { dg-do run } */ -/* { dg-output "" { xfail avr32*-*-* } } */ #include "ffitest.h" #include <stdarg.h> @@ -25,62 +24,10 @@ struct large_tag unsigned e; }; -static int -test_fn (int n, ...) -{ - va_list ap; - struct small_tag s1; - struct small_tag s2; - struct large_tag l; - unsigned char uc; - signed char sc; - unsigned short us; - signed short ss; - unsigned int ui; - signed int si; - unsigned long ul; - signed long sl; - float f; - double d; - - va_start (ap, n); - s1 = va_arg (ap, struct small_tag); - l = va_arg (ap, struct large_tag); - s2 = va_arg (ap, struct small_tag); - - uc = va_arg (ap, unsigned); - sc = va_arg (ap, signed); - - us = va_arg (ap, unsigned); - ss = va_arg (ap, signed); - - ui = va_arg (ap, unsigned int); - si = va_arg (ap, signed int); - - ul = va_arg (ap, unsigned long); - sl = va_arg (ap, signed long); - - f = va_arg (ap, double); /* C standard promotes float->double - when anonymous */ - d = va_arg (ap, double); - - printf ("%u %u %u %u %u %u %u %u %u uc=%u sc=%d %u %d %u %d %lu %ld %f %f\n", - s1.a, s1.b, l.a, l.b, l.c, l.d, l.e, - s2.a, s2.b, - uc, sc, - us, ss, - ui, si, - ul, sl, - f, d); - va_end (ap); - return n + 1; -} - int main (void) { ffi_cif cif; - void* args[15]; ffi_type* arg_types[15]; ffi_type s_type; @@ -89,24 +36,6 @@ main (void) ffi_type l_type; ffi_type *l_type_elements[6]; - struct small_tag s1; - struct small_tag s2; - struct large_tag l1; - - int n; - ffi_arg res; - - unsigned char uc; - signed char sc; - unsigned short us; - signed short ss; - unsigned int ui; - signed int si; - unsigned long ul; - signed long sl; - double d1; - double f1; - s_type.size = 0; s_type.alignment = 0; s_type.type = FFI_TYPE_STRUCT; @@ -144,53 +73,6 @@ main (void) arg_types[13] = &ffi_type_double; arg_types[14] = NULL; - CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_OK); - - s1.a = 5; - s1.b = 6; - - l1.a = 10; - l1.b = 11; - l1.c = 12; - l1.d = 13; - l1.e = 14; - - s2.a = 7; - s2.b = 8; - - n = 41; - - uc = 9; - sc = 10; - us = 11; - ss = 12; - ui = 13; - si = 14; - ul = 15; - sl = 16; - f1 = 2.12; - d1 = 3.13; - - args[0] = &n; - args[1] = &s1; - args[2] = &l1; - args[3] = &s2; - args[4] = &uc; - args[5] = ≻ - args[6] = &us; - args[7] = &ss; - args[8] = &ui; - args[9] = &si; - args[10] = &ul; - args[11] = &sl; - args[12] = &f1; - args[13] = &d1; - args[14] = NULL; - - ffi_call(&cif, FFI_FN(test_fn), &res, args); - /* { dg-output "5 6 10 11 12 13 14 7 8 uc=9 sc=10 11 12 13 14 15 16 2.120000 3.130000" } */ - printf("res: %d\n", (int) res); - /* { dg-output "\nres: 42" } */ - + CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_BAD_ARGTYPE); return 0; } diff --git a/libffi/testsuite/libffi.call/va_2.c b/libffi/testsuite/libffi.call/va_2.c new file mode 100644 index 0000000..0589d08 --- /dev/null +++ b/libffi/testsuite/libffi.call/va_2.c @@ -0,0 +1,196 @@ +/* Area: ffi_call + Purpose: Test passing struct in variable argument lists. + Limitations: none. + PR: none. + Originator: ARM Ltd. */ + +/* { dg-do run } */ +/* { dg-output "" { xfail avr32*-*-* m68k-*-* alpha-*-* } } */ + +#include "ffitest.h" +#include <stdarg.h> + +struct small_tag +{ + unsigned char a; + unsigned char b; +}; + +struct large_tag +{ + unsigned a; + unsigned b; + unsigned c; + unsigned d; + unsigned e; +}; + +static int +test_fn (int n, ...) +{ + va_list ap; + struct small_tag s1; + struct small_tag s2; + struct large_tag l; + unsigned char uc; + signed char sc; + unsigned short us; + signed short ss; + unsigned int ui; + signed int si; + unsigned long ul; + signed long sl; + float f; + double d; + + va_start (ap, n); + s1 = va_arg (ap, struct small_tag); + l = va_arg (ap, struct large_tag); + s2 = va_arg (ap, struct small_tag); + + uc = va_arg (ap, unsigned); + sc = va_arg (ap, signed); + + us = va_arg (ap, unsigned); + ss = va_arg (ap, signed); + + ui = va_arg (ap, unsigned int); + si = va_arg (ap, signed int); + + ul = va_arg (ap, unsigned long); + sl = va_arg (ap, signed long); + + f = va_arg (ap, double); /* C standard promotes float->double + when anonymous */ + d = va_arg (ap, double); + + printf ("%u %u %u %u %u %u %u %u %u uc=%u sc=%d %u %d %u %d %lu %ld %f %f\n", + s1.a, s1.b, l.a, l.b, l.c, l.d, l.e, + s2.a, s2.b, + uc, sc, + us, ss, + ui, si, + ul, sl, + f, d); + va_end (ap); + return n + 1; +} + +int +main (void) +{ + ffi_cif cif; + void* args[15]; + ffi_type* arg_types[15]; + + ffi_type s_type; + ffi_type *s_type_elements[3]; + + ffi_type l_type; + ffi_type *l_type_elements[6]; + + struct small_tag s1; + struct small_tag s2; + struct large_tag l1; + + int n; + ffi_arg res; + + unsigned int uc; + signed int sc; + unsigned int us; + signed int ss; + unsigned int ui; + signed int si; + unsigned long ul; + signed long sl; + double d1; + double f1; + + s_type.size = 0; + s_type.alignment = 0; + s_type.type = FFI_TYPE_STRUCT; + s_type.elements = s_type_elements; + + s_type_elements[0] = &ffi_type_uchar; + s_type_elements[1] = &ffi_type_uchar; + s_type_elements[2] = NULL; + + l_type.size = 0; + l_type.alignment = 0; + l_type.type = FFI_TYPE_STRUCT; + l_type.elements = l_type_elements; + + l_type_elements[0] = &ffi_type_uint; + l_type_elements[1] = &ffi_type_uint; + l_type_elements[2] = &ffi_type_uint; + l_type_elements[3] = &ffi_type_uint; + l_type_elements[4] = &ffi_type_uint; + l_type_elements[5] = NULL; + + arg_types[0] = &ffi_type_sint; + arg_types[1] = &s_type; + arg_types[2] = &l_type; + arg_types[3] = &s_type; + arg_types[4] = &ffi_type_uint; + arg_types[5] = &ffi_type_sint; + arg_types[6] = &ffi_type_uint; + arg_types[7] = &ffi_type_sint; + arg_types[8] = &ffi_type_uint; + arg_types[9] = &ffi_type_sint; + arg_types[10] = &ffi_type_ulong; + arg_types[11] = &ffi_type_slong; + arg_types[12] = &ffi_type_double; + arg_types[13] = &ffi_type_double; + arg_types[14] = NULL; + + CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_OK); + + s1.a = 5; + s1.b = 6; + + l1.a = 10; + l1.b = 11; + l1.c = 12; + l1.d = 13; + l1.e = 14; + + s2.a = 7; + s2.b = 8; + + n = 41; + + uc = 9; + sc = 10; + us = 11; + ss = 12; + ui = 13; + si = 14; + ul = 15; + sl = 16; + f1 = 2.12; + d1 = 3.13; + + args[0] = &n; + args[1] = &s1; + args[2] = &l1; + args[3] = &s2; + args[4] = &uc; + args[5] = ≻ + args[6] = &us; + args[7] = &ss; + args[8] = &ui; + args[9] = &si; + args[10] = &ul; + args[11] = &sl; + args[12] = &f1; + args[13] = &d1; + args[14] = NULL; + + ffi_call(&cif, FFI_FN(test_fn), &res, args); + /* { dg-output "5 6 10 11 12 13 14 7 8 uc=9 sc=10 11 12 13 14 15 16 2.120000 3.130000" } */ + printf("res: %d\n", (int) res); + /* { dg-output "\nres: 42" } */ + + return 0; +} diff --git a/libffi/testsuite/libffi.closures/closure.exp b/libffi/testsuite/libffi.closures/closure.exp new file mode 100644 index 0000000..ed4145c --- /dev/null +++ b/libffi/testsuite/libffi.closures/closure.exp @@ -0,0 +1,67 @@ +# Copyright (C) 2003, 2006, 2009, 2010, 2014, 2019 Free Software Foundation, Inc. +# Copyright (C) 2019 Anthony Green + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +dg-init +libffi-init + +global srcdir subdir + +if { [string match $compiler_vendor "microsoft"] } { + # -wd4005 macro redefinition + # -wd4244 implicit conversion to type of smaller size + # -wd4305 truncation to smaller type + # -wd4477 printf %lu of uintptr_t + # -wd4312 implicit conversion to type of greater size + # -wd4311 pointer truncation to unsigned long + # -EHsc C++ Exception Handling (no SEH exceptions) + set additional_options "-wd4005 -wd4244 -wd4305 -wd4477 -wd4312 -wd4311 -EHsc"; +} else { + set additional_options ""; +} + +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.c]] + +if { [libffi_feature_test "#if FFI_CLOSURES"] } { + run-many-tests $tlist "" +} else { + foreach test $tlist { + unsupported "$test" + } +} + +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.cc]] + +# No C++ for or1k +if { [istarget "or1k-*-*"] } { + foreach test $tlist { + unsupported "$test" + } +} else { + if { [libffi_feature_test "#if FFI_CLOSURES"] } { + run-many-tests $tlist $additional_options + } else { + foreach test $tlist { + unsupported "$test" + } + } +} + +dg-finish + +# Local Variables: +# tcl-indent-level:4 +# End: diff --git a/libffi/testsuite/libffi.call/closure_fn0.c b/libffi/testsuite/libffi.closures/closure_fn0.c index a579ff6..a579ff6 100644 --- a/libffi/testsuite/libffi.call/closure_fn0.c +++ b/libffi/testsuite/libffi.closures/closure_fn0.c diff --git a/libffi/testsuite/libffi.call/closure_fn1.c b/libffi/testsuite/libffi.closures/closure_fn1.c index 9123173..9123173 100644 --- a/libffi/testsuite/libffi.call/closure_fn1.c +++ b/libffi/testsuite/libffi.closures/closure_fn1.c diff --git a/libffi/testsuite/libffi.call/closure_fn2.c b/libffi/testsuite/libffi.closures/closure_fn2.c index 08ff9d9..08ff9d9 100644 --- a/libffi/testsuite/libffi.call/closure_fn2.c +++ b/libffi/testsuite/libffi.closures/closure_fn2.c diff --git a/libffi/testsuite/libffi.call/closure_fn3.c b/libffi/testsuite/libffi.closures/closure_fn3.c index 9b54d80..9b54d80 100644 --- a/libffi/testsuite/libffi.call/closure_fn3.c +++ b/libffi/testsuite/libffi.closures/closure_fn3.c diff --git a/libffi/testsuite/libffi.call/closure_fn4.c b/libffi/testsuite/libffi.closures/closure_fn4.c index d4a1530..d4a1530 100644 --- a/libffi/testsuite/libffi.call/closure_fn4.c +++ b/libffi/testsuite/libffi.closures/closure_fn4.c diff --git a/libffi/testsuite/libffi.call/closure_fn5.c b/libffi/testsuite/libffi.closures/closure_fn5.c index 9907442..9907442 100644 --- a/libffi/testsuite/libffi.call/closure_fn5.c +++ b/libffi/testsuite/libffi.closures/closure_fn5.c diff --git a/libffi/testsuite/libffi.call/closure_fn6.c b/libffi/testsuite/libffi.closures/closure_fn6.c index 73c54fd..73c54fd 100644 --- a/libffi/testsuite/libffi.call/closure_fn6.c +++ b/libffi/testsuite/libffi.closures/closure_fn6.c diff --git a/libffi/testsuite/libffi.call/closure_loc_fn0.c b/libffi/testsuite/libffi.closures/closure_loc_fn0.c index b3afa0b..ad488ac 100644 --- a/libffi/testsuite/libffi.call/closure_loc_fn0.c +++ b/libffi/testsuite/libffi.closures/closure_loc_fn0.c @@ -83,7 +83,10 @@ int main (void) CHECK(ffi_prep_closure_loc(pcl, &cif, closure_loc_test_fn0, (void *) 3 /* userdata */, codeloc) == FFI_OK); +#ifndef FFI_EXEC_STATIC_TRAMP + /* With static trampolines, the codeloc does not point to closure */ CHECK(memcmp(pcl, codeloc, sizeof(*pcl)) == 0); +#endif res = (*((closure_loc_test_type0)codeloc)) (1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13, diff --git a/libffi/testsuite/libffi.call/closure_simple.c b/libffi/testsuite/libffi.closures/closure_simple.c index 5a4e728..5a4e728 100644 --- a/libffi/testsuite/libffi.call/closure_simple.c +++ b/libffi/testsuite/libffi.closures/closure_simple.c diff --git a/libffi/testsuite/libffi.call/cls_12byte.c b/libffi/testsuite/libffi.closures/cls_12byte.c index ea0825d..ea0825d 100644 --- a/libffi/testsuite/libffi.call/cls_12byte.c +++ b/libffi/testsuite/libffi.closures/cls_12byte.c diff --git a/libffi/testsuite/libffi.call/cls_16byte.c b/libffi/testsuite/libffi.closures/cls_16byte.c index 89a08a2..89a08a2 100644 --- a/libffi/testsuite/libffi.call/cls_16byte.c +++ b/libffi/testsuite/libffi.closures/cls_16byte.c diff --git a/libffi/testsuite/libffi.call/cls_18byte.c b/libffi/testsuite/libffi.closures/cls_18byte.c index 9f75da8..9f75da8 100644 --- a/libffi/testsuite/libffi.call/cls_18byte.c +++ b/libffi/testsuite/libffi.closures/cls_18byte.c diff --git a/libffi/testsuite/libffi.call/cls_19byte.c b/libffi/testsuite/libffi.closures/cls_19byte.c index 278794b..278794b 100644 --- a/libffi/testsuite/libffi.call/cls_19byte.c +++ b/libffi/testsuite/libffi.closures/cls_19byte.c diff --git a/libffi/testsuite/libffi.call/cls_1_1byte.c b/libffi/testsuite/libffi.closures/cls_1_1byte.c index 82492c0..82492c0 100644 --- a/libffi/testsuite/libffi.call/cls_1_1byte.c +++ b/libffi/testsuite/libffi.closures/cls_1_1byte.c diff --git a/libffi/testsuite/libffi.call/cls_20byte.c b/libffi/testsuite/libffi.closures/cls_20byte.c index 3f8bb28..34ea021 100644 --- a/libffi/testsuite/libffi.call/cls_20byte.c +++ b/libffi/testsuite/libffi.closures/cls_20byte.c @@ -14,7 +14,7 @@ typedef struct cls_struct_20byte { int c; } cls_struct_20byte; -cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1, +static cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1, struct cls_struct_20byte a2) { struct cls_struct_20byte result; diff --git a/libffi/testsuite/libffi.call/cls_20byte1.c b/libffi/testsuite/libffi.closures/cls_20byte1.c index 6562727..eab4be6 100644 --- a/libffi/testsuite/libffi.call/cls_20byte1.c +++ b/libffi/testsuite/libffi.closures/cls_20byte1.c @@ -16,7 +16,7 @@ typedef struct cls_struct_20byte { double c; } cls_struct_20byte; -cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1, +static cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1, struct cls_struct_20byte a2) { struct cls_struct_20byte result; diff --git a/libffi/testsuite/libffi.call/cls_24byte.c b/libffi/testsuite/libffi.closures/cls_24byte.c index 1d82f6e..78796da 100644 --- a/libffi/testsuite/libffi.call/cls_24byte.c +++ b/libffi/testsuite/libffi.closures/cls_24byte.c @@ -31,7 +31,7 @@ cls_struct_24byte cls_struct_24byte_fn(struct cls_struct_24byte b0, b0.a, b0.b, b0.c, b0.d, b1.a, b1.b, b1.c, b1.d, b2.a, b2.b, b2.c, b2.d, - b3.a, b3.b, b3.c, b2.d, + b3.a, b3.b, b3.c, b3.d, result.a, result.b, result.c, result.d); return result; @@ -94,7 +94,7 @@ int main (void) args_dbl[4] = NULL; ffi_call(&cif, FFI_FN(cls_struct_24byte_fn), &res_dbl, args_dbl); - /* { dg-output "9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 9: 22 15 17 25" } */ + /* { dg-output "9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 4: 22 15 17 25" } */ printf("res: %g %g %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); /* { dg-output "\nres: 22 15 17 25" } */ @@ -105,7 +105,7 @@ int main (void) cls_struct_24byte, cls_struct_24byte)) (code))(e_dbl, f_dbl, g_dbl, h_dbl); - /* { dg-output "\n9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 9: 22 15 17 25" } */ + /* { dg-output "\n9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 4: 22 15 17 25" } */ printf("res: %g %g %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); /* { dg-output "\nres: 22 15 17 25" } */ diff --git a/libffi/testsuite/libffi.call/cls_2byte.c b/libffi/testsuite/libffi.closures/cls_2byte.c index 81bb0a6..81bb0a6 100644 --- a/libffi/testsuite/libffi.call/cls_2byte.c +++ b/libffi/testsuite/libffi.closures/cls_2byte.c diff --git a/libffi/testsuite/libffi.call/cls_3_1byte.c b/libffi/testsuite/libffi.closures/cls_3_1byte.c index b782746..b782746 100644 --- a/libffi/testsuite/libffi.call/cls_3_1byte.c +++ b/libffi/testsuite/libffi.closures/cls_3_1byte.c diff --git a/libffi/testsuite/libffi.call/cls_3byte1.c b/libffi/testsuite/libffi.closures/cls_3byte1.c index a02c463..a02c463 100644 --- a/libffi/testsuite/libffi.call/cls_3byte1.c +++ b/libffi/testsuite/libffi.closures/cls_3byte1.c diff --git a/libffi/testsuite/libffi.call/cls_3byte2.c b/libffi/testsuite/libffi.closures/cls_3byte2.c index c7251ce..c7251ce 100644 --- a/libffi/testsuite/libffi.call/cls_3byte2.c +++ b/libffi/testsuite/libffi.closures/cls_3byte2.c diff --git a/libffi/testsuite/libffi.closures/cls_3float.c b/libffi/testsuite/libffi.closures/cls_3float.c new file mode 100644 index 0000000..48888f8 --- /dev/null +++ b/libffi/testsuite/libffi.closures/cls_3float.c @@ -0,0 +1,95 @@ +/* Area: ffi_call, closure_call + Purpose: Check structure passing with different structure size. + Depending on the ABI. Check overlapping. + Limitations:>none. + PR: none. + Originator: <compnerd@compnerd.org> 20171026 */ + +/* { dg-do run } */ + +#include "ffitest.h" + +typedef struct cls_struct_3float { + float f; + float g; + float h; +} cls_struct_3float; + +cls_struct_3float cls_struct_3float_fn(struct cls_struct_3float a1, + struct cls_struct_3float a2) +{ + struct cls_struct_3float result; + + result.f = a1.f + a2.f; + result.g = a1.g + a2.g; + result.h = a1.h + a2.h; + + printf("%g %g %g %g %g %g: %g %g %g\n", a1.f, a1.g, a1.h, + a2.f, a2.g, a2.h, result.f, result.g, result.h); + + return result; +} + +static void +cls_struct_3float_gn(ffi_cif *cif __UNUSED__, void* resp, void **args, + void* userdata __UNUSED__) +{ + struct cls_struct_3float a1, a2; + + a1 = *(struct cls_struct_3float*)(args[0]); + a2 = *(struct cls_struct_3float*)(args[1]); + + *(cls_struct_3float*)resp = cls_struct_3float_fn(a1, a2); +} + +int main (void) +{ + ffi_cif cif; + void *code; + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + void *args_dbl[3]; + ffi_type* cls_struct_fields[4]; + ffi_type cls_struct_type; + ffi_type* dbl_arg_types[3]; + + struct cls_struct_3float g_dbl = { 1.0f, 2.0f, 3.0f }; + struct cls_struct_3float f_dbl = { 1.0f, 2.0f, 3.0f }; + struct cls_struct_3float res_dbl; + + cls_struct_fields[0] = &ffi_type_float; + cls_struct_fields[1] = &ffi_type_float; + cls_struct_fields[2] = &ffi_type_float; + cls_struct_fields[3] = NULL; + + cls_struct_type.size = 0; + cls_struct_type.alignment = 0; + cls_struct_type.type = FFI_TYPE_STRUCT; + cls_struct_type.elements = cls_struct_fields; + + dbl_arg_types[0] = &cls_struct_type; + dbl_arg_types[1] = &cls_struct_type; + dbl_arg_types[2] = NULL; + + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, + dbl_arg_types) == FFI_OK); + + args_dbl[0] = &g_dbl; + args_dbl[1] = &f_dbl; + args_dbl[2] = NULL; + + ffi_call(&cif, FFI_FN(cls_struct_3float_fn), &res_dbl, args_dbl); + /* { dg-output "1 2 3 1 2 3: 2 4 6" } */ + printf("res: %g %g %g\n", res_dbl.f, res_dbl.g, res_dbl.h); + /* { dg-output "\nres: 2 4 6" } */ + + CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_3float_gn, NULL, code) == + FFI_OK); + + res_dbl = ((cls_struct_3float(*)(cls_struct_3float, + cls_struct_3float))(code))(g_dbl, f_dbl); + /* { dg-output "\n1 2 3 1 2 3: 2 4 6" } */ + printf("res: %g %g %g\n", res_dbl.f, res_dbl.g, res_dbl.h); + /* { dg-output "\nres: 2 4 6" } */ + + exit(0); +} diff --git a/libffi/testsuite/libffi.call/cls_4_1byte.c b/libffi/testsuite/libffi.closures/cls_4_1byte.c index 2d6d8b6..2d6d8b6 100644 --- a/libffi/testsuite/libffi.call/cls_4_1byte.c +++ b/libffi/testsuite/libffi.closures/cls_4_1byte.c diff --git a/libffi/testsuite/libffi.call/cls_4byte.c b/libffi/testsuite/libffi.closures/cls_4byte.c index 4ac3787..4ac3787 100644 --- a/libffi/testsuite/libffi.call/cls_4byte.c +++ b/libffi/testsuite/libffi.closures/cls_4byte.c diff --git a/libffi/testsuite/libffi.call/cls_5_1_byte.c b/libffi/testsuite/libffi.closures/cls_5_1_byte.c index ad9d51c..8db761c 100644 --- a/libffi/testsuite/libffi.call/cls_5_1_byte.c +++ b/libffi/testsuite/libffi.closures/cls_5_1_byte.c @@ -16,7 +16,7 @@ typedef struct cls_struct_5byte { unsigned char e; } cls_struct_5byte; -cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1, +static cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1, struct cls_struct_5byte a2) { struct cls_struct_5byte result; diff --git a/libffi/testsuite/libffi.call/cls_5byte.c b/libffi/testsuite/libffi.closures/cls_5byte.c index 4e0c000..fbb69ce 100644 --- a/libffi/testsuite/libffi.call/cls_5byte.c +++ b/libffi/testsuite/libffi.closures/cls_5byte.c @@ -14,7 +14,7 @@ typedef struct cls_struct_5byte { unsigned char c; } cls_struct_5byte; -cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1, +static cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1, struct cls_struct_5byte a2) { struct cls_struct_5byte result; diff --git a/libffi/testsuite/libffi.call/cls_64byte.c b/libffi/testsuite/libffi.closures/cls_64byte.c index a55edc2..a55edc2 100644 --- a/libffi/testsuite/libffi.call/cls_64byte.c +++ b/libffi/testsuite/libffi.closures/cls_64byte.c diff --git a/libffi/testsuite/libffi.call/cls_6_1_byte.c b/libffi/testsuite/libffi.closures/cls_6_1_byte.c index b4dcdba..7970986 100644 --- a/libffi/testsuite/libffi.call/cls_6_1_byte.c +++ b/libffi/testsuite/libffi.closures/cls_6_1_byte.c @@ -17,7 +17,7 @@ typedef struct cls_struct_6byte { unsigned char f; } cls_struct_6byte; -cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1, +static cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1, struct cls_struct_6byte a2) { struct cls_struct_6byte result; diff --git a/libffi/testsuite/libffi.call/cls_6byte.c b/libffi/testsuite/libffi.closures/cls_6byte.c index 7406780..e89c73c 100644 --- a/libffi/testsuite/libffi.call/cls_6byte.c +++ b/libffi/testsuite/libffi.closures/cls_6byte.c @@ -16,7 +16,7 @@ typedef struct cls_struct_6byte { unsigned char d; } cls_struct_6byte; -cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1, +static cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1, struct cls_struct_6byte a2) { struct cls_struct_6byte result; diff --git a/libffi/testsuite/libffi.call/cls_7_1_byte.c b/libffi/testsuite/libffi.closures/cls_7_1_byte.c index 14a7e96..94b1a44 100644 --- a/libffi/testsuite/libffi.call/cls_7_1_byte.c +++ b/libffi/testsuite/libffi.closures/cls_7_1_byte.c @@ -18,7 +18,7 @@ typedef struct cls_struct_7byte { unsigned char g; } cls_struct_7byte; -cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1, +static cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1, struct cls_struct_7byte a2) { struct cls_struct_7byte result; diff --git a/libffi/testsuite/libffi.call/cls_7byte.c b/libffi/testsuite/libffi.closures/cls_7byte.c index 1645cc6..3aa8d6c 100644 --- a/libffi/testsuite/libffi.call/cls_7byte.c +++ b/libffi/testsuite/libffi.closures/cls_7byte.c @@ -15,7 +15,7 @@ typedef struct cls_struct_7byte { unsigned short d; } cls_struct_7byte; -cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1, +static cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1, struct cls_struct_7byte a2) { struct cls_struct_7byte result; diff --git a/libffi/testsuite/libffi.call/cls_8byte.c b/libffi/testsuite/libffi.closures/cls_8byte.c index f6c1ea5..f6c1ea5 100644 --- a/libffi/testsuite/libffi.call/cls_8byte.c +++ b/libffi/testsuite/libffi.closures/cls_8byte.c diff --git a/libffi/testsuite/libffi.call/cls_9byte1.c b/libffi/testsuite/libffi.closures/cls_9byte1.c index 0b85722..6eb4520 100644 --- a/libffi/testsuite/libffi.call/cls_9byte1.c +++ b/libffi/testsuite/libffi.closures/cls_9byte1.c @@ -15,7 +15,7 @@ typedef struct cls_struct_9byte { double b; } cls_struct_9byte; -cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1, +static cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1, struct cls_struct_9byte b2) { struct cls_struct_9byte result; diff --git a/libffi/testsuite/libffi.call/cls_9byte2.c b/libffi/testsuite/libffi.closures/cls_9byte2.c index edf991d..26e460b 100644 --- a/libffi/testsuite/libffi.call/cls_9byte2.c +++ b/libffi/testsuite/libffi.closures/cls_9byte2.c @@ -15,7 +15,7 @@ typedef struct cls_struct_9byte { int b; } cls_struct_9byte; -cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1, +static cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1, struct cls_struct_9byte b2) { struct cls_struct_9byte result; diff --git a/libffi/testsuite/libffi.call/cls_align_double.c b/libffi/testsuite/libffi.closures/cls_align_double.c index aad5f3c..910e228 100644 --- a/libffi/testsuite/libffi.call/cls_align_double.c +++ b/libffi/testsuite/libffi.closures/cls_align_double.c @@ -15,7 +15,7 @@ typedef struct cls_struct_align { unsigned char c; } cls_struct_align; -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, +static cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, struct cls_struct_align a2) { struct cls_struct_align result; diff --git a/libffi/testsuite/libffi.call/cls_align_float.c b/libffi/testsuite/libffi.closures/cls_align_float.c index 37e0855..56161ef 100644 --- a/libffi/testsuite/libffi.call/cls_align_float.c +++ b/libffi/testsuite/libffi.closures/cls_align_float.c @@ -13,7 +13,7 @@ typedef struct cls_struct_align { unsigned char c; } cls_struct_align; -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, +static cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, struct cls_struct_align a2) { struct cls_struct_align result; diff --git a/libffi/testsuite/libffi.call/cls_align_longdouble.c b/libffi/testsuite/libffi.closures/cls_align_longdouble.c index b3322d8..3dccdef 100644 --- a/libffi/testsuite/libffi.call/cls_align_longdouble.c +++ b/libffi/testsuite/libffi.closures/cls_align_longdouble.c @@ -14,7 +14,7 @@ typedef struct cls_struct_align { unsigned char c; } cls_struct_align; -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, +static cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, struct cls_struct_align a2) { struct cls_struct_align result; diff --git a/libffi/testsuite/libffi.call/cls_align_longdouble_split.c b/libffi/testsuite/libffi.closures/cls_align_longdouble_split.c index cc1c43b..9b01cbd 100644 --- a/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +++ b/libffi/testsuite/libffi.closures/cls_align_longdouble_split.c @@ -19,7 +19,7 @@ typedef struct cls_struct_align { long double g; } cls_struct_align; -cls_struct_align cls_struct_align_fn( +static cls_struct_align cls_struct_align_fn( cls_struct_align a1, cls_struct_align a2) { diff --git a/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c b/libffi/testsuite/libffi.closures/cls_align_longdouble_split2.c index 5d3bec0..8a973e7 100644 --- a/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +++ b/libffi/testsuite/libffi.closures/cls_align_longdouble_split2.c @@ -20,7 +20,7 @@ typedef struct cls_struct_align { long double g; } cls_struct_align; -cls_struct_align cls_struct_align_fn( +static cls_struct_align cls_struct_align_fn( cls_struct_align a1, cls_struct_align a2) { diff --git a/libffi/testsuite/libffi.call/cls_align_pointer.c b/libffi/testsuite/libffi.closures/cls_align_pointer.c index 8fbf36a..ef59259 100644 --- a/libffi/testsuite/libffi.call/cls_align_pointer.c +++ b/libffi/testsuite/libffi.closures/cls_align_pointer.c @@ -13,7 +13,7 @@ typedef struct cls_struct_align { unsigned char c; } cls_struct_align; -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, +static cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, struct cls_struct_align a2) { struct cls_struct_align result; diff --git a/libffi/testsuite/libffi.call/cls_align_sint16.c b/libffi/testsuite/libffi.closures/cls_align_sint16.c index 039b874..7997709 100644 --- a/libffi/testsuite/libffi.call/cls_align_sint16.c +++ b/libffi/testsuite/libffi.closures/cls_align_sint16.c @@ -13,7 +13,7 @@ typedef struct cls_struct_align { unsigned char c; } cls_struct_align; -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, +static cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, struct cls_struct_align a2) { struct cls_struct_align result; diff --git a/libffi/testsuite/libffi.call/cls_align_sint32.c b/libffi/testsuite/libffi.closures/cls_align_sint32.c index c96c6d1..5edde72 100644 --- a/libffi/testsuite/libffi.call/cls_align_sint32.c +++ b/libffi/testsuite/libffi.closures/cls_align_sint32.c @@ -13,7 +13,7 @@ typedef struct cls_struct_align { unsigned char c; } cls_struct_align; -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, +static cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, struct cls_struct_align a2) { struct cls_struct_align result; diff --git a/libffi/testsuite/libffi.call/cls_align_sint64.c b/libffi/testsuite/libffi.closures/cls_align_sint64.c index 9aa7bdd..bcba22f 100644 --- a/libffi/testsuite/libffi.call/cls_align_sint64.c +++ b/libffi/testsuite/libffi.closures/cls_align_sint64.c @@ -14,7 +14,7 @@ typedef struct cls_struct_align { unsigned char c; } cls_struct_align; -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, +static cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, struct cls_struct_align a2) { struct cls_struct_align result; diff --git a/libffi/testsuite/libffi.call/cls_align_uint16.c b/libffi/testsuite/libffi.closures/cls_align_uint16.c index 97620b7..f33c0ec 100644 --- a/libffi/testsuite/libffi.call/cls_align_uint16.c +++ b/libffi/testsuite/libffi.closures/cls_align_uint16.c @@ -13,7 +13,7 @@ typedef struct cls_struct_align { unsigned char c; } cls_struct_align; -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, +static cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, struct cls_struct_align a2) { struct cls_struct_align result; diff --git a/libffi/testsuite/libffi.call/cls_align_uint32.c b/libffi/testsuite/libffi.closures/cls_align_uint32.c index 5766fad..c96eee6 100644 --- a/libffi/testsuite/libffi.call/cls_align_uint32.c +++ b/libffi/testsuite/libffi.closures/cls_align_uint32.c @@ -13,7 +13,7 @@ typedef struct cls_struct_align { unsigned char c; } cls_struct_align; -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, +static cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, struct cls_struct_align a2) { struct cls_struct_align result; diff --git a/libffi/testsuite/libffi.call/cls_align_uint64.c b/libffi/testsuite/libffi.closures/cls_align_uint64.c index a52cb89..958e1c2 100644 --- a/libffi/testsuite/libffi.call/cls_align_uint64.c +++ b/libffi/testsuite/libffi.closures/cls_align_uint64.c @@ -15,7 +15,7 @@ typedef struct cls_struct_align { unsigned char c; } cls_struct_align; -cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, +static cls_struct_align cls_struct_align_fn(struct cls_struct_align a1, struct cls_struct_align a2) { struct cls_struct_align result; diff --git a/libffi/testsuite/libffi.call/cls_dbls_struct.c b/libffi/testsuite/libffi.closures/cls_dbls_struct.c index d663791..25b8b63 100644 --- a/libffi/testsuite/libffi.call/cls_dbls_struct.c +++ b/libffi/testsuite/libffi.closures/cls_dbls_struct.c @@ -56,11 +56,11 @@ int main(int argc __UNUSED__, char** argv __UNUSED__) CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_gn, NULL, code) == FFI_OK); - ((void*(*)(Dbls))(code))(arg); - /* { dg-output "1.0 2.0\n" } */ + ((void (*)(Dbls))(code))(arg); + /* { dg-output "1.0 2.0" } */ closure_test_fn(arg); - /* { dg-output "1.0 2.0\n" } */ + /* { dg-output "\n1.0 2.0" } */ return 0; } diff --git a/libffi/testsuite/libffi.call/cls_double.c b/libffi/testsuite/libffi.closures/cls_double.c index 84ad4cb..84ad4cb 100644 --- a/libffi/testsuite/libffi.call/cls_double.c +++ b/libffi/testsuite/libffi.closures/cls_double.c diff --git a/libffi/testsuite/libffi.call/cls_double_va.c b/libffi/testsuite/libffi.closures/cls_double_va.c index e077f92..e077f92 100644 --- a/libffi/testsuite/libffi.call/cls_double_va.c +++ b/libffi/testsuite/libffi.closures/cls_double_va.c diff --git a/libffi/testsuite/libffi.call/cls_float.c b/libffi/testsuite/libffi.closures/cls_float.c index 0090fed..0090fed 100644 --- a/libffi/testsuite/libffi.call/cls_float.c +++ b/libffi/testsuite/libffi.closures/cls_float.c diff --git a/libffi/testsuite/libffi.call/cls_longdouble.c b/libffi/testsuite/libffi.closures/cls_longdouble.c index d24e72e..d24e72e 100644 --- a/libffi/testsuite/libffi.call/cls_longdouble.c +++ b/libffi/testsuite/libffi.closures/cls_longdouble.c diff --git a/libffi/testsuite/libffi.call/cls_longdouble_va.c b/libffi/testsuite/libffi.closures/cls_longdouble_va.c index 39b438b..39b438b 100644 --- a/libffi/testsuite/libffi.call/cls_longdouble_va.c +++ b/libffi/testsuite/libffi.closures/cls_longdouble_va.c diff --git a/libffi/testsuite/libffi.call/cls_many_mixed_args.c b/libffi/testsuite/libffi.closures/cls_many_mixed_args.c index 7fd6c82..7fd6c82 100644 --- a/libffi/testsuite/libffi.call/cls_many_mixed_args.c +++ b/libffi/testsuite/libffi.closures/cls_many_mixed_args.c diff --git a/libffi/testsuite/libffi.call/cls_many_mixed_float_double.c b/libffi/testsuite/libffi.closures/cls_many_mixed_float_double.c index 62b0697a..62b0697a 100644 --- a/libffi/testsuite/libffi.call/cls_many_mixed_float_double.c +++ b/libffi/testsuite/libffi.closures/cls_many_mixed_float_double.c diff --git a/libffi/testsuite/libffi.call/cls_multi_schar.c b/libffi/testsuite/libffi.closures/cls_multi_schar.c index 71df7b6..417f7be 100644 --- a/libffi/testsuite/libffi.call/cls_multi_schar.c +++ b/libffi/testsuite/libffi.closures/cls_multi_schar.c @@ -7,7 +7,7 @@ /* { dg-do run } */ #include "ffitest.h" -signed char test_func_fn(signed char a1, signed char a2) +static signed char test_func_fn(signed char a1, signed char a2) { signed char result; diff --git a/libffi/testsuite/libffi.call/cls_multi_sshort.c b/libffi/testsuite/libffi.closures/cls_multi_sshort.c index 4c39153..467146d 100644 --- a/libffi/testsuite/libffi.call/cls_multi_sshort.c +++ b/libffi/testsuite/libffi.closures/cls_multi_sshort.c @@ -7,7 +7,7 @@ /* { dg-do run } */ #include "ffitest.h" -signed short test_func_fn(signed short a1, signed short a2) +static signed short test_func_fn(signed short a1, signed short a2) { signed short result; diff --git a/libffi/testsuite/libffi.call/cls_multi_sshortchar.c b/libffi/testsuite/libffi.closures/cls_multi_sshortchar.c index 1c3aeb5..de45b59 100644 --- a/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +++ b/libffi/testsuite/libffi.closures/cls_multi_sshortchar.c @@ -7,7 +7,7 @@ /* { dg-do run } */ #include "ffitest.h" -signed short test_func_fn(signed char a1, signed short a2, +static signed short test_func_fn(signed char a1, signed short a2, signed char a3, signed short a4) { signed short result; diff --git a/libffi/testsuite/libffi.call/cls_multi_uchar.c b/libffi/testsuite/libffi.closures/cls_multi_uchar.c index 009c02c..eb93e95 100644 --- a/libffi/testsuite/libffi.call/cls_multi_uchar.c +++ b/libffi/testsuite/libffi.closures/cls_multi_uchar.c @@ -7,7 +7,7 @@ /* { dg-do run } */ #include "ffitest.h" -unsigned char test_func_fn(unsigned char a1, unsigned char a2, +static unsigned char test_func_fn(unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4) { unsigned char result; diff --git a/libffi/testsuite/libffi.call/cls_multi_ushort.c b/libffi/testsuite/libffi.closures/cls_multi_ushort.c index dd10ca7..0e5838d 100644 --- a/libffi/testsuite/libffi.call/cls_multi_ushort.c +++ b/libffi/testsuite/libffi.closures/cls_multi_ushort.c @@ -7,7 +7,7 @@ /* { dg-do run } */ #include "ffitest.h" -unsigned short test_func_fn(unsigned short a1, unsigned short a2) +static unsigned short test_func_fn(unsigned short a1, unsigned short a2) { unsigned short result; diff --git a/libffi/testsuite/libffi.call/cls_multi_ushortchar.c b/libffi/testsuite/libffi.closures/cls_multi_ushortchar.c index 2588e97..69aedfe 100644 --- a/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +++ b/libffi/testsuite/libffi.closures/cls_multi_ushortchar.c @@ -7,7 +7,7 @@ /* { dg-do run } */ #include "ffitest.h" -unsigned short test_func_fn(unsigned char a1, unsigned short a2, +static unsigned short test_func_fn(unsigned char a1, unsigned short a2, unsigned char a3, unsigned short a4) { unsigned short result; diff --git a/libffi/testsuite/libffi.call/cls_pointer.c b/libffi/testsuite/libffi.closures/cls_pointer.c index d82a87a..d82a87a 100644 --- a/libffi/testsuite/libffi.call/cls_pointer.c +++ b/libffi/testsuite/libffi.closures/cls_pointer.c diff --git a/libffi/testsuite/libffi.call/cls_pointer_stack.c b/libffi/testsuite/libffi.closures/cls_pointer_stack.c index 1f1d915..1f1d915 100644 --- a/libffi/testsuite/libffi.call/cls_pointer_stack.c +++ b/libffi/testsuite/libffi.closures/cls_pointer_stack.c diff --git a/libffi/testsuite/libffi.call/cls_schar.c b/libffi/testsuite/libffi.closures/cls_schar.c index 82986b1..82986b1 100644 --- a/libffi/testsuite/libffi.call/cls_schar.c +++ b/libffi/testsuite/libffi.closures/cls_schar.c diff --git a/libffi/testsuite/libffi.call/cls_sint.c b/libffi/testsuite/libffi.closures/cls_sint.c index c7e13b7..c7e13b7 100644 --- a/libffi/testsuite/libffi.call/cls_sint.c +++ b/libffi/testsuite/libffi.closures/cls_sint.c diff --git a/libffi/testsuite/libffi.call/cls_sshort.c b/libffi/testsuite/libffi.closures/cls_sshort.c index 846d57e..846d57e 100644 --- a/libffi/testsuite/libffi.call/cls_sshort.c +++ b/libffi/testsuite/libffi.closures/cls_sshort.c diff --git a/libffi/testsuite/libffi.call/cls_struct_va1.c b/libffi/testsuite/libffi.closures/cls_struct_va1.c index 6d1fdae..6d1fdae 100644 --- a/libffi/testsuite/libffi.call/cls_struct_va1.c +++ b/libffi/testsuite/libffi.closures/cls_struct_va1.c diff --git a/libffi/testsuite/libffi.call/cls_uchar.c b/libffi/testsuite/libffi.closures/cls_uchar.c index c1317e7..c1317e7 100644 --- a/libffi/testsuite/libffi.call/cls_uchar.c +++ b/libffi/testsuite/libffi.closures/cls_uchar.c diff --git a/libffi/testsuite/libffi.call/cls_uint.c b/libffi/testsuite/libffi.closures/cls_uint.c index 885cff5..885cff5 100644 --- a/libffi/testsuite/libffi.call/cls_uint.c +++ b/libffi/testsuite/libffi.closures/cls_uint.c diff --git a/libffi/testsuite/libffi.call/cls_uint_va.c b/libffi/testsuite/libffi.closures/cls_uint_va.c index b04cfd1..b04cfd1 100644 --- a/libffi/testsuite/libffi.call/cls_uint_va.c +++ b/libffi/testsuite/libffi.closures/cls_uint_va.c diff --git a/libffi/testsuite/libffi.call/cls_ulong_va.c b/libffi/testsuite/libffi.closures/cls_ulong_va.c index 0315082..0315082 100644 --- a/libffi/testsuite/libffi.call/cls_ulong_va.c +++ b/libffi/testsuite/libffi.closures/cls_ulong_va.c diff --git a/libffi/testsuite/libffi.call/cls_ulonglong.c b/libffi/testsuite/libffi.closures/cls_ulonglong.c index 62f2cae..62f2cae 100644 --- a/libffi/testsuite/libffi.call/cls_ulonglong.c +++ b/libffi/testsuite/libffi.closures/cls_ulonglong.c diff --git a/libffi/testsuite/libffi.call/cls_ushort.c b/libffi/testsuite/libffi.closures/cls_ushort.c index a00100e..a00100e 100644 --- a/libffi/testsuite/libffi.call/cls_ushort.c +++ b/libffi/testsuite/libffi.closures/cls_ushort.c diff --git a/libffi/testsuite/libffi.call/err_bad_abi.c b/libffi/testsuite/libffi.closures/err_bad_abi.c index f5a7317..f5a7317 100644 --- a/libffi/testsuite/libffi.call/err_bad_abi.c +++ b/libffi/testsuite/libffi.closures/err_bad_abi.c diff --git a/libffi/testsuite/libffi.closures/ffitest.h b/libffi/testsuite/libffi.closures/ffitest.h new file mode 100644 index 0000000..95d96a8 --- /dev/null +++ b/libffi/testsuite/libffi.closures/ffitest.h @@ -0,0 +1,144 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <ffi.h> +#include "fficonfig.h" + +#if defined HAVE_STDINT_H +#include <stdint.h> +#endif + +#if defined HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#define MAX_ARGS 256 + +#define CHECK(x) \ + do { \ + if(!(x)){ \ + printf("Check failed:\n%s\n", #x); \ + abort(); \ + } \ + } while(0) + +/* Define macros so that compilers other than gcc can run the tests. */ +#undef __UNUSED__ +#if defined(__GNUC__) +#define __UNUSED__ __attribute__((__unused__)) +#define __STDCALL__ __attribute__((stdcall)) +#define __THISCALL__ __attribute__((thiscall)) +#define __FASTCALL__ __attribute__((fastcall)) +#define __MSABI__ __attribute__((ms_abi)) +#else +#define __UNUSED__ +#define __STDCALL__ __stdcall +#define __THISCALL__ __thiscall +#define __FASTCALL__ __fastcall +#endif + +#ifndef ABI_NUM +#define ABI_NUM FFI_DEFAULT_ABI +#define ABI_ATTR +#endif + +/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a + file open. */ +#ifdef HAVE_MMAP_ANON +# undef HAVE_MMAP_DEV_ZERO + +# include <sys/mman.h> +# ifndef MAP_FAILED +# define MAP_FAILED -1 +# endif +# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON) +# define MAP_ANONYMOUS MAP_ANON +# endif +# define USING_MMAP + +#endif + +#ifdef HAVE_MMAP_DEV_ZERO + +# include <sys/mman.h> +# ifndef MAP_FAILED +# define MAP_FAILED -1 +# endif +# define USING_MMAP + +#endif + +/* MinGW kludge. */ +#if defined(_WIN64) | defined(_WIN32) +#define PRIdLL "I64d" +#define PRIuLL "I64u" +#else +#define PRIdLL "lld" +#define PRIuLL "llu" +#endif + +/* Tru64 UNIX kludge. */ +#if defined(__alpha__) && defined(__osf__) +/* Tru64 UNIX V4.0 doesn't support %lld/%lld, but long is 64-bit. */ +#undef PRIdLL +#define PRIdLL "ld" +#undef PRIuLL +#define PRIuLL "lu" +#define PRId8 "hd" +#define PRIu8 "hu" +#define PRId64 "ld" +#define PRIu64 "lu" +#define PRIuPTR "lu" +#endif + +/* PA HP-UX kludge. */ +#if defined(__hppa__) && defined(__hpux__) && !defined(PRIuPTR) +#define PRIuPTR "lu" +#endif + +/* IRIX kludge. */ +#if defined(__sgi) +/* IRIX 6.5 <inttypes.h> provides all definitions, but only for C99 + compilations. */ +#define PRId8 "hhd" +#define PRIu8 "hhu" +#if (_MIPS_SZLONG == 32) +#define PRId64 "lld" +#define PRIu64 "llu" +#endif +/* This doesn't match <inttypes.h>, which always has "lld" here, but the + arguments are uint64_t, int64_t, which are unsigned long, long for + 64-bit in <sgidefs.h>. */ +#if (_MIPS_SZLONG == 64) +#define PRId64 "ld" +#define PRIu64 "lu" +#endif +/* This doesn't match <inttypes.h>, which has "u" here, but the arguments + are uintptr_t, which is always unsigned long. */ +#define PRIuPTR "lu" +#endif + +/* Solaris < 10 kludge. */ +#if defined(__sun__) && defined(__svr4__) && !defined(PRIuPTR) +#if defined(__arch64__) || defined (__x86_64__) +#define PRIuPTR "lu" +#else +#define PRIuPTR "u" +#endif +#endif + +/* MSVC kludge. */ +#if defined _MSC_VER +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) +#define PRIuPTR "lu" +#define PRIu8 "u" +#define PRId8 "d" +#define PRIu64 "I64u" +#define PRId64 "I64d" +#endif +#endif + +#ifndef PRIuPTR +#define PRIuPTR "u" +#endif diff --git a/libffi/testsuite/libffi.call/huge_struct.c b/libffi/testsuite/libffi.closures/huge_struct.c index 187c42c..e8e1d86 100644 --- a/libffi/testsuite/libffi.call/huge_struct.c +++ b/libffi/testsuite/libffi.closures/huge_struct.c @@ -7,7 +7,9 @@ /* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ /* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */ -/* { dg-options -Wformat=0 { target moxie*-*-elf } } */ +/* { dg-options -Wformat=0 { target moxie*-*-elf or1k-*-* } } */ + +#include <inttypes.h> #include "ffitest.h" diff --git a/libffi/testsuite/libffi.call/nested_struct.c b/libffi/testsuite/libffi.closures/nested_struct.c index c15e3a0..10797a3 100644 --- a/libffi/testsuite/libffi.call/nested_struct.c +++ b/libffi/testsuite/libffi.closures/nested_struct.c @@ -25,7 +25,7 @@ typedef struct cls_struct_combined { cls_struct_16byte2 e; } cls_struct_combined; -cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0, +static cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0, struct cls_struct_16byte2 b1, struct cls_struct_combined b2) { diff --git a/libffi/testsuite/libffi.call/nested_struct1.c b/libffi/testsuite/libffi.closures/nested_struct1.c index 477a6b9..df8ab59 100644 --- a/libffi/testsuite/libffi.call/nested_struct1.c +++ b/libffi/testsuite/libffi.closures/nested_struct1.c @@ -25,7 +25,7 @@ typedef struct cls_struct_combined { cls_struct_16byte2 e; } cls_struct_combined; -cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0, +static cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0, struct cls_struct_16byte2 b1, struct cls_struct_combined b2, struct cls_struct_16byte1 b3) diff --git a/libffi/testsuite/libffi.call/nested_struct10.c b/libffi/testsuite/libffi.closures/nested_struct10.c index 34a74e7..3cf2b44 100644 --- a/libffi/testsuite/libffi.call/nested_struct10.c +++ b/libffi/testsuite/libffi.closures/nested_struct10.c @@ -32,6 +32,7 @@ static B B_fn(struct A b2, struct B b3, struct C b4) result.x.a = b2.a + b3.x.a + b3.z + b4.d; result.x.b = b2.b + b3.x.b + b3.y + b4.e; result.y = b2.b + b3.x.b + b4.e; + result.z = 0; printf("%d %d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b, (int)b3.x.a, b3.x.b, b3.y, b3.z, (int)b4.d, b4.e, diff --git a/libffi/testsuite/libffi.call/nested_struct11.c b/libffi/testsuite/libffi.closures/nested_struct11.c index 3510493..3510493 100644 --- a/libffi/testsuite/libffi.call/nested_struct11.c +++ b/libffi/testsuite/libffi.closures/nested_struct11.c diff --git a/libffi/testsuite/libffi.closures/nested_struct12.c b/libffi/testsuite/libffi.closures/nested_struct12.c new file mode 100644 index 0000000..0d307ae --- /dev/null +++ b/libffi/testsuite/libffi.closures/nested_struct12.c @@ -0,0 +1,86 @@ +/* Area: ffi_call + Purpose: Check nested float struct. + Limitations: none. + PR: none. + Originator: Cheng Jin <jincheng@ca.ibm.com> */ + +/* { dg-do run } */ +#include "ffitest.h" + +typedef struct stru_FF stru_FF; +typedef struct stru_Nested_F stru_Nested_F; + +struct stru_FF { + float elem1; + float elem2; +}; + +struct stru_Nested_F { + float elem1; + stru_FF elem2; +}; + +static float testNestedFloatStruct(float arg1, stru_Nested_F arg2) +{ + float floatSum = arg1 + arg2.elem1 + arg2.elem2.elem1 + arg2.elem2.elem2; + return floatSum; +} + +int main (void) +{ + float ts12_result = 0; + int structElemNum = 2; + int nestedStructElemNum = 2; + int argNum = 2; + + ffi_cif cif; + ffi_type **struct_float1 = (ffi_type **)malloc(sizeof(ffi_type *) * (structElemNum + 1)); + ffi_type **struct_float2 = (ffi_type **)malloc(sizeof(ffi_type *) * (nestedStructElemNum + 1)); + ffi_type **args = (ffi_type **)malloc(sizeof(ffi_type *) * (argNum + 1)); + void **values = (void **)malloc(sizeof(void *) * (argNum + 1)); + ffi_type struct_float_type1, struct_float_type2; + ffi_type *retType = &ffi_type_float; + float arg1; + float *arg2 = (float *)malloc(sizeof(stru_Nested_F)); + + struct_float2[0] = &ffi_type_float; + struct_float2[1] = &ffi_type_float; + struct_float2[2] = NULL; + + struct_float_type2.size = 0; + struct_float_type2.alignment = 0; + struct_float_type2.type = FFI_TYPE_STRUCT; + struct_float_type2.elements = struct_float2; + + struct_float1[0] = &ffi_type_float; + struct_float1[1] = &struct_float_type2; + struct_float1[2] = NULL; + + struct_float_type1.size = 0; + struct_float_type1.alignment = 0; + struct_float_type1.type = FFI_TYPE_STRUCT; + struct_float_type1.elements = struct_float1; + + args[0] = &ffi_type_float; + args[1] = &struct_float_type1; + args[2] = NULL; + + arg1 = 37.88; + arg2[0] = 31.22; + arg2[1] = 33.44; + arg2[2] = 35.66; + values[0] = &arg1; + values[1] = arg2; + values[2] = NULL; + + CHECK( ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, retType, args) == FFI_OK); + ffi_call(&cif, FFI_FN(testNestedFloatStruct), &ts12_result, values); + CHECK(ts12_result == 138.2f); + + free(struct_float1); + free(struct_float2); + free(args); + free(values); + + exit(0); +} diff --git a/libffi/testsuite/libffi.call/nested_struct12.c b/libffi/testsuite/libffi.closures/nested_struct13.c index 6f3d736..6c139b9 100644 --- a/libffi/testsuite/libffi.call/nested_struct12.c +++ b/libffi/testsuite/libffi.closures/nested_struct13.c @@ -1,8 +1,8 @@ -/* Area: ffi_call, closure_call - Purpose: Check structure passing. - Limitations: none. - PR: none. - Originator: <jincheng@ca.ibm.com> and <jakub@redhat.com> 20210609 */ +/* Area: ffi_call, closure_call + Purpose: Check structure passing. + Limitations: none. + PR: none. + Originator: <jincheng@ca.ibm.com> and <jakub@redhat.com> 20210609 */ /* { dg-do run } */ #include "ffitest.h" @@ -25,7 +25,7 @@ B B_fn(float b0, struct B b1) result.y.b = b0 + b1.y.b; printf("%g %g %g %g: %g %g %g\n", b0, b1.x, b1.y.a, b1.y.b, - result.x, result.y.a, result.y.b); + result.x, result.y.a, result.y.b); return result; } @@ -83,7 +83,7 @@ int main (void) dbl_arg_types[2] = NULL; CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1, - dbl_arg_types) == FFI_OK); + dbl_arg_types) == FFI_OK); args_dbl[0] = &e_dbl; args_dbl[1] = &f_dbl; diff --git a/libffi/testsuite/libffi.call/nested_struct2.c b/libffi/testsuite/libffi.closures/nested_struct2.c index 69268cd..d919e5c 100644 --- a/libffi/testsuite/libffi.call/nested_struct2.c +++ b/libffi/testsuite/libffi.closures/nested_struct2.c @@ -19,7 +19,7 @@ typedef struct B { unsigned char y; } B; -B B_fn(struct A b0, struct B b1) +static B B_fn(struct A b0, struct B b1) { struct B result; diff --git a/libffi/testsuite/libffi.call/nested_struct3.c b/libffi/testsuite/libffi.closures/nested_struct3.c index ab18cad..7d4c2cf 100644 --- a/libffi/testsuite/libffi.call/nested_struct3.c +++ b/libffi/testsuite/libffi.closures/nested_struct3.c @@ -19,7 +19,7 @@ typedef struct B { unsigned char y; } B; -B B_fn(struct A b0, struct B b1) +static B B_fn(struct A b0, struct B b1) { struct B result; diff --git a/libffi/testsuite/libffi.call/nested_struct4.c b/libffi/testsuite/libffi.closures/nested_struct4.c index 2ffb4d6..2ffb4d6 100644 --- a/libffi/testsuite/libffi.call/nested_struct4.c +++ b/libffi/testsuite/libffi.closures/nested_struct4.c diff --git a/libffi/testsuite/libffi.call/nested_struct5.c b/libffi/testsuite/libffi.closures/nested_struct5.c index 6c79845..6c79845 100644 --- a/libffi/testsuite/libffi.call/nested_struct5.c +++ b/libffi/testsuite/libffi.closures/nested_struct5.c diff --git a/libffi/testsuite/libffi.call/nested_struct6.c b/libffi/testsuite/libffi.closures/nested_struct6.c index 59d3579..59d3579 100644 --- a/libffi/testsuite/libffi.call/nested_struct6.c +++ b/libffi/testsuite/libffi.closures/nested_struct6.c diff --git a/libffi/testsuite/libffi.call/nested_struct7.c b/libffi/testsuite/libffi.closures/nested_struct7.c index 27595e6..27595e6 100644 --- a/libffi/testsuite/libffi.call/nested_struct7.c +++ b/libffi/testsuite/libffi.closures/nested_struct7.c diff --git a/libffi/testsuite/libffi.call/nested_struct8.c b/libffi/testsuite/libffi.closures/nested_struct8.c index 0e6c682..0e6c682 100644 --- a/libffi/testsuite/libffi.call/nested_struct8.c +++ b/libffi/testsuite/libffi.closures/nested_struct8.c diff --git a/libffi/testsuite/libffi.call/nested_struct9.c b/libffi/testsuite/libffi.closures/nested_struct9.c index 5f7ac67..5f7ac67 100644 --- a/libffi/testsuite/libffi.call/nested_struct9.c +++ b/libffi/testsuite/libffi.closures/nested_struct9.c diff --git a/libffi/testsuite/libffi.call/problem1.c b/libffi/testsuite/libffi.closures/problem1.c index 6a91555..6a91555 100644 --- a/libffi/testsuite/libffi.call/problem1.c +++ b/libffi/testsuite/libffi.closures/problem1.c diff --git a/libffi/testsuite/libffi.closures/single_entry_structs1.c b/libffi/testsuite/libffi.closures/single_entry_structs1.c new file mode 100644 index 0000000..00c4e17 --- /dev/null +++ b/libffi/testsuite/libffi.closures/single_entry_structs1.c @@ -0,0 +1,86 @@ +/* Area: ffi_call, closure_call + Purpose: Single argument structs have a different ABI in emscripten. + Limitations: none. + PR: none. + Originator: <hood@mit.edu> */ + +/* { dg-do run } */ +#include "ffitest.h" + +typedef struct A { + int a; +} A; + +static struct A A_fn(int b0, struct A b1) +{ + b1.a += b0; + return b1; +} + +static void +A_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, + void* userdata __UNUSED__) +{ + int b0; + struct A b1; + + b0 = *(int*)(args[0]); + b1 = *(struct A*)(args[1]); + + *(A*)resp = A_fn(b0, b1); +} + +int main (void) +{ + printf("123\n"); + ffi_cif cif; + void *code; + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + void* args_dbl[3]; + ffi_type* cls_struct_fields[2]; + ffi_type cls_struct_type; + ffi_type* dbl_arg_types[3]; + + int e_dbl = 12125; + struct A f_dbl = { 31625 }; + + struct A res_dbl; + + cls_struct_type.size = 0; + cls_struct_type.alignment = 0; + cls_struct_type.type = FFI_TYPE_STRUCT; + cls_struct_type.elements = cls_struct_fields; + + cls_struct_fields[0] = &ffi_type_sint; + cls_struct_fields[1] = NULL; + + dbl_arg_types[0] = &ffi_type_sint; + dbl_arg_types[1] = &cls_struct_type; + dbl_arg_types[2] = NULL; + + res_dbl = A_fn(e_dbl, f_dbl); + printf("0 res: %d\n", res_dbl.a); + /* { dg-output "0 res: 43750" } */ + + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, + dbl_arg_types) == FFI_OK); + + args_dbl[0] = &e_dbl; + args_dbl[1] = &f_dbl; + args_dbl[2] = NULL; + + + ffi_call(&cif, FFI_FN(A_fn), &res_dbl, args_dbl); + printf("1 res: %d\n", res_dbl.a); + /* { dg-output "\n1 res: 43750" } */ + CHECK( res_dbl.a == (e_dbl + f_dbl.a)); + + CHECK(ffi_prep_closure_loc(pcl, &cif, A_gn, NULL, code) == FFI_OK); + + res_dbl = ((A(*)(int, A))(code))(e_dbl, f_dbl); + printf("2 res: %d\n", res_dbl.a); + /* { dg-output "\n2 res: 43750" } */ + CHECK( res_dbl.a == (e_dbl + f_dbl.a)); + + exit(0); +} diff --git a/libffi/testsuite/libffi.closures/single_entry_structs2.c b/libffi/testsuite/libffi.closures/single_entry_structs2.c new file mode 100644 index 0000000..ab6556b --- /dev/null +++ b/libffi/testsuite/libffi.closures/single_entry_structs2.c @@ -0,0 +1,102 @@ +/* Area: ffi_call, closure_call + Purpose: Single argument structs have a different ABI in emscripten. + Limitations: none. + PR: none. + Originator: <hood@mit.edu> */ + +/* { dg-do run } */ +#include "ffitest.h" + +typedef struct A { + int a, b; +} A; + +typedef struct B { + struct A y; +} B; + +static struct B B_fn(int b0, struct B b1) +{ + b1.y.a += b0; + b1.y.b -= b0; + return b1; +} + +static void +B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, + void* userdata __UNUSED__) +{ + int b0; + struct B b1; + + b0 = *(int*)(args[0]); + b1 = *(struct B*)(args[1]); + + *(B*)resp = B_fn(b0, b1); +} + +int main (void) +{ + ffi_cif cif; + void *code; + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + void* args_dbl[3]; + ffi_type* cls_struct_fields[3]; + ffi_type* cls_struct_fields1[2]; + ffi_type cls_struct_type, cls_struct_type1; + ffi_type* dbl_arg_types[3]; + + int e_dbl = 12125; + struct B f_dbl = { { 31625, 16723 } }; + + struct B res_dbl; + + cls_struct_type.size = 0; + cls_struct_type.alignment = 0; + cls_struct_type.type = FFI_TYPE_STRUCT; + cls_struct_type.elements = cls_struct_fields; + + cls_struct_type1.size = 0; + cls_struct_type1.alignment = 0; + cls_struct_type1.type = FFI_TYPE_STRUCT; + cls_struct_type1.elements = cls_struct_fields1; + + cls_struct_fields[0] = &ffi_type_sint; + cls_struct_fields[1] = &ffi_type_sint; + cls_struct_fields[2] = NULL; + + cls_struct_fields1[0] = &cls_struct_type; + cls_struct_fields1[1] = NULL; + + + dbl_arg_types[0] = &ffi_type_sint; + dbl_arg_types[1] = &cls_struct_type1; + dbl_arg_types[2] = NULL; + + res_dbl = B_fn(e_dbl, f_dbl); + printf("0 res: %d %d\n", res_dbl.y.a, res_dbl.y.b); + /* { dg-output "0 res: 43750 4598" } */ + + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1, + dbl_arg_types) == FFI_OK); + + args_dbl[0] = &e_dbl; + args_dbl[1] = &f_dbl; + args_dbl[2] = NULL; + + ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl); + printf("1 res: %d %d\n", res_dbl.y.a, res_dbl.y.b); + /* { dg-output "\n1 res: 43750 4598" } */ + CHECK( res_dbl.y.a == (f_dbl.y.a + e_dbl)); + CHECK( res_dbl.y.b == (f_dbl.y.b - e_dbl)); + + CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK); + + res_dbl = ((B(*)(int, B))(code))(e_dbl, f_dbl); + printf("2 res: %d %d\n", res_dbl.y.a, res_dbl.y.b); + /* { dg-output "\n2 res: 43750 4598" } */ + CHECK( res_dbl.y.a == (f_dbl.y.a + e_dbl)); + CHECK( res_dbl.y.b == (f_dbl.y.b - e_dbl)); + + exit(0); +} diff --git a/libffi/testsuite/libffi.closures/single_entry_structs3.c b/libffi/testsuite/libffi.closures/single_entry_structs3.c new file mode 100644 index 0000000..4f619cb --- /dev/null +++ b/libffi/testsuite/libffi.closures/single_entry_structs3.c @@ -0,0 +1,101 @@ +/* Area: ffi_call, closure_call + Purpose: Single argument structs have a different ABI in emscripten. + Limitations: none. + PR: none. + Originator: <hood@mit.edu> */ + +/* { dg-do run } */ +#include "ffitest.h" + +typedef struct A { + int a; +} A; + +typedef struct B { + struct A y; +} B; + +static struct B B_fn(int b0, struct B b1) +{ + b1.y.a += b0; + return b1; +} + +static void +B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, + void* userdata __UNUSED__) +{ + int b0; + struct B b1; + + b0 = *(int*)(args[0]); + b1 = *(struct B*)(args[1]); + + *(B*)resp = B_fn(b0, b1); +} + +int main (void) +{ + printf("123\n"); + ffi_cif cif; + void *code; + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + void* args_dbl[3]; + ffi_type* cls_struct_fields[2]; + ffi_type* cls_struct_fields1[2]; + ffi_type cls_struct_type, cls_struct_type1; + ffi_type* dbl_arg_types[3]; + + int e_dbl = 12125; + struct B f_dbl = { { 31625 } }; + + struct B res_dbl; + + cls_struct_type.size = 0; + cls_struct_type.alignment = 0; + cls_struct_type.type = FFI_TYPE_STRUCT; + cls_struct_type.elements = cls_struct_fields; + + cls_struct_type1.size = 0; + cls_struct_type1.alignment = 0; + cls_struct_type1.type = FFI_TYPE_STRUCT; + cls_struct_type1.elements = cls_struct_fields1; + + cls_struct_fields[0] = &ffi_type_sint; + cls_struct_fields[1] = NULL; + + cls_struct_fields1[0] = &cls_struct_type; + cls_struct_fields1[1] = NULL; + + + dbl_arg_types[0] = &ffi_type_sint; + dbl_arg_types[1] = &cls_struct_type1; + dbl_arg_types[2] = NULL; + + res_dbl = B_fn(e_dbl, f_dbl); + printf("0 res: %d\n", res_dbl.y.a); + /* { dg-output "0 res: 43750" } */ + + + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1, + dbl_arg_types) == FFI_OK); + + args_dbl[0] = &e_dbl; + args_dbl[1] = &f_dbl; + args_dbl[2] = NULL; + + + ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl); + printf("1 res: %d\n", res_dbl.y.a); + /* { dg-output "\n1 res: 43750" } */ + CHECK( res_dbl.y.a == (e_dbl + f_dbl.y.a)); + + CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK); + + res_dbl = ((B(*)(int, B))(code))(e_dbl, f_dbl); + printf("2 res: %d\n", res_dbl.y.a); + /* { dg-output "\n2 res: 43750" } */ + CHECK( res_dbl.y.a == (e_dbl + f_dbl.y.a)); + + exit(0); +} diff --git a/libffi/testsuite/libffi.call/stret_large.c b/libffi/testsuite/libffi.closures/stret_large.c index 71c2469..71c2469 100644 --- a/libffi/testsuite/libffi.call/stret_large.c +++ b/libffi/testsuite/libffi.closures/stret_large.c diff --git a/libffi/testsuite/libffi.call/stret_large2.c b/libffi/testsuite/libffi.closures/stret_large2.c index d9c750e..d9c750e 100644 --- a/libffi/testsuite/libffi.call/stret_large2.c +++ b/libffi/testsuite/libffi.closures/stret_large2.c diff --git a/libffi/testsuite/libffi.call/stret_medium.c b/libffi/testsuite/libffi.closures/stret_medium.c index 973ee02..56e3d9d 100644 --- a/libffi/testsuite/libffi.call/stret_medium.c +++ b/libffi/testsuite/libffi.closures/stret_medium.c @@ -21,7 +21,7 @@ typedef struct struct_72byte { double i; } struct_72byte; -struct_72byte cls_struct_72byte_fn( +static struct_72byte cls_struct_72byte_fn( struct_72byte b0, struct_72byte b1, struct_72byte b2, diff --git a/libffi/testsuite/libffi.call/stret_medium2.c b/libffi/testsuite/libffi.closures/stret_medium2.c index 84323d1..0746b6e 100644 --- a/libffi/testsuite/libffi.call/stret_medium2.c +++ b/libffi/testsuite/libffi.closures/stret_medium2.c @@ -22,7 +22,7 @@ typedef struct struct_72byte { long long i; } struct_72byte; -struct_72byte cls_struct_72byte_fn( +static struct_72byte cls_struct_72byte_fn( struct_72byte b0, struct_72byte b1, struct_72byte b2, diff --git a/libffi/testsuite/libffi.call/testclosure.c b/libffi/testsuite/libffi.closures/testclosure.c index ca31056..600368e 100644 --- a/libffi/testsuite/libffi.call/testclosure.c +++ b/libffi/testsuite/libffi.closures/testclosure.c @@ -14,7 +14,7 @@ typedef struct cls_struct_combined { float d; } cls_struct_combined; -void cls_struct_combined_fn(struct cls_struct_combined arg) +static void cls_struct_combined_fn(struct cls_struct_combined arg) { printf("%g %g %g %g\n", arg.a, arg.b, diff --git a/libffi/testsuite/libffi.special/unwindtest.cc b/libffi/testsuite/libffi.closures/unwindtest.cc index d7ffd4a..e114565 100644 --- a/libffi/testsuite/libffi.special/unwindtest.cc +++ b/libffi/testsuite/libffi.closures/unwindtest.cc @@ -4,18 +4,11 @@ PR: none. Originator: Jeff Sturm <jsturm@one-point.com> */ -/* { dg-do run } */ -#include "ffitestcxx.h" +/* { dg-do run { xfail x86_64-apple-darwin* moxie*-*-* } } */ -#if defined HAVE_STDINT_H -#include <stdint.h> -#endif +#include "ffitest.h" -#if defined HAVE_INTTYPES_H -#include <inttypes.h> -#endif - -void +void ABI_ATTR closure_test_fn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__, void** args __UNUSED__, void* userdata __UNUSED__) { diff --git a/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc b/libffi/testsuite/libffi.closures/unwindtest_ffi_call.cc index 29739cd..153d240 100644 --- a/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc +++ b/libffi/testsuite/libffi.closures/unwindtest_ffi_call.cc @@ -4,8 +4,9 @@ PR: none. Originator: Andreas Tobler <andreast@gcc.gnu.org> 20061213 */ -/* { dg-do run } */ -#include "ffitestcxx.h" +/* { dg-do run { xfail moxie*-*-* } } */ + +#include "ffitest.h" static int checking(int a __UNUSED__, short b __UNUSED__, signed char c __UNUSED__) diff --git a/libffi/testsuite/libffi.go/static-chain.h b/libffi/testsuite/libffi.go/static-chain.h index e120eea..3675b40 100644 --- a/libffi/testsuite/libffi.go/static-chain.h +++ b/libffi/testsuite/libffi.go/static-chain.h @@ -4,12 +4,6 @@ # define STATIC_CHAIN_REG "$1" #elif defined(__arm__) # define STATIC_CHAIN_REG "ip" -#elif defined(__hppa__) -# if defined(__LP64) -# define define STATIC_CHAIN_REG "%r31" -# else -# define define STATIC_CHAIN_REG "%r29" /* %ret1 */ -# endif #elif defined(__sparc__) # if defined(__arch64__) || defined(__sparcv9) # define STATIC_CHAIN_REG "g5" diff --git a/libffi/testsuite/libffi.special/ffitestcxx.h b/libffi/testsuite/libffi.special/ffitestcxx.h deleted file mode 100644 index 83f5442..0000000 --- a/libffi/testsuite/libffi.special/ffitestcxx.h +++ /dev/null @@ -1,96 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <fcntl.h> -#include <ffi.h> -#include "fficonfig.h" - -#define MAX_ARGS 256 - - -/* Define __UNUSED__ that also other compilers than gcc can run the tests. */ -#undef __UNUSED__ -#if defined(__GNUC__) -#define __UNUSED__ __attribute__((__unused__)) -#else -#define __UNUSED__ -#endif - -#define CHECK(x) (!(x) ? abort() : (void)0) - -/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a - file open. */ -#ifdef HAVE_MMAP_ANON -# undef HAVE_MMAP_DEV_ZERO - -# include <sys/mman.h> -# ifndef MAP_FAILED -# define MAP_FAILED -1 -# endif -# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON) -# define MAP_ANONYMOUS MAP_ANON -# endif -# define USING_MMAP - -#endif - -#ifdef HAVE_MMAP_DEV_ZERO - -# include <sys/mman.h> -# ifndef MAP_FAILED -# define MAP_FAILED -1 -# endif -# define USING_MMAP - -#endif - - -/* MinGW kludge. */ -#ifdef _WIN64 -#define PRIdLL "I64d" -#define PRIuLL "I64u" -#else -#define PRIdLL "lld" -#define PRIuLL "llu" -#endif - -#ifdef USING_MMAP -static inline void * -allocate_mmap (size_t size) -{ - void *page; -#if defined (HAVE_MMAP_DEV_ZERO) - static int dev_zero_fd = -1; -#endif - -#ifdef HAVE_MMAP_DEV_ZERO - if (dev_zero_fd == -1) - { - dev_zero_fd = open ("/dev/zero", O_RDONLY); - if (dev_zero_fd == -1) - { - perror ("open /dev/zero: %m"); - exit (1); - } - } -#endif - - -#ifdef HAVE_MMAP_ANON - page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -#endif -#ifdef HAVE_MMAP_DEV_ZERO - page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE, dev_zero_fd, 0); -#endif - - if (page == (char *) MAP_FAILED) - { - perror ("virtual memory exhausted"); - exit (1); - } - - return page; -} - -#endif diff --git a/libffi/testsuite/libffi.special/special.exp b/libffi/testsuite/libffi.special/special.exp deleted file mode 100644 index 74671b1..0000000 --- a/libffi/testsuite/libffi.special/special.exp +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) 2003, 2006, 2009, 2010 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING3. If not see -# <http://www.gnu.org/licenses/>. - -dg-init -libffi-init - -global srcdir subdir - -global cxx_options - -set cxx_options " -shared-libgcc -lstdc++" - -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] $cxx_options "-O0 -W -Wall" -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] $cxx_options "-O2" -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] $cxx_options "-O3" -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] $cxx_options "-Os" - -dg-finish - -# Local Variables: -# tcl-indent-level:4 -# End: diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 12816cc..ccad9a3 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,17 @@ +2021-10-18 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/102086 + PR fortran/92189 + PR fortran/92621 + PR fortran/101308 + PR fortran/101309 + PR fortran/101635 + PR fortran/92482 + * ISO_Fortran_binding.h (CFI_type_cfunptr): Make unique type again. + * runtime/ISO_Fortran_binding.c (cfi_desc_to_gfc_desc, + gfc_desc_to_cfi_desc): Add comment that those are no longer called + by new code. + 2021-09-27 Tobias Burnus <tobias@codesourcery.com> PR fortran/94070 diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 4917102..50d14b3 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,42 @@ +2021-10-20 Chung-Lin Tang <cltang@codesourcery.com> + + * testsuite/libgomp.fortran/target-in-reduction-1.f90: New test. + * testsuite/libgomp.fortran/target-in-reduction-2.f90: New test. + +2021-10-20 Jakub Jelinek <jakub@redhat.com> + + PR libgomp/102838 + * libgomp.h (struct gomp_work_share_1st_cacheline): New type. + (struct gomp_work_share): Only use aligned(64) attribute if + GOMP_HAVE_EFFICIENT_ALIGNED_ALLOC is defined, otherwise just + add padding before lock to ensure lock is at offset 64 bytes + into the structure. + (gomp_workshare_struct_check1, gomp_workshare_struct_check2): + New poor man's static assertions. + * work.c (gomp_work_share_start): Use gomp_aligned_alloc instead of + gomp_malloc if GOMP_HAVE_EFFICIENT_ALIGNED_ALLOC. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + Richard Biener <rguenther@suse.de> + + * testsuite/libgomp.graphite/force-parallel-5.c: Remove xfail. + +2021-10-18 Jakub Jelinek <jakub@redhat.com> + + * config/linux/affinity.c (gomp_affinity_init_numa_domains): Add + && gomp_places_list_len < count after nfirst <= nlast loop condition. + +2021-10-18 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/102086 + PR fortran/92189 + PR fortran/92621 + PR fortran/101308 + PR fortran/101309 + PR fortran/101635 + PR fortran/92482 + * testsuite/libgomp.fortran/optional-bind-c.f90: New test. + 2021-10-15 Jakub Jelinek <jakub@redhat.com> * testsuite/libgomp.c/affinity-1.c (struct places): Change name field diff --git a/libgomp/config/linux/affinity.c b/libgomp/config/linux/affinity.c index e11906a..ce86c58 100644 --- a/libgomp/config/linux/affinity.c +++ b/libgomp/config/linux/affinity.c @@ -401,7 +401,7 @@ gomp_affinity_init_numa_domains (unsigned long count, cpu_set_t *copy, break; q = end; } - for (; nfirst <= nlast; nfirst++) + for (; nfirst <= nlast && gomp_places_list_len < count; nfirst++) { sprintf (name + prefix_len, "node%lu/cpulist", nfirst); f = fopen (name, "r"); diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h index 33a9591..023d8a8 100644 --- a/libgomp/libgomp.h +++ b/libgomp/libgomp.h @@ -257,6 +257,30 @@ struct gomp_doacross_work_share unsigned int shift_counts[]; }; +/* Like struct gomp_work_share, but only the 1st cacheline of it plus + flexible array at the end. + Keep in sync with struct gomp_work_share. */ +struct gomp_work_share_1st_cacheline +{ + enum gomp_schedule_type sched; + int mode; + union { + struct { + long chunk_size, end, incr; + }; + struct { + unsigned long long chunk_size_ull, end_ull, incr_ull; + }; + }; + union { + unsigned *ordered_team_ids; + struct gomp_doacross_work_share *doacross; + }; + unsigned ordered_num_used, ordered_owner, ordered_cur; + struct gomp_work_share *next_alloc; + char pad[]; +}; + struct gomp_work_share { /* This member records the SCHEDULE clause to be used for this construct. @@ -324,7 +348,12 @@ struct gomp_work_share are in a different cache line. */ /* This lock protects the update of the following members. */ +#ifdef GOMP_HAVE_EFFICIENT_ALIGNED_ALLOC gomp_mutex_t lock __attribute__((aligned (64))); +#else + char pad[64 - offsetof (struct gomp_work_share_1st_cacheline, pad)]; + gomp_mutex_t lock; +#endif /* This is the count of the number of threads that have exited the work share construct. If the construct was marked nowait, they have moved on @@ -362,6 +391,12 @@ struct gomp_work_share unsigned inline_ordered_team_ids[0]; }; +extern char gomp_workshare_struct_check1 + [offsetof (struct gomp_work_share_1st_cacheline, next_alloc) + == offsetof (struct gomp_work_share, next_alloc) ? 1 : -1]; +extern char gomp_workshare_struct_check2 + [offsetof (struct gomp_work_share, lock) == 64 ? 1 : -1]; + /* This structure contains all of the thread-local data associated with a thread team. This is the data that must be saved when a thread encounters a nested PARALLEL construct. */ diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index 0219504..e711707 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -337,7 +337,7 @@ The OpenMP 4.5 specification is fully supported. @multitable @columnfractions .60 .10 .25 @headitem Description @tab Status @tab Comments -@item Support of strictly structured blocks in Fortran @tab N @tab +@item Support of strictly structured blocks in Fortran @tab Y @tab @item Support of structured block sequences in C/C++ @tab Y @tab @item @code{unconstrained} and @code{reproducible} modifiers on @code{order} clause @tab Y @tab diff --git a/libgomp/testsuite/libgomp.fortran/target-in-reduction-1.f90 b/libgomp/testsuite/libgomp.fortran/target-in-reduction-1.f90 new file mode 100644 index 0000000..f9acb71 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/target-in-reduction-1.f90 @@ -0,0 +1,78 @@ +! { dg-do run } + +module mod1 + contains + + subroutine foo (x, y) + integer :: x, y + + !$omp taskgroup task_reduction (+: x, y) + + !$omp target in_reduction (+: x, y) + x = x + 8 + y = y + 16 + !$omp end target + + !$omp task in_reduction (+: x, y) + x = x + 2 + y = y + 4 + !$omp end task + + !$omp end taskgroup + end subroutine foo + + integer function bar (x) + integer, value :: x + + !$omp taskgroup task_reduction (+: x) + + !$omp target in_reduction (+: x) + x = x + 16 + !$omp end target + + !$omp task in_reduction (+: x) + x = x + 32 + !$omp end task + + !$omp end taskgroup + + bar = x + end function bar + end module mod1 + +program main + use mod1 + integer :: x, y + real :: f; + + x = 1 + y = 1 + + call foo (x, y) + + if (x .ne. 11) stop 1 + if (y .ne. 21) stop 2 + + y = bar (8) + if (y .ne. 56) stop 3 + + x = 0 + f = 0.0 + + !$omp taskgroup task_reduction (+: x, f) + !$omp target in_reduction (+: x, f) + x = x + 1 + f = f + 2.0 + !$omp end target + + !$omp task in_reduction (+: x, f) + x = x + 2 + f = f + 3.0 + !$omp end task + + !$omp end taskgroup + + if (x .ne. 3) stop 4 + if (f .ne. 5.0) stop 5 + +end program main diff --git a/libgomp/testsuite/libgomp.fortran/target-in-reduction-2.f90 b/libgomp/testsuite/libgomp.fortran/target-in-reduction-2.f90 new file mode 100644 index 0000000..7f2e16b --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/target-in-reduction-2.f90 @@ -0,0 +1,30 @@ +! { dg-do run } + +program main + integer :: x + + x = 0 + !$omp taskgroup task_reduction (+: x) + call foo (x) + call bar (x) + !$omp end taskgroup + + if (x .ne. 3) stop 1 + +contains + + subroutine foo (x) + integer :: x + !$omp task in_reduction (+: x) + x = x + 1 + !$omp end task + end subroutine foo + + subroutine bar (x) + integer :: x + !$omp target in_reduction (+: x) + x = x + 2 + !$omp end target + end subroutine bar + +end program main diff --git a/libgomp/testsuite/libgomp.fortran/task-reduction-16.f90 b/libgomp/testsuite/libgomp.fortran/task-reduction-16.f90 index c6b39e0..5b8617a 100644 --- a/libgomp/testsuite/libgomp.fortran/task-reduction-16.f90 +++ b/libgomp/testsuite/libgomp.fortran/task-reduction-16.f90 @@ -20,6 +20,7 @@ contains !$omp scope reduction (task, iand: c) !$omp barrier !$omp sections + !$omp section block a = a + 1; b(0) = b(0) * 2; call bar (2); b(2) = b(2) * 3 c(1) = iand(c(1), not(ishft(1_8, 2))) diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-5.c b/libgomp/testsuite/libgomp.graphite/force-parallel-5.c index b83ca79..de31d64 100644 --- a/libgomp/testsuite/libgomp.graphite/force-parallel-5.c +++ b/libgomp/testsuite/libgomp.graphite/force-parallel-5.c @@ -31,6 +31,6 @@ int main(void) } /* Check that parallel code generation part make the right answer. */ -/* { dg-final { scan-tree-dump-times "2 loops carried no dependency" 1 "graphite" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "2 loops carried no dependency" 1 "graphite" } } */ /* { dg-final { scan-tree-dump-times "loopfn.0" 4 "optimized" } } */ /* { dg-final { scan-tree-dump-times "loopfn.1" 4 "optimized" } } */ diff --git a/libgomp/work.c b/libgomp/work.c index 9d63eec..bf25591 100644 --- a/libgomp/work.c +++ b/libgomp/work.c @@ -191,7 +191,12 @@ gomp_work_share_start (size_t ordered) /* Work sharing constructs can be orphaned. */ if (team == NULL) { +#ifdef GOMP_HAVE_EFFICIENT_ALIGNED_ALLOC + ws = gomp_aligned_alloc (__alignof (struct gomp_work_share), + sizeof (*ws)); +#else ws = gomp_malloc (sizeof (*ws)); +#endif gomp_init_work_share (ws, ordered, 1); thr->ts.work_share = ws; return true; diff --git a/liboffloadmic/ChangeLog b/liboffloadmic/ChangeLog index b027ed7..4dbc6ba 100644 --- a/liboffloadmic/ChangeLog +++ b/liboffloadmic/ChangeLog @@ -1,3 +1,8 @@ +2021-10-19 Martin Liska <mliska@suse.cz> + + * include/coi/source/COIBuffer_source.h: Convert 2 chars to + unicode. + 2021-05-25 Richard Biener <rguenther@suse.de> PR libgomp/100747 diff --git a/liboffloadmic/include/coi/source/COIBuffer_source.h b/liboffloadmic/include/coi/source/COIBuffer_source.h index e1f9157..b90d505 100644 --- a/liboffloadmic/include/coi/source/COIBuffer_source.h +++ b/liboffloadmic/include/coi/source/COIBuffer_source.h @@ -373,7 +373,7 @@ typedef struct arr_desc { int64_t base; // Base address int64_t rank; // Rank of array, i.e. number of dimensions - dim_desc dim[3]; // This array has as many elements as “rank” + dim_desc dim[3]; // This array has as many elements as 'rank' // currently limited to 3. } arr_desc; diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 785c946..3aa8a53 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,111 @@ +2021-10-20 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/20_util/optional/monadic/transform.cc: Check that + an rvalue result is not materialized too soon. + +2021-10-19 Patrick Palka <ppalka@redhat.com> + + * include/std/ranges (iota_view::_Iterator::operator+): Adjust + definition as per LWG 3580. + (iota_view::_Iterator::operator-): Likewise. + +2021-10-19 Patrick Palka <ppalka@redhat.com> + + * include/std/ranges (basic_istream_view::_M_object): Value + initialize as per LWG 3568. + +2021-10-19 Patrick Palka <ppalka@redhat.com> + + * include/bits/ranges_util.h + (__detail::__uses_nonqualification_pointer_conversion): Define + and use it ... + (__detail::__convertible_to_nonslicing): ... here, as per LWG 3470. + * testsuite/std/ranges/subrange/1.cc: New test. + +2021-10-19 Patrick Palka <ppalka@redhat.com> + + * include/std/ranges (iota_view::_Iterator): Befriend iota_view. + (iota_view::_Sentinel): Likewise. + (iota_view::iota_view): Add three overloads, each taking an + iterator/sentinel pair as per LWG 3523. + * testsuite/std/ranges/iota/iota_view.cc (test06): New test. + +2021-10-19 Patrick Palka <ppalka@redhat.com> + + * include/bits/ranges_base.h (view_interface): Forward declare. + (__detail::__is_derived_from_view_interface_fn): Declare. + (__detail::__is_derived_from_view_interface): Define as per LWG 3549. + (enable_view): Adjust as per LWG 3549. + * include/bits/ranges_util.h (view_interface): Don't derive from + view_base. + * include/std/ranges (filter_view): Revert r11-3504 change. + (transform_view): Likewise. + (take_view): Likewise. + (take_while_view): Likewise. + (drop_view): Likewise. + (drop_while_view): Likewise. + (join_view): Likewise. + (lazy_split_view): Likewise. + (split_view): Likewise. + (reverse_view): Likewise. + * testsuite/std/ranges/adaptors/sizeof.cc: Update expected sizes. + * testsuite/std/ranges/view.cc (test_view::test_view): Remove + this default ctor since views no longer need to be default initable. + (test01): New test. + +2021-10-19 Jonathan Wakely <jwakely@redhat.com> + + * src/c++11/random.cc (which_source): New helper function. + (random_device::_M_getentropy()): Use which_source and return + suitable values for sources other than device files. + * testsuite/26_numerics/random/random_device/entropy.cc: New test. + +2021-10-19 Jonathan Wakely <jwakely@redhat.com> + + * doc/Makefile.am (stamp-html-doxygen, stamp-html-doxygen) + (stamp-latex-doxygen, stamp-man-doxygen): Fix recipes for + relative ${top_srcdir}. + * doc/Makefile.in: Regenerate. + +2021-10-19 Jonathan Wakely <jwakely@redhat.com> + + * include/std/variant (_Uninitialized): Use an empty struct + for the unused union member, instead of char. + +2021-10-19 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/stl_stack.h (stack(Iterator, Iterator)): Remove + non-deducible template parameter from deduction guide. + * testsuite/23_containers/stack/deduction.cc: Check new C++23 + deduction guides. + +2021-10-19 Jonathan Wakely <jwakely@redhat.com> + + * include/std/optional (_Optional_payload_base::_Storage): Add + constructor taking a callable function to invoke. + (_Optional_payload_base::_M_apply): New function. + (__cpp_lib_monadic_optional): Define for C++23. + (optional::and_then, optional::transform, optional::or_else): + Define for C++23. + * include/std/ranges (__detail::__cached): Remove. + (__detail::__non_propagating_cache): Remove use of __cached for + contained value. Use _Optional_payload_base::_M_construct and + _Optional_payload_base::_M_apply to set the contained value. + * include/std/version (__cpp_lib_monadic_optional): Define. + * testsuite/20_util/optional/monadic/and_then.cc: New test. + * testsuite/20_util/optional/monadic/or_else.cc: New test. + * testsuite/20_util/optional/monadic/or_else_neg.cc: New test. + * testsuite/20_util/optional/monadic/transform.cc: New test. + * testsuite/20_util/optional/monadic/version.cc: New test. + +2021-10-19 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/102825 + * include/bits/mofunc_impl.h (move_only_function): Remove + invalid base initializer. + * testsuite/20_util/move_only_function/cons.cc: Instantiate + constructors to check bodies. + 2021-10-15 Jonathan Wakely <jwakely@redhat.com> * include/bits/fs_path.h (path::_S_convert(T)): Avoid recursive diff --git a/libstdc++-v3/doc/Makefile.am b/libstdc++-v3/doc/Makefile.am index 487e862..0aacf3f 100644 --- a/libstdc++-v3/doc/Makefile.am +++ b/libstdc++-v3/doc/Makefile.am @@ -226,10 +226,11 @@ ${doxygen_outdir}/man: mkdir -p ${doxygen_outdir}/man stamp-xml-doxygen: ${doxygen_outdir}/xml - @builddir=`cd ..; ${PWD_COMMAND}`; \ + -srcdir=`cd ${top_srcdir}; ${PWD_COMMAND}`; \ + builddir=`cd ..; ${PWD_COMMAND}`; \ ${SHELL} ${doxygen_script} \ --host_alias=${host_alias} --mode=xml \ - "${top_srcdir}" "$${builddir}" NO || true + "$${srcdir}" "$${builddir}" NO $(STAMP) stamp-xml-doxygen stamp-xml-single-doxygen: stamp-xml-doxygen @@ -239,17 +240,19 @@ stamp-xml-single-doxygen: stamp-xml-doxygen $(STAMP) stamp-xml-single-doxygen stamp-html-doxygen: ${doxygen_outdir}/html - @builddir=`cd ..; ${PWD_COMMAND}`; \ + -srcdir=`cd ${top_srcdir}; ${PWD_COMMAND}`; \ + builddir=`cd ..; ${PWD_COMMAND}`; \ ${SHELL} ${doxygen_script} \ --host_alias=${host_alias} --mode=html \ - "${top_srcdir}" "$${builddir}" YES || true + "$${srcdir}" "$${builddir}" YES $(STAMP) stamp-html-doxygen stamp-latex-doxygen: ${doxygen_outdir}/latex - @builddir=`cd ..; ${PWD_COMMAND}`; \ + -srcdir=`cd ${top_srcdir}; ${PWD_COMMAND}`; \ + builddir=`cd ..; ${PWD_COMMAND}`; \ ${SHELL} ${doxygen_script} \ --host_alias=${host_alias} --mode=latex --latex_cmd=$(LATEX_CMD) \ - "${top_srcdir}" "$${builddir}" NO || true + "$${srcdir}" "$${builddir}" NO $(STAMP) stamp-latex-doxygen # Chance of loooooonnggg creation time on this rule. Iff this fails, @@ -274,10 +277,11 @@ stamp-pdf-doxygen: stamp-latex-doxygen ${doxygen_outdir}/pdf $(STAMP) stamp-pdf-doxygen stamp-man-doxygen: ${doxygen_outdir}/man - @builddir=`cd ..; ${PWD_COMMAND}`; \ + -srcdir=`cd ${top_srcdir}; ${PWD_COMMAND}`; \ + builddir=`cd ..; ${PWD_COMMAND}`; \ ${SHELL} ${doxygen_script} \ --host_alias=${host_alias} --mode=man \ - "${top_srcdir}" "$${builddir}" YES || true + "$${srcdir}" "$${builddir}" YES $(STAMP) stamp-man-doxygen doc-xml-doxygen: stamp-xml-doxygen diff --git a/libstdc++-v3/doc/Makefile.in b/libstdc++-v3/doc/Makefile.in index fe1113e..bfb3ce7 100644 --- a/libstdc++-v3/doc/Makefile.in +++ b/libstdc++-v3/doc/Makefile.in @@ -917,10 +917,11 @@ ${doxygen_outdir}/man: mkdir -p ${doxygen_outdir}/man stamp-xml-doxygen: ${doxygen_outdir}/xml - @builddir=`cd ..; ${PWD_COMMAND}`; \ + -srcdir=`cd ${top_srcdir}; ${PWD_COMMAND}`; \ + builddir=`cd ..; ${PWD_COMMAND}`; \ ${SHELL} ${doxygen_script} \ --host_alias=${host_alias} --mode=xml \ - "${top_srcdir}" "$${builddir}" NO || true + "$${srcdir}" "$${builddir}" NO $(STAMP) stamp-xml-doxygen stamp-xml-single-doxygen: stamp-xml-doxygen @@ -930,17 +931,19 @@ stamp-xml-single-doxygen: stamp-xml-doxygen $(STAMP) stamp-xml-single-doxygen stamp-html-doxygen: ${doxygen_outdir}/html - @builddir=`cd ..; ${PWD_COMMAND}`; \ + -srcdir=`cd ${top_srcdir}; ${PWD_COMMAND}`; \ + builddir=`cd ..; ${PWD_COMMAND}`; \ ${SHELL} ${doxygen_script} \ --host_alias=${host_alias} --mode=html \ - "${top_srcdir}" "$${builddir}" YES || true + "$${srcdir}" "$${builddir}" YES $(STAMP) stamp-html-doxygen stamp-latex-doxygen: ${doxygen_outdir}/latex - @builddir=`cd ..; ${PWD_COMMAND}`; \ + -srcdir=`cd ${top_srcdir}; ${PWD_COMMAND}`; \ + builddir=`cd ..; ${PWD_COMMAND}`; \ ${SHELL} ${doxygen_script} \ --host_alias=${host_alias} --mode=latex --latex_cmd=$(LATEX_CMD) \ - "${top_srcdir}" "$${builddir}" NO || true + "$${srcdir}" "$${builddir}" NO $(STAMP) stamp-latex-doxygen # Chance of loooooonnggg creation time on this rule. Iff this fails, @@ -965,10 +968,11 @@ stamp-pdf-doxygen: stamp-latex-doxygen ${doxygen_outdir}/pdf $(STAMP) stamp-pdf-doxygen stamp-man-doxygen: ${doxygen_outdir}/man - @builddir=`cd ..; ${PWD_COMMAND}`; \ + -srcdir=`cd ${top_srcdir}; ${PWD_COMMAND}`; \ + builddir=`cd ..; ${PWD_COMMAND}`; \ ${SHELL} ${doxygen_script} \ --host_alias=${host_alias} --mode=man \ - "${top_srcdir}" "$${builddir}" YES || true + "$${srcdir}" "$${builddir}" YES $(STAMP) stamp-man-doxygen doc-xml-doxygen: stamp-xml-doxygen diff --git a/libstdc++-v3/include/bits/mofunc_impl.h b/libstdc++-v3/include/bits/mofunc_impl.h index 543c6f5..968d235 100644 --- a/libstdc++-v3/include/bits/mofunc_impl.h +++ b/libstdc++-v3/include/bits/mofunc_impl.h @@ -108,7 +108,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION move_only_function(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args) noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>()) - : _Mofunc_base(nullptr), _M_invoke(&_S_invoke<_Tp>) + : _M_invoke(&_S_invoke<_Tp>) { static_assert(is_same_v<decay_t<_Tp>, _Tp>); _M_init<_Tp>(__il, std::forward<_Args>(__args)...); diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 01d0c35..43b0b9f 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -614,12 +614,31 @@ namespace ranges template<sized_range _Range> using range_size_t = decltype(ranges::size(std::declval<_Range&>())); + template<typename _Derived> + requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> + class view_interface; // defined in <bits/ranges_util.h> + + namespace __detail + { + template<typename _Tp, typename _Up> + requires (!same_as<_Tp, view_interface<_Up>>) + void __is_derived_from_view_interface_fn(const _Tp&, + const view_interface<_Up>&); // not defined + + // Returns true iff _Tp has exactly one public base class that's a + // specialization of view_interface. + template<typename _Tp> + concept __is_derived_from_view_interface + = requires (_Tp __t) { __is_derived_from_view_interface_fn(__t, __t); }; + } + /// [range.view] The ranges::view_base type. struct view_base { }; /// [range.view] The ranges::enable_view boolean. template<typename _Tp> - inline constexpr bool enable_view = derived_from<_Tp, view_base>; + inline constexpr bool enable_view = derived_from<_Tp, view_base> + || __detail::__is_derived_from_view_interface<_Tp>; /// [range.view] The ranges::view concept. template<typename _Tp> @@ -669,7 +688,8 @@ namespace ranges /// A range which can be safely converted to a view. template<typename _Tp> concept viewable_range = range<_Tp> - && (borrowed_range<_Tp> || view<remove_cvref_t<_Tp>>); + && ((view<remove_cvref_t<_Tp>> && constructible_from<remove_cvref_t<_Tp>, _Tp>) + || (!view<remove_cvref_t<_Tp>> && borrowed_range<_Tp>)); // [range.iter.ops] range iterator operations diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index 7e7b958..a52b8fc 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -61,7 +61,7 @@ namespace ranges /// The ranges::view_interface class template template<typename _Derived> requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> - class view_interface : public view_base + class view_interface { private: constexpr _Derived& _M_derived() noexcept @@ -184,11 +184,16 @@ namespace ranges namespace __detail { - template<class _From, class _To> + template<typename _From, typename _To> + concept __uses_nonqualification_pointer_conversion + = is_pointer_v<_From> && is_pointer_v<_To> + && !convertible_to<remove_pointer_t<_From>(*)[], + remove_pointer_t<_To>(*)[]>; + + template<typename _From, typename _To> concept __convertible_to_non_slicing = convertible_to<_From, _To> - && !(is_pointer_v<decay_t<_From>> && is_pointer_v<decay_t<_To>> - && __different_from<remove_pointer_t<decay_t<_From>>, - remove_pointer_t<decay_t<_To>>>); + && !__uses_nonqualification_pointer_conversion<decay_t<_From>, + decay_t<_To>>; template<typename _Tp> concept __pair_like diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 8afd675..0090b2d 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1821,13 +1821,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { iter_value_t<_It> _M_keep; + constexpr __arrow_proxy(iter_reference_t<_It>&& __x) : _M_keep(std::move(__x)) { } friend class common_iterator; public: - const iter_value_t<_It>* + constexpr const iter_value_t<_It>* operator->() const noexcept { return std::__addressof(_M_keep); } }; @@ -1836,13 +1837,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { iter_value_t<_It> _M_keep; + constexpr __postfix_proxy(iter_reference_t<_It>&& __x) : _M_keep(std::forward<iter_reference_t<_It>>(__x)) { } friend class common_iterator; public: - const iter_value_t<_It>& + constexpr const iter_value_t<_It>& operator*() const noexcept { return _M_keep; } }; diff --git a/libstdc++-v3/include/bits/stl_stack.h b/libstdc++-v3/include/bits/stl_stack.h index 429743f..76b2e24 100644 --- a/libstdc++-v3/include/bits/stl_stack.h +++ b/libstdc++-v3/include/bits/stl_stack.h @@ -322,7 +322,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION -> stack<typename _Container::value_type, _Container>; #ifdef __cpp_lib_adaptor_iterator_pair_constructor - template<typename _InputIterator, typename _Allocator, + template<typename _InputIterator, typename _ValT = typename iterator_traits<_InputIterator>::value_type, typename = _RequireInputIter<_InputIterator>> diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index b69268b..783d7ca 100644 --- a/libstdc++-v3/include/std/optional +++ b/libstdc++-v3/include/std/optional @@ -1,6 +1,7 @@ // <optional> -*- C++ -*- // Copyright (C) 2013-2021 Free Software Foundation, Inc. +// Copyright The GNU Toolchain Authors. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -44,6 +45,10 @@ #include <bits/utility.h> // in_place_t #if __cplusplus > 201703L # include <compare> +# include <bits/invoke.h> // std::__invoke +#endif +#if __cplusplus > 202002L +# include <concepts> #endif namespace std _GLIBCXX_VISIBILITY(default) @@ -81,6 +86,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Tag to disengage optional objects. inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; + template<typename _Fn> struct _Optional_func { _Fn& _M_f; }; + /** * @brief Exception class thrown when a disengaged optional object is * dereferenced. @@ -211,6 +218,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_value(__il, std::forward<_Args>(__args)...) { } +#if __cplusplus >= 202002L + template<typename _Fn, typename _Arg> + constexpr + _Storage(_Optional_func<_Fn> __f, _Arg&& __arg) + : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f), + std::forward<_Arg>(__arg))) + { } +#endif + _Empty_byte _M_empty; _Up _M_value; }; @@ -232,6 +248,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_value(__il, std::forward<_Args>(__args)...) { } +#if __cplusplus >= 202002L + template<typename _Fn, typename _Arg> + constexpr + _Storage(_Optional_func<_Fn> __f, _Arg&& __arg) + : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f), + std::forward<_Arg>(__arg))) + { } +#endif + // User-provided destructor is needed when _Up has non-trivial dtor. _GLIBCXX20_CONSTEXPR ~_Storage() { } @@ -260,6 +285,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_payload._M_value.~_Stored_type(); } +#if __cplusplus >= 202002L + template<typename _Fn, typename _Up> + constexpr void + _M_apply(_Optional_func<_Fn> __f, _Up&& __x) + { + std::construct_at(std::__addressof(this->_M_payload), + __f, std::forward<_Up>(__x)); + _M_engaged = true; + } +#endif + // The _M_get() operations have _M_engaged as a precondition. // They exist to access the contained value with the appropriate // const-qualification, because _M_payload has had the const removed. @@ -637,6 +673,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> class optional; + template<typename _Tp> + inline constexpr bool __is_optional_v = false; + template<typename _Tp> + inline constexpr bool __is_optional_v<optional<_Tp>> = true; + template<typename _Tp, typename _Up> using __converts_from_optional = __or_<is_constructible<_Tp, const optional<_Up>&>, @@ -1002,7 +1043,143 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return static_cast<_Tp>(std::forward<_Up>(__u)); } +#if __cplusplus > 202002L && __cpp_lib_concepts +#define __cpp_lib_monadic_optional 202110L + + // [optional.monadic] + + template<typename _Fn> + constexpr auto + and_then(_Fn&& __f) & + { + using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp&>>; + static_assert(__is_optional_v<remove_cvref_t<_Up>>); + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), **this); + else + return _Up(); + } + + template<typename _Fn> + constexpr auto + and_then(_Fn&& __f) const & + { + using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp&>>; + static_assert(__is_optional_v<_Up>); + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), **this); + else + return _Up(); + } + + template<typename _Fn> + constexpr auto + and_then(_Fn&& __f) && + { + using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp>>; + static_assert(__is_optional_v<remove_cvref_t<_Up>>); + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), std::move(**this)); + else + return _Up(); + } + + template<typename _Fn> + constexpr auto + and_then(_Fn&& __f) const && + { + using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp>>; + static_assert(__is_optional_v<remove_cvref_t<_Up>>); + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), std::move(**this)); + else + return _Up(); + } + + template<typename _Fn> + constexpr auto + transform(_Fn&& __f) & + { + using _Up = invoke_result_t<_Fn, _Tp&>; + if (has_value()) + return optional<_Up>(_Optional_func<_Fn>{__f}, **this); + else + return optional<_Up>(); + } + + template<typename _Fn> + constexpr auto + transform(_Fn&& __f) const & + { + using _Up = invoke_result_t<_Fn, const _Tp&>; + if (has_value()) + return optional<_Up>(_Optional_func<_Fn>{__f}, **this); + else + return optional<_Up>(); + } + + template<typename _Fn> + constexpr auto + transform(_Fn&& __f) && + { + using _Up = invoke_result_t<_Fn, _Tp>; + if (has_value()) + return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(**this)); + else + return optional<_Up>(); + } + + template<typename _Fn> + constexpr auto + transform(_Fn&& __f) const && + { + using _Up = invoke_result_t<_Fn, const _Tp>; + if (has_value()) + return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(**this)); + else + return optional<_Up>(); + } + + template<typename _Fn> requires invocable<_Fn> && copy_constructible<_Tp> + constexpr optional + or_else(_Fn&& __f) const& + { + using _Up = invoke_result_t<_Fn>; + static_assert( is_same_v<remove_cvref_t<_Up>, optional> ); + + if (has_value()) + return *this; + else + return std::forward<_Fn>(__f)(); + } + + template<typename _Fn> requires invocable<_Fn> && move_constructible<_Tp> + constexpr optional + or_else(_Fn&& __f) && + { + using _Up = invoke_result_t<_Fn>; + static_assert( is_same_v<remove_cvref_t<_Up>, optional> ); + + if (has_value()) + return std::move(*this); + else + return std::forward<_Fn>(__f)(); + } +#endif + _GLIBCXX20_CONSTEXPR void reset() noexcept { this->_M_reset(); } + + private: +#if __cplusplus >= 202002L + template<typename _Up> friend class optional; + + template<typename _Fn, typename _Value> + explicit constexpr + optional(_Optional_func<_Fn> __f, _Value&& __v) + { + this->_M_payload._M_apply(__f, std::forward<_Value>(__v)); + } +#endif }; template<typename _Tp> @@ -1241,11 +1418,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !__rhs || __lhs >= *__rhs; } #ifdef __cpp_lib_three_way_comparison - template<typename _Tp> - inline constexpr bool __is_optional_v = false; - template<typename _Tp> - inline constexpr bool __is_optional_v<optional<_Tp>> = true; - template<typename _Tp, typename _Up> requires (!__is_optional_v<_Up>) && three_way_comparable_with<_Tp, _Up> diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index b8de400..30ba060 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -497,7 +497,10 @@ namespace ranges friend constexpr _Iterator operator+(_Iterator __i, difference_type __n) requires __detail::__advanceable<_Winc> - { return __i += __n; } + { + __i += __n; + return __i; + } friend constexpr _Iterator operator+(difference_type __n, _Iterator __i) @@ -507,7 +510,10 @@ namespace ranges friend constexpr _Iterator operator-(_Iterator __i, difference_type __n) requires __detail::__advanceable<_Winc> - { return __i -= __n; } + { + __i -= __n; + return __i; + } friend constexpr difference_type operator-(const _Iterator& __x, const _Iterator& __y) @@ -532,6 +538,7 @@ namespace ranges private: _Winc _M_value = _Winc(); + friend iota_view; friend _Sentinel; }; @@ -568,6 +575,8 @@ namespace ranges operator-(const _Sentinel& __x, const _Iterator& __y) requires sized_sentinel_for<_Bound, _Winc> { return __x._M_distance_from(__y); } + + friend iota_view; }; _Winc _M_value = _Winc(); @@ -590,6 +599,24 @@ namespace ranges __glibcxx_assert( bool(__value <= __bound) ); } + constexpr + iota_view(_Iterator __first, _Iterator __last) + requires same_as<_Winc, _Bound> + : iota_view(__first._M_value, __last._M_value) + { } + + constexpr + iota_view(_Iterator __first, unreachable_sentinel_t __last) + requires same_as<_Bound, unreachable_sentinel_t> + : iota_view(__first._M_value, __last) + { } + + constexpr + iota_view(_Iterator __first, _Sentinel __last) + requires (!same_as<_Winc, _Bound>) && (!same_as<_Bound, unreachable_sentinel_t>) + : iota_view(__first._M_value, __last._M_bound) + { } + constexpr _Iterator begin() const { return _Iterator{_M_value}; } @@ -705,7 +732,7 @@ namespace views private: basic_istream<_CharT, _Traits>* _M_stream; - _Val _M_object; + _Val _M_object = _Val(); struct _Iterator { @@ -1160,33 +1187,9 @@ namespace views::__adaptor }; template<typename _Tp> - struct __cached - { - struct _Deref_t { }; - static constexpr _Deref_t __deref{}; - - // Initialize _M_t directly from the result of dereferencing __i. - // This avoids any unwanted temporary materialization that would - // occur if *__i was bound to a reference before initializing _M_t. - template<typename _Iter> - constexpr explicit - __cached(_Deref_t, _Iter&& __i) - : _M_t(*__i) - { } - - template<typename... _Args> - constexpr explicit - __cached(_Args&&... __args) - : _M_t(std::forward<_Args>(__args)...) - { } - - _Tp _M_t; - }; - - template<typename _Tp> requires is_object_v<_Tp> struct __non_propagating_cache<_Tp> - : protected _Optional_base<__cached<_Tp>> + : protected _Optional_base<_Tp> { __non_propagating_cache() = default; @@ -1218,9 +1221,7 @@ namespace views::__adaptor operator=(_Tp __val) { this->_M_reset(); - std::construct_at(std::__addressof(this->_M_payload._M_payload), - std::in_place, std::move(__val)); - this->_M_payload._M_engaged = true; + this->_M_payload._M_construct(std::move(__val)); return *this; } @@ -1230,22 +1231,20 @@ namespace views::__adaptor constexpr _Tp& operator*() noexcept - { return this->_M_get()._M_t; } + { return this->_M_get(); } constexpr const _Tp& operator*() const noexcept - { return this->_M_get()._M_t; } + { return this->_M_get(); } template<typename _Iter> constexpr _Tp& _M_emplace_deref(const _Iter& __i) { this->_M_reset(); - // Use the special constructor of __cached<_Tp> that does *__i. - std::construct_at(std::__addressof(this->_M_payload._M_payload), - std::in_place, __cached<_Tp>::__deref, __i); - this->_M_payload._M_engaged = true; - return **this; + auto __f = [] (auto& __x) { return *__x; }; + this->_M_payload._M_apply(_Optional_func{__f}, __i); + return this->_M_get(); } }; @@ -1511,9 +1510,9 @@ namespace views::__adaptor { return __y.__equal(__x); } }; + _Vp _M_base = _Vp(); [[no_unique_address]] __detail::__box<_Pred> _M_pred; [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; - _Vp _M_base = _Vp(); public: filter_view() requires (default_initializable<_Vp> @@ -1522,7 +1521,7 @@ namespace views::__adaptor constexpr filter_view(_Vp __base, _Pred __pred) - : _M_pred(std::move(__pred)), _M_base(std::move(__base)) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) { } constexpr _Vp @@ -1878,8 +1877,8 @@ namespace views::__adaptor friend _Sentinel<!_Const>; }; - [[no_unique_address]] __detail::__box<_Fp> _M_fun; _Vp _M_base = _Vp(); + [[no_unique_address]] __detail::__box<_Fp> _M_fun; public: transform_view() requires (default_initializable<_Vp> @@ -1888,7 +1887,7 @@ namespace views::__adaptor constexpr transform_view(_Vp __base, _Fp __fun) - : _M_fun(std::move(__fun)), _M_base(std::move(__base)) + : _M_base(std::move(__base)), _M_fun(std::move(__fun)) { } constexpr _Vp @@ -2015,15 +2014,15 @@ namespace views::__adaptor friend _Sentinel<!_Const>; }; - range_difference_t<_Vp> _M_count = 0; _Vp _M_base = _Vp(); + range_difference_t<_Vp> _M_count = 0; public: take_view() requires default_initializable<_Vp> = default; constexpr take_view(_Vp base, range_difference_t<_Vp> __count) - : _M_count(std::move(__count)), _M_base(std::move(base)) + : _M_base(std::move(base)), _M_count(std::move(__count)) { } constexpr _Vp @@ -2199,8 +2198,8 @@ namespace views::__adaptor friend _Sentinel<!_Const>; }; - [[no_unique_address]] __detail::__box<_Pred> _M_pred; _Vp _M_base = _Vp(); + [[no_unique_address]] __detail::__box<_Pred> _M_pred; public: take_while_view() requires (default_initializable<_Vp> @@ -2209,7 +2208,7 @@ namespace views::__adaptor constexpr take_while_view(_Vp base, _Pred __pred) - : _M_pred(std::move(__pred)), _M_base(std::move(base)) + : _M_base(std::move(base)), _M_pred(std::move(__pred)) { } constexpr _Vp @@ -2280,8 +2279,8 @@ namespace views::__adaptor class drop_view : public view_interface<drop_view<_Vp>> { private: - range_difference_t<_Vp> _M_count = 0; _Vp _M_base = _Vp(); + range_difference_t<_Vp> _M_count = 0; // ranges::next(begin(base), count, end(base)) is O(1) if _Vp satisfies // both random_access_range and sized_range. Otherwise, cache its result. @@ -2297,7 +2296,7 @@ namespace views::__adaptor constexpr drop_view(_Vp __base, range_difference_t<_Vp> __count) - : _M_count(__count), _M_base(std::move(__base)) + : _M_base(std::move(__base)), _M_count(__count) { __glibcxx_assert(__count >= 0); } constexpr _Vp @@ -2404,9 +2403,9 @@ namespace views::__adaptor class drop_while_view : public view_interface<drop_while_view<_Vp, _Pred>> { private: + _Vp _M_base = _Vp(); [[no_unique_address]] __detail::__box<_Pred> _M_pred; [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; - _Vp _M_base = _Vp(); public: drop_while_view() requires (default_initializable<_Vp> @@ -2415,7 +2414,7 @@ namespace views::__adaptor constexpr drop_while_view(_Vp __base, _Pred __pred) - : _M_pred(std::move(__pred)), _M_base(std::move(__base)) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) { } constexpr _Vp @@ -2524,7 +2523,8 @@ namespace views::__adaptor using _OuterCat = typename iterator_traits<_Outer_iter>::iterator_category; using _InnerCat = typename iterator_traits<_Inner_iter>::iterator_category; if constexpr (derived_from<_OuterCat, bidirectional_iterator_tag> - && derived_from<_InnerCat, bidirectional_iterator_tag>) + && derived_from<_InnerCat, bidirectional_iterator_tag> + && common_range<range_reference_t<_Base<_Const>>>) return bidirectional_iterator_tag{}; else if constexpr (derived_from<_OuterCat, forward_iterator_tag> && derived_from<_InnerCat, forward_iterator_tag>) @@ -2576,7 +2576,8 @@ namespace views::__adaptor { if constexpr (_S_ref_is_glvalue && bidirectional_range<_Base> - && bidirectional_range<range_reference_t<_Base>>) + && bidirectional_range<range_reference_t<_Base>> + && common_range<range_reference_t<_Base>>) return bidirectional_iterator_tag{}; else if constexpr (_S_ref_is_glvalue && forward_range<_Base> @@ -2751,9 +2752,9 @@ namespace views::__adaptor friend _Sentinel<!_Const>; }; + _Vp _M_base = _Vp(); [[no_unique_address]] __detail::__non_propagating_cache<remove_cv_t<_InnerRange>> _M_inner; - _Vp _M_base = _Vp(); public: join_view() requires default_initializable<_Vp> = default; @@ -3136,7 +3137,7 @@ namespace views::__adaptor { return _M_i_current(); } constexpr iterator_t<_Base> - base() && + base() && requires forward_range<_Vp> { return std::move(_M_i_current()); } constexpr decltype(auto) @@ -3189,12 +3190,12 @@ namespace views::__adaptor { ranges::iter_swap(__x._M_i_current(), __y._M_i_current()); } }; + _Vp _M_base = _Vp(); _Pattern _M_pattern = _Pattern(); // XXX: _M_current is "present only if !forward_range<V>" [[no_unique_address]] __detail::__maybe_present_t<!forward_range<_Vp>, __detail::__non_propagating_cache<iterator_t<_Vp>>> _M_current; - _Vp _M_base = _Vp(); public: @@ -3204,7 +3205,7 @@ namespace views::__adaptor constexpr lazy_split_view(_Vp __base, _Pattern __pattern) - : _M_pattern(std::move(__pattern)), _M_base(std::move(__base)) + : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) { } template<input_range _Range> @@ -3212,8 +3213,8 @@ namespace views::__adaptor && constructible_from<_Pattern, single_view<range_value_t<_Range>>> constexpr lazy_split_view(_Range&& __r, range_value_t<_Range> __e) - : _M_pattern(views::single(std::move(__e))), - _M_base(views::all(std::forward<_Range>(__r))) + : _M_base(views::all(std::forward<_Range>(__r))), + _M_pattern(views::single(std::move(__e))) { } constexpr _Vp @@ -3228,8 +3229,11 @@ namespace views::__adaptor begin() { if constexpr (forward_range<_Vp>) - return _OuterIter<__detail::__simple_view<_Vp>>{ - this, ranges::begin(_M_base)}; + { + constexpr bool __simple + = __detail::__simple_view<_Vp> && __detail::__simple_view<_Pattern>; + return _OuterIter<__simple>{this, ranges::begin(_M_base)}; + } else { _M_current = ranges::begin(_M_base); @@ -3246,8 +3250,9 @@ namespace views::__adaptor constexpr auto end() requires forward_range<_Vp> && common_range<_Vp> { - return _OuterIter<__detail::__simple_view<_Vp>>{ - this, ranges::end(_M_base)}; + constexpr bool __simple + = __detail::__simple_view<_Vp> && __detail::__simple_view<_Pattern>; + return _OuterIter<__simple>{this, ranges::end(_M_base)}; } constexpr auto @@ -3311,9 +3316,9 @@ namespace views::__adaptor class split_view : public view_interface<split_view<_Vp, _Pattern>> { private: + _Vp _M_base = _Vp(); _Pattern _M_pattern = _Pattern(); __detail::__non_propagating_cache<subrange<iterator_t<_Vp>>> _M_cached_begin; - _Vp _M_base = _Vp(); struct _Iterator; struct _Sentinel; @@ -3325,8 +3330,7 @@ namespace views::__adaptor constexpr split_view(_Vp __base, _Pattern __pattern) - : _M_pattern(std::move(__pattern)), - _M_base(std::move(__base)) + : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) { } template<forward_range _Range> @@ -3334,12 +3338,12 @@ namespace views::__adaptor && constructible_from<_Pattern, single_view<range_value_t<_Range>>> constexpr split_view(_Range&& __r, range_value_t<_Range> __e) - : _M_pattern(views::single(std::move(__e))), - _M_base(views::all(std::forward<_Range>(__r))) + : _M_base(views::all(std::forward<_Range>(__r))), + _M_pattern(views::single(std::move(__e))) { } constexpr _Vp - base() const& requires copyable<_Vp> + base() const& requires copy_constructible<_Vp> { return _M_base; } constexpr _Vp @@ -3658,11 +3662,11 @@ namespace views::__adaptor && sized_sentinel_for<sentinel_t<_Vp>, iterator_t<_Vp>>); + _Vp _M_base = _Vp(); [[no_unique_address]] __detail::__maybe_present_t<_S_needs_cached_begin, __detail::_CachedPosition<_Vp>> _M_cached_begin; - _Vp _M_base = _Vp(); public: reverse_view() requires default_initializable<_Vp> = default; diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index d18365f..3da7dad 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -293,8 +293,10 @@ namespace __variant constexpr _Type&& _M_get() && noexcept { return std::move(_M_storage); } + struct _Empty_byte { }; + union { - char _M_nope; + _Empty_byte _M_empty; _Type _M_storage; }; #else diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index 2b11830..0a7b28a 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -292,6 +292,9 @@ #define __cpp_lib_adaptor_iterator_pair_constructor 202106L #define __cpp_lib_invoke_r 202106L #define __cpp_lib_is_scoped_enum 202011L +#if __cpp_lib_concepts +# define __cpp_lib_monadic_optional 202110L +#endif #define __cpp_lib_move_only_function 202110L #define __cpp_lib_string_contains 202011L #if _GLIBCXX_USE_CXX11_ABI // Only supported with cxx11-abi diff --git a/libstdc++-v3/src/c++11/random.cc b/libstdc++-v3/src/c++11/random.cc index 44b9f30..4b64bde 100644 --- a/libstdc++-v3/src/c++11/random.cc +++ b/libstdc++-v3/src/c++11/random.cc @@ -192,6 +192,51 @@ namespace std _GLIBCXX_VISIBILITY(default) return lcg(); } #endif + + enum Which { + rand_s = 1, rdseed = 2, rdrand = 4, device_file = 8, prng = 16, + any = 0xffff + }; + + inline Which + which_source(random_device::result_type (*func [[maybe_unused]])(void*), + void* file [[maybe_unused]]) + { +#ifdef _GLIBCXX_USE_CRT_RAND_S + if (func == &__winxp_rand_s) + return rand_s; +#endif + +#ifdef USE_RDSEED +#ifdef USE_RDRAND + if (func == &__x86_rdseed_rdrand) + return rdseed; +#endif + if (func == &__x86_rdseed) + return rdseed; +#endif + +#ifdef USE_RDRAND + if (func == &__x86_rdrand) + return rdrand; +#endif + +#ifdef _GLIBCXX_USE_DEV_RANDOM + if (file != nullptr) + return device_file; +#endif + +#ifdef USE_LCG + if (func == &__lcg) + return prng; +#endif + +#ifdef USE_MT19937 + return prng; +#endif + + return any; // should be unreachable + } } void @@ -209,10 +254,7 @@ namespace std _GLIBCXX_VISIBILITY(default) const char* fname [[gnu::unused]] = nullptr; - enum { - rand_s = 1, rdseed = 2, rdrand = 4, device_file = 8, prng = 16, - any = 0xffff - } which; + Which which; if (token == "default") { @@ -449,10 +491,25 @@ namespace std _GLIBCXX_VISIBILITY(default) double random_device::_M_getentropy() const noexcept { + const int max = sizeof(result_type) * __CHAR_BIT__; + + switch(which_source(_M_func, _M_file)) + { + case rdrand: + case rdseed: + return (double) max; + case rand_s: + case prng: + return 0.0; + case device_file: + // handled below + break; + default: + return 0.0; + } + #if defined _GLIBCXX_USE_DEV_RANDOM \ && defined _GLIBCXX_HAVE_SYS_IOCTL_H && defined RNDGETENTCNT - if (!_M_file) - return 0.0; #ifdef USE_POSIX_FILE_IO const int fd = _M_fd; @@ -469,7 +526,6 @@ namespace std _GLIBCXX_VISIBILITY(default) if (ent < 0) return 0.0; - const int max = sizeof(result_type) * __CHAR_BIT__; if (ent > max) ent = max; diff --git a/libstdc++-v3/testsuite/20_util/move_only_function/cons.cc b/libstdc++-v3/testsuite/20_util/move_only_function/cons.cc index 0992f10..d8a0a4a 100644 --- a/libstdc++-v3/testsuite/20_util/move_only_function/cons.cc +++ b/libstdc++-v3/testsuite/20_util/move_only_function/cons.cc @@ -96,3 +96,30 @@ static_assert( ! is_nothrow_constructible_v<move_only_function<void() noexcept>, in_place_type_t<H>, int> ); static_assert( is_nothrow_constructible_v<move_only_function<void() noexcept>, in_place_type_t<H>, int, int> ); + +struct I { + I(int, const char*); + I(std::initializer_list<char>); + int operator()() const noexcept; +}; + +static_assert( is_constructible_v<move_only_function<void()>, + std::in_place_type_t<I>, + int, const char*> ); +static_assert( is_constructible_v<move_only_function<void()>, + std::in_place_type_t<I>, + std::initializer_list<char>> ); + +void +test_instantiation() +{ + // Instantiate the constructor bodies + move_only_function<void()> f0; + move_only_function<void()> f1(nullptr); + move_only_function<void()> f2( I(1, "two") ); + move_only_function<void()> f3(std::in_place_type<I>, 3, "four"); + move_only_function<void()> f4(std::in_place_type<I>, // PR libstdc++/102825 + { 'P', 'R', '1', '0', '2', '8', '2', '5'}); + auto f5 = std::move(f4); + f4 = std::move(f5); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/monadic/and_then.cc b/libstdc++-v3/testsuite/20_util/optional/monadic/and_then.cc new file mode 100644 index 0000000..f69ab95 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/monadic/and_then.cc @@ -0,0 +1,132 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include <optional> + +#ifndef __cpp_lib_monadic_optional +# error "Feature test macro for monadic optional is missing in <optional>" +#elif __cpp_lib_monadic_optional < 202110L +# error "Feature test macro for monadic optional has wrong value in <optional>" +#endif + +#include <testsuite_hooks.h> + +constexpr bool +test_and_then() +{ + std::optional<int> o; + auto r = o.and_then([](int) -> std::optional<short> { throw 1; }); + VERIFY( !r.has_value() ); + static_assert( std::is_same_v<decltype(r), std::optional<short>> ); + + o = 111; + r = o.and_then([](int i) -> std::optional<short> { return {i/10}; }); + VERIFY( *r == 11 ); + + return true; +} + +static_assert( test_and_then() ); + +enum { CalledLvalue = 1, CalledConst = 2, PassedLvalue = 4, PassedConst = 8 }; + +struct F +{ + template<typename This, typename Value> + static constexpr std::optional<int> + called_as() + { + int res = 0; + if constexpr (std::is_lvalue_reference_v<This>) + res |= CalledLvalue; + if constexpr (std::is_const_v<std::remove_reference_t<This>>) + res |= CalledConst; + + if constexpr (std::is_lvalue_reference_v<Value>) + res |= PassedLvalue; + if constexpr (std::is_const_v<std::remove_reference_t<Value>>) + res |= PassedConst; + + return {res}; + } + + template<typename T> + constexpr std::optional<int> + operator()(T&&) & + { return called_as<F&, T>(); } + + template<typename T> + constexpr std::optional<int> + operator()(T&&) const & + { return called_as<const F&, T>(); } + + template<typename T> + constexpr std::optional<int> + operator()(T&&) && + { return called_as<F, T>(); } + + template<typename T> + constexpr std::optional<int> + operator()(T&&) const && + { return called_as<const F, T>(); } +}; + +constexpr bool +test_forwarding() +{ + std::optional<long> o = 1; + F f; + + VERIFY( *o.and_then(f) == (PassedLvalue|CalledLvalue) ); + VERIFY( *o.and_then(std::move(f)) == PassedLvalue ); + VERIFY( *std::move(o).and_then(f) == CalledLvalue ); + VERIFY( *std::move(o).and_then(std::move(f)) == 0 ); + + const auto& co = o; + + VERIFY( *co.and_then(f) == (PassedLvalue|PassedConst|CalledLvalue) ); + VERIFY( *co.and_then(std::move(f)) == (PassedLvalue|PassedConst) ); + VERIFY( *std::move(co).and_then(f) == (PassedConst|CalledLvalue) ); + VERIFY( *std::move(co).and_then(std::move(f)) == PassedConst ); + + const auto& cf = f; + + VERIFY( *o.and_then(cf) == (PassedLvalue|CalledLvalue|CalledConst) ); + VERIFY( *o.and_then(std::move(cf)) == (PassedLvalue|CalledConst) ); + VERIFY( *std::move(o).and_then(cf) == (CalledLvalue|CalledConst) ); + VERIFY( *std::move(o).and_then(std::move(cf)) == CalledConst ); + + VERIFY( *co.and_then(cf) == (PassedLvalue|PassedConst|CalledLvalue|CalledConst) ); + VERIFY( *co.and_then(std::move(cf)) == (PassedLvalue|PassedConst|CalledConst) ); + VERIFY( *std::move(co).and_then(cf) == (PassedConst|CalledLvalue|CalledConst) ); + VERIFY( *std::move(co).and_then(std::move(cf)) == (PassedConst|CalledConst) ); + + o = std::nullopt; + + VERIFY( ! o.and_then(f).has_value() ); + VERIFY( ! co.and_then(f).has_value() ); + VERIFY( ! std::move(o).and_then(f).has_value() ); + VERIFY( ! std::move(co).and_then(f).has_value() ); + + return true; +} + +static_assert( test_forwarding() ); + +void f(int&) { } + +void +test_unconstrained() +{ + // PR libstc++/102863 - Optional monadic ops should not be constrained + std::optional<int> x; + auto answer = x.and_then([](auto& y) { f(y); return std::optional<int>{42}; }); + VERIFY( !answer ); +} + +int main() +{ + test_and_then(); + test_forwarding(); + test_unconstrained(); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/monadic/or_else.cc b/libstdc++-v3/testsuite/20_util/optional/monadic/or_else.cc new file mode 100644 index 0000000..0508104 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/monadic/or_else.cc @@ -0,0 +1,103 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include <optional> +#include <testsuite_hooks.h> + +constexpr bool +test_or_else() +{ + std::optional<int> o; + auto&& r = o.or_else([]() -> std::optional<int> { return {303}; }); + VERIFY( !o ); + VERIFY( *r == 303 ); + static_assert( std::is_same_v<decltype(r), std::optional<int>&&> ); + + o = 808; + const std::optional<int> tr = 909; + auto&& r2 = o.or_else([&]() -> const auto& { return tr; }); + static_assert( std::is_same_v<decltype(r2), std::optional<int>&&> ); + VERIFY( r2 == o ); + + return true; +} + +static_assert( test_or_else() ); + +constexpr bool +test_move() +{ + struct X + { + constexpr X() { } + constexpr X(const X&) { copied = true; } + constexpr X(X&& x) { moved = true; x.gone = true; } + + bool copied = false; + bool moved = false; + bool gone = false; + }; + + std::optional<X> o(std::in_place); + + auto f = []{ return std::optional<X>{}; }; + VERIFY( o.or_else(f)->copied ); + VERIFY( ! o->gone ); + + VERIFY( std::move(o).or_else(f)->moved ); + VERIFY( o->gone ); + + struct move_only + { + constexpr move_only() { } + constexpr move_only(move_only&&) { } + }; + + std::optional<move_only> mo; + // doesn't require copy + std::move(mo).or_else([] { return std::optional<move_only>{}; }); + + return true; +} + +static_assert( test_move() ); + +constexpr bool +test_call() +{ + struct F + { + constexpr std::optional<int> operator()() & { return {1}; } + constexpr std::optional<int> operator()() && { return {2}; } + constexpr std::optional<int> operator()() const & { return {3}; }; + constexpr std::optional<int> operator()() const && { return {4}; } + }; + + std::optional<int> o; + F f; + + VERIFY( *o.or_else(f) == 1 ); + VERIFY( *std::move(o).or_else(f) == 1 ); + + VERIFY( *o.or_else(std::move(f)) == 2 ); + VERIFY( *std::move(o).or_else(std::move(f)) == 2 ); + + const F& cf = f; + + VERIFY( *o.or_else(cf) == 3 ); + VERIFY( *std::move(o).or_else(cf) == 3 ); + + VERIFY( *o.or_else(std::move(cf)) == 4 ); + VERIFY( *std::move(o).or_else(std::move(cf)) == 4 ); + + return true; +} + +static_assert( test_call() ); + +int main() +{ + test_or_else(); + test_move(); + test_call(); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc b/libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc new file mode 100644 index 0000000..16e9486 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc @@ -0,0 +1,30 @@ +// { dg-options "-std=gnu++23" } +// { dg-do compile { target c++23 } } + +#include <optional> + +void +test01() +{ + std::optional<int> o; + o.or_else([&] { return o; }); // OK + o.or_else([] { return std::optional<short>(); }); // { dg-error "here" } + o.or_else([] { return 1; }); // { dg-error "here" } + std::move(o).or_else([] { return std::optional<short>(); }); // { dg-error "here" } + std::move(o).or_else([] { return 1; }); // { dg-error "here" } +} + +// { dg-prune-output "static assertion failed" } + +void +test02() +{ + struct move_only + { + move_only() { } + move_only(move_only&&) { } + }; + + std::optional<move_only> mo; + mo.or_else([]{ return std::optional<move_only>{}; }); // { dg-error "no matching function" } +} diff --git a/libstdc++-v3/testsuite/20_util/optional/monadic/transform.cc b/libstdc++-v3/testsuite/20_util/optional/monadic/transform.cc new file mode 100644 index 0000000..356c94d --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/monadic/transform.cc @@ -0,0 +1,152 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include <optional> +#include <testsuite_hooks.h> + +constexpr bool +test_transform() +{ + std::optional<int> o; + auto&& r = o.transform([](int) -> unsigned { throw 1; }); + static_assert( std::is_same_v<decltype(r), std::optional<unsigned>&&> ); + VERIFY( ! r.has_value() ); + + o = 10; + auto&& r2 = o.transform([](int i) -> unsigned { return i + 2u; }); + static_assert( std::is_same_v<decltype(r2), std::optional<unsigned>&&> ); + VERIFY( *r2 == 12u ); + + return true; +} + +static_assert( test_transform() ); + +enum { CalledLvalue = 1, CalledConst = 2, PassedLvalue = 4, PassedConst = 8 }; + +struct F +{ + template<typename This, typename Value> + static constexpr int + called_as() + { + int res = 0; + if constexpr (std::is_lvalue_reference_v<This>) + res |= CalledLvalue; + if constexpr (std::is_const_v<std::remove_reference_t<This>>) + res |= CalledConst; + + if constexpr (std::is_lvalue_reference_v<Value>) + res |= PassedLvalue; + if constexpr (std::is_const_v<std::remove_reference_t<Value>>) + res |= PassedConst; + + return res; + } + + template<typename T> + constexpr int + operator()(T&&) & + { return called_as<F&, T>(); } + + template<typename T> + constexpr int + operator()(T&&) const & + { return called_as<const F&, T>(); } + + template<typename T> + constexpr int + operator()(T&&) && + { return called_as<F, T>(); } + + template<typename T> + constexpr int + operator()(T&&) const && + { return called_as<const F, T>(); } +}; + +constexpr bool +test_forwarding() +{ + std::optional<long> o = 1; + F f; + + VERIFY( *o.transform(f) == (PassedLvalue|CalledLvalue) ); + VERIFY( *o.transform(std::move(f)) == PassedLvalue ); + VERIFY( *std::move(o).transform(f) == CalledLvalue ); + VERIFY( *std::move(o).transform(std::move(f)) == 0 ); + + const auto& co = o; + + VERIFY( *co.transform(f) == (PassedLvalue|PassedConst|CalledLvalue) ); + VERIFY( *co.transform(std::move(f)) == (PassedLvalue|PassedConst) ); + VERIFY( *std::move(co).transform(f) == (PassedConst|CalledLvalue) ); + VERIFY( *std::move(co).transform(std::move(f)) == PassedConst ); + + const auto& cf = f; + + VERIFY( *o.transform(cf) == (PassedLvalue|CalledLvalue|CalledConst) ); + VERIFY( *o.transform(std::move(cf)) == (PassedLvalue|CalledConst) ); + VERIFY( *std::move(o).transform(cf) == (CalledLvalue|CalledConst) ); + VERIFY( *std::move(o).transform(std::move(cf)) == CalledConst ); + + VERIFY( *co.transform(cf) == (PassedLvalue|PassedConst|CalledLvalue|CalledConst) ); + VERIFY( *co.transform(std::move(cf)) == (PassedLvalue|PassedConst|CalledConst) ); + VERIFY( *std::move(co).transform(cf) == (PassedConst|CalledLvalue|CalledConst) ); + VERIFY( *std::move(co).transform(std::move(cf)) == (PassedConst|CalledConst) ); + + o = std::nullopt; + + VERIFY( ! o.transform(f).has_value() ); + VERIFY( ! co.transform(f).has_value() ); + VERIFY( ! std::move(o).transform(f).has_value() ); + VERIFY( ! std::move(co).transform(f).has_value() ); + + return true; +} + +static_assert( test_forwarding() ); + +constexpr bool +test_copy_elision() +{ + struct immovable + { + constexpr immovable(int p) : power_level(p) { } + immovable(immovable&&) = delete; + + int power_level; + }; + + struct Force + { + constexpr immovable operator()(int i) const { return {i+1}; } + }; + + std::optional<int> irresistible(9000); + std::optional<immovable> object = irresistible.transform(Force{}); + VERIFY( object->power_level > 9000 ); + + return true; +} + +static_assert( test_copy_elision() ); + +void f(int&) { } + +void +test_unconstrained() +{ + // PR libstc++/102863 - Optional monadic ops should not be constrained + std::optional<int> x; + auto answer = x.transform([](auto& y) { f(y); return 42; }); + VERIFY( !answer ); +} + +int main() +{ + test_transform(); + test_forwarding(); + test_copy_elision(); + test_unconstrained(); +} diff --git a/libstdc++-v3/testsuite/20_util/optional/monadic/version.cc b/libstdc++-v3/testsuite/20_util/optional/monadic/version.cc new file mode 100644 index 0000000..90b2a90 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/monadic/version.cc @@ -0,0 +1,10 @@ +// { dg-options "-std=gnu++23" } +// { dg-do preprocess { target c++23 } } + +#include <version> + +#ifndef __cpp_lib_monadic_optional +# error "Feature test macro for monadic optional is missing in <version>" +#elif __cpp_lib_monadic_optional < 202110L +# error "Feature test macro for monadic optional has wrong value in <version>" +#endif diff --git a/libstdc++-v3/testsuite/23_containers/stack/deduction.cc b/libstdc++-v3/testsuite/23_containers/stack/deduction.cc index 169a063..dea7ba0 100644 --- a/libstdc++-v3/testsuite/23_containers/stack/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/stack/deduction.cc @@ -87,3 +87,17 @@ test02() std::stack s8(std::move(l), l.get_allocator()); check_type<std::stack<long, std::list<long>>>(s8); } + +#if __cpp_lib_adaptor_iterator_pair_constructor +void +test03() +{ + std::list<long> l; + + std::stack s1(l.begin(), l.end()); + check_type<std::stack<long>>(s1); + + std::stack s2(l.begin(), l.end(), std::allocator<long>()); + check_type<std::stack<long>>(s1); +} +#endif diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc new file mode 100644 index 0000000..9ef1538 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc @@ -0,0 +1,37 @@ +// { dg-do run { target c++11 } } + +#include <random> +#include <testsuite_hooks.h> +#include <testsuite_random.h> + +void +test01() +{ + for (auto token : { "mt19937", "prng", "rand_s" }) + if (__gnu_test::random_device_available(token)) + VERIFY( std::random_device(token).entropy() == 0.0 ); + + using result_type = std::random_device::result_type; + const double max = std::log2(std::numeric_limits<result_type>::max() + 1.0); + + for (auto token : { "/dev/random", "/dev/urandom" }) + if (__gnu_test::random_device_available(token)) + { + const double entropy = std::random_device(token).entropy(); + VERIFY( entropy >= 0.0 ); + VERIFY( entropy <= max ); + } + + for (auto token : { "rdrand", "rdseed" }) + if (__gnu_test::random_device_available(token)) + { + const double entropy = std::random_device(token).entropy(); + VERIFY( entropy == max ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/all.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/all.cc index 9a6a31e..ce1384c 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/all.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/all.cc @@ -159,6 +159,20 @@ test06() static_assert(!noexcept(views::all(BorrowedRange<false, false>(x)))); } +void +test07() +{ + // LWG 3481 + struct view_t : ranges::empty_view<int> { // move-only view + view_t(const view_t&) = delete; + view_t(view_t&&) = default; + view_t& operator=(const view_t&) = delete; + view_t& operator=(view_t&&) = default; + }; + static_assert(std::movable<view_t> && !std::copyable<view_t>); + static_assert(!ranges::viewable_range<view_t&>); +} + int main() { @@ -168,4 +182,5 @@ main() static_assert(test04()); test05(); test06(); + test07(); } diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc index 219e2a6..61524d4 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/sizeof.cc @@ -42,11 +42,11 @@ static_assert(sizeof(ranges::drop_while_view<V, decltype(&pred_f)>) == 4*ptr); static_assert(sizeof(ranges::transform_view<V, decltype(&func_f)>) == 3*ptr); static_assert(sizeof(ranges::filter_view<V, decltype(pred_l)>) == 3*ptr); -static_assert(sizeof(ranges::take_while_view<V, decltype(pred_l)>) == 3*ptr); +static_assert(sizeof(ranges::take_while_view<V, decltype(pred_l)>) == 2*ptr); static_assert(sizeof(ranges::drop_while_view<V, decltype(pred_l)>) == 3*ptr); -static_assert(sizeof(ranges::transform_view<V, decltype(func_l)>) == 3*ptr); +static_assert(sizeof(ranges::transform_view<V, decltype(func_l)>) == 2*ptr); static_assert(sizeof(ranges::lazy_split_view<V, std::string_view>) == 4*ptr); static_assert - (sizeof(ranges::reverse_view<ranges::filter_view<V, decltype(pred_l)>>) == 4*ptr); + (sizeof(ranges::reverse_view<ranges::filter_view<V, decltype(pred_l)>>) == 3*ptr); diff --git a/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc b/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc index 362ef1f..5bebe4b 100644 --- a/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc +++ b/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc @@ -18,6 +18,7 @@ // { dg-options "-std=gnu++2a" } // { dg-do run { target c++2a } } +#include <algorithm> #include <ranges> #include <testsuite_hooks.h> @@ -90,6 +91,25 @@ test05() VERIFY( r.begin() - r.end() == -3 ); } +void +test06() +{ + // Verify LWG 3523 changes. + auto v1 = std::views::iota(0, 5); + auto w1 = decltype(v1)(v1.begin(), v1.end()); + VERIFY( std::ranges::equal(v1, w1) ); + + auto v2 = std::views::iota(0); + auto w2 = decltype(v2)(v2.begin(), v2.end()); + static_assert(std::same_as<decltype(w2.end()), std::unreachable_sentinel_t>); + VERIFY( *w2.begin() == 0 ); + + auto v3 = std::views::iota(0, 5l); + auto w3 = decltype(v3)(v3.begin(), v3.end()); + static_assert(!std::ranges::common_range<decltype(w3)>); + VERIFY( std::ranges::equal(v3, w3) ); +} + int main() { @@ -98,4 +118,5 @@ main() test03(); test04(); test05(); + test06(); } diff --git a/libstdc++-v3/testsuite/std/ranges/subrange/1.cc b/libstdc++-v3/testsuite/std/ranges/subrange/1.cc new file mode 100644 index 0000000..8a53261 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/subrange/1.cc @@ -0,0 +1,19 @@ +// { dg-options "-std=gnu++20" } +// { dg-do run { target c++20 } } + +#include <ranges> + +void +test01() +{ + // LWG 3470 + int a[3] = {1,2,3}; + int* b[3] = {&a[2], &a[0], &a[1]}; + auto c = std::ranges::subrange<const int*const*>(b); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/std/ranges/view.cc b/libstdc++-v3/testsuite/std/ranges/view.cc index dd82582..98a162e 100644 --- a/libstdc++-v3/testsuite/std/ranges/view.cc +++ b/libstdc++-v3/testsuite/std/ranges/view.cc @@ -52,10 +52,7 @@ static_assert(!std::ranges::view<__gnu_test::test_random_access_range<int>>); template<typename T> struct test_view : __gnu_test::test_random_access_range<T>, std::ranges::view_base -{ - // views must be default-initializable: - test_view() : __gnu_test::test_random_access_range<T>(nullptr, nullptr) { } -}; +{ }; static_assert(std::ranges::view<test_view<int>>); @@ -63,3 +60,26 @@ template<> constexpr bool std::ranges::enable_view<test_view<long>> = false; static_assert(!std::ranges::view<test_view<long>>); + +void +test01() +{ + // Verify LWG 3549 changes to ranges::enable_view. + using std::ranges::view_interface; + + struct v1 + : __gnu_test::test_random_access_range<int>, view_interface<v1> { }; + static_assert(!std::derived_from<v1, std::ranges::view_base>); + static_assert(std::ranges::enable_view<v1>); + + struct v2 : v1, view_interface<v2> { }; + static_assert(!std::derived_from<v2, std::ranges::view_base>); + static_assert(!std::ranges::enable_view<v2>); + + struct v3 : __gnu_test::test_random_access_range<int> { }; + static_assert(!std::derived_from<v3, std::ranges::view_base>); + static_assert(!std::ranges::enable_view<v3>); + + struct v4 { }; + static_assert(!std::ranges::enable_view<view_interface<v4>>); +} |