diff --git a/gcc/c-family/c-ada-spec.cc b/gcc/c-family/c-ada-spec.cc index c7ae03223..bcdfb60c3 100644 --- a/gcc/c-family/c-ada-spec.cc +++ b/gcc/c-family/c-ada-spec.cc @@ -1566,6 +1566,21 @@ dump_ada_import (pretty_printer *pp, tree t, int spc) const bool is_stdcall = TREE_CODE (t) == FUNCTION_DECL && lookup_attribute ("stdcall", TYPE_ATTRIBUTES (TREE_TYPE (t))); + bool uses_vector_abi = false; + const bool is_cpp_method + = TREE_CODE (t) == FUNCTION_DECL + && TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE; + + if (TREE_CODE (t) == FUNCTION_DECL) + { + tree function_type = TREE_TYPE (t); + + uses_vector_abi = TREE_CODE (TREE_TYPE (function_type)) == VECTOR_TYPE; + for (tree args = TYPE_ARG_TYPES (function_type); + args && !uses_vector_abi; + args = TREE_CHAIN (args)) + uses_vector_abi = TREE_CODE (TREE_VALUE (args)) == VECTOR_TYPE; + } pp_string (pp, "with Import => True, "); @@ -1573,6 +1588,12 @@ dump_ada_import (pretty_printer *pp, tree t, int spc) if (is_stdcall) pp_string (pp, "Convention => Stdcall, "); + else if (uses_vector_abi && !is_cpp_method) + /* GNAT foreign conventions can pass the representative Ada array by + reference before vector_type changes its machine mode. Free functions + therefore use the Ada convention's native vector mode; C++ methods keep + CPP convention for their implicit object and dispatch-table slot. */ + pp_string (pp, "Convention => Ada, "); else if (name[0] == '_' && name[1] == 'Z') pp_string (pp, "Convention => CPP, "); else @@ -2190,7 +2228,22 @@ dump_ada_node (pretty_printer *pp, tree node, tree type, int spc, break; case VECTOR_TYPE: - pp_string (pp, ""); + if (name_only && TYPE_NAME (node)) + dump_ada_node (pp, TYPE_NAME (node), node, spc, limited_access, true); + else + { + unsigned HOST_WIDE_INT subparts; + if (!TYPE_VECTOR_SUBPARTS (node).is_constant (&subparts)) + pp_string (pp, ""); + else + { + pp_string (pp, "array (0 .. "); + pp_unsigned_wide_integer (pp, subparts - 1); + pp_string (pp, ") of "); + dump_ada_node (pp, TREE_TYPE (node), node, spc, limited_access, + true); + } + } break; case COMPLEX_TYPE: @@ -3050,6 +3099,10 @@ dump_ada_declaration (pretty_printer *pp, tree t, tree type, int spc) pp_string (pp, "type "); break; + case VECTOR_TYPE: + pp_string (pp, "type "); + break; + case FUNCTION_TYPE: pp_string (pp, "-- skipped function type "); dump_ada_node (pp, t, type, spc, false, true); @@ -3381,6 +3434,21 @@ dump_ada_declaration (pretty_printer *pp, tree t, tree type, int spc) { pp_string (pp, "; -- "); dump_sloc (pp, t); + + if (TREE_CODE (t) == TYPE_DECL + && TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE) + { + newline_and_indent (pp, spc); + pp_string (pp, "for "); + dump_ada_node (pp, t, type, spc, false, true); + pp_string (pp, "'Alignment use "); + pp_decimal_int (pp, TYPE_ALIGN (TREE_TYPE (t)) / BITS_PER_UNIT); + pp_semicolon (pp); + newline_and_indent (pp, spc); + pp_string (pp, "pragma Machine_Attribute ("); + dump_ada_node (pp, t, type, spc, false, true); + pp_string (pp, ", \"vector_type\");"); + } } return 1; diff --git a/gcc/testsuite/g++.dg/ada-spec/vector-types.C b/gcc/testsuite/g++.dg/ada-spec/vector-types.C new file mode 100644 index 000000000..445ba88ef --- /dev/null +++ b/gcc/testsuite/g++.dg/ada-spec/vector-types.C @@ -0,0 +1,49 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-ada-spec-slim" } */ +/* { dg-final { scan-file vector_types_c.ads "type Int_Vector is array \(0 .. 3\) of int;" } } */ +/* { dg-final { scan-file vector_types_c.ads "for Int_Vector'Alignment use 16;" } } */ +/* { dg-final { scan-file vector_types_c.ads "pragma Machine_Attribute \(Int_Vector, \"vector_type\"\);" } } */ +/* { dg-final { scan-file vector_types_c.ads "type Double_Vector is array \(0 .. 1\) of double;" } } */ +/* { dg-final { scan-file-times vector_types_c.ads "Convention => Ada" 3 } } */ +/* { dg-final { scan-file vector_types_c.ads "function cpp_transform_vector" } } */ +/* { dg-final { scan-file vector_types_c.ads "function transform" } } */ + +typedef int Int_Vector __attribute__((vector_size(16))); +typedef double Double_Vector __attribute__((vector_size(16))); + +Int_Vector +vector_identity (Int_Vector value) +{ + return value; +} + +Double_Vector +double_vector_identity (Double_Vector value) +{ + return value; +} + +class Vector_Object +{ +public: + virtual ~Vector_Object () = default; + virtual Int_Vector transform (Int_Vector value) { return value; } +}; + +extern "C" Vector_Object *create_vector_object () +{ + return new Vector_Object; +} + +extern "C" void delete_vector_object (Vector_Object *object) +{ + delete object; +} + +extern "C" Int_Vector +cpp_transform_vector (Vector_Object *object, Int_Vector value) +{ + return object->transform (value); +} + +/* { dg-final { cleanup-ada-spec } } */ diff --git a/gcc/testsuite/g++.dg/ada-spec/scalable-vector.C b/gcc/testsuite/g++.dg/ada-spec/scalable-vector.C new file mode 100644 --- /dev/null +++ b/gcc/testsuite/g++.dg/ada-spec/scalable-vector.C @@ -0,0 +1,13 @@ +/* { dg-do compile { target aarch64*-*-linux* } } */ +/* { dg-options "-march=armv8-a+sve -fdump-ada-spec-slim" } */ +/* { dg-final { scan-file scalable_vector_c.ads "" } } */ + +#include + +svint32_t +scalable_identity (svint32_t value) +{ + return value; +} + +/* { dg-final { cleanup-ada-spec } } */