From 93ae3e13bc5ac98acaa9936ae28e5d8442f25cfa Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 11 Feb 2018 23:44:55 +0100 Subject: [PATCH] Add fn spec flags for all library functions. --- gcc/d/ChangeLog | 7 +++ gcc/d/d-tree.h | 2 +- gcc/d/runtime.cc | 17 +++++- gcc/d/runtime.def | 137 +++++++++++++++++++++++++--------------------- 4 files changed, 98 insertions(+), 65 deletions(-) diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index a6dd475b5..63a1a3822 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,10 @@ +2018-02-12 Iain Buclaw + + * runtime.cc (build_libcall_decl): Update signature, handle "fn spec" + attribute. + * runtime.def (DEF_D_RUNTIME): Add fnspec argument. All callers + updated. + 2018-02-11 Iain Buclaw * runtime.def (DYNAMIC_CAST, INTERFACE_CAST): Set ECF_CONST. diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index 1f1252eed..73da5c787 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -453,7 +453,7 @@ extern GTY(()) tree d_global_trees[DTI_MAX]; enum libcall_fn { -#define DEF_D_RUNTIME(CODE, N, T, P, F) LIBCALL_ ## CODE, +#define DEF_D_RUNTIME(CODE, N, T, P, F, S) LIBCALL_ ## CODE, #include "runtime.def" diff --git a/gcc/d/runtime.cc b/gcc/d/runtime.cc index c6d3a6f1a..60c5cdedc 100644 --- a/gcc/d/runtime.cc +++ b/gcc/d/runtime.cc @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "fold-const.h" #include "stringpool.h" +#include "attribs.h" #include "d-tree.h" #include "d-frontend.h" @@ -214,7 +215,7 @@ get_libcall_type (libcall_type type) static tree build_libcall_decl (const char *name, libcall_type return_type, - int flags, int nparams, ...) + int flags, const char *fnspec, int nparams, ...) { tree *args = XALLOCAVEC (tree, nparams); bool varargs = false; @@ -248,6 +249,15 @@ build_libcall_decl (const char *name, libcall_type return_type, else fntype = build_function_type_array (tret, nparams, args); + if (fnspec) + { + tree attr_args = build_tree_list (NULL_TREE, + build_string (strlen (fnspec), fnspec)); + tree attrs = tree_cons (get_identifier ("fn spec"), + attr_args, TYPE_ATTRIBUTES (fntype)); + fntype = build_type_attribute_variant (fntype, attrs); + } + tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, get_identifier (name), fntype); DECL_EXTERNAL (decl) = 1; @@ -276,9 +286,10 @@ get_libcall (libcall_fn libcall) switch (libcall) { -#define DEF_D_RUNTIME(CODE, NAME, TYPE, PARAMS, FLAGS) \ +#define DEF_D_RUNTIME(CODE, NAME, TYPE, PARAMS, FLAGS, FNSPEC) \ case LIBCALL_ ## CODE: \ - libcall_decls[libcall] = build_libcall_decl (NAME, TYPE, FLAGS, PARAMS); \ + libcall_decls[libcall] = build_libcall_decl (NAME, TYPE, FLAGS, FNSPEC, \ + PARAMS); \ break; #include "runtime.def" diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def index ba22ab7dc..596f3c460 100644 --- a/gcc/d/runtime.def +++ b/gcc/d/runtime.def @@ -17,10 +17,11 @@ along with GCC; see the file COPYING3. If not see /* D runtime library functions. */ -/* DEF_D_RUNTIME (CODE, NAME, FLAGS) +/* DEF_D_RUNTIME (CODE, NAME, FLAGS, FNSPEC) CODE The enum code used to refer this function. NAME The name of this function as a string. FLAGS ECF flags to describe attributes of the function. + FNSPEC A string describing the functions fnspec. Used for declaring functions that are called by generated code. Most are extern(C) - for those that are not, ensure to use correct mangling. */ @@ -35,193 +36,207 @@ along with GCC; see the file COPYING3. If not see /* Used when an assert() contract fails. */ DEF_D_RUNTIME (ASSERT, "_d_assert", RT(VOID), P2(STRING, UINT), - ECF_COLD | ECF_LEAF | ECF_NORETURN) + ECF_COLD | ECF_LEAF | ECF_NORETURN, ".RR") DEF_D_RUNTIME (ASSERT_MSG, "_d_assert_msg", RT(VOID), P3(STRING, STRING, UINT), - ECF_COLD | ECF_LEAF | ECF_NORETURN) + ECF_COLD | ECF_LEAF | ECF_NORETURN, ".RRR") /* Used when an assert() contract fails in a unittest function. */ DEF_D_RUNTIME (UNITTEST, "_d_unittest", RT(VOID), P2(STRING, UINT), - ECF_COLD | ECF_LEAF | ECF_NORETURN) + ECF_COLD | ECF_LEAF | ECF_NORETURN, ".RR") DEF_D_RUNTIME (UNITTEST_MSG, "_d_unittest_msg", RT(VOID), - P3(STRING, STRING, UINT), ECF_COLD | ECF_LEAF | ECF_NORETURN) + P3(STRING, STRING, UINT), + ECF_COLD | ECF_LEAF | ECF_NORETURN, ".RRR") /* Used when an array index outside the bounds of its range. */ DEF_D_RUNTIME (ARRAY_BOUNDS, "_d_arraybounds", RT(VOID), P2(STRING, UINT), - ECF_COLD | ECF_LEAF | ECF_NORETURN) + ECF_COLD | ECF_LEAF | ECF_NORETURN, ".RR") /* Used when calling new on a class. */ DEF_D_RUNTIME (NEWCLASS, "_d_newclass", RT(OBJECT), P1(CONST_CLASSINFO), - ECF_LEAF) + ECF_LEAF, "mR") /* Used when calling delete on a class or interface. */ -DEF_D_RUNTIME (DELCLASS, "_d_delclass", RT(VOID), P1(VOIDPTR), 0) -DEF_D_RUNTIME (DELINTERFACE, "_d_delinterface", RT(VOID), P1(VOIDPTR), 0) +DEF_D_RUNTIME (DELCLASS, "_d_delclass", RT(VOID), P1(VOIDPTR), + 0, ".w") +DEF_D_RUNTIME (DELINTERFACE, "_d_delinterface", RT(VOID), P1(VOIDPTR), + 0, ".w") /* Same as deleting a class, but used for stack-allocated classes. */ -DEF_D_RUNTIME (CALLFINALIZER, "_d_callfinalizer", RT(VOID), P1(VOIDPTR), 0) +DEF_D_RUNTIME (CALLFINALIZER, "_d_callfinalizer", RT(VOID), P1(VOIDPTR), + 0, ".w") DEF_D_RUNTIME (CALLINTERFACEFINALIZER, "_d_callinterfacefinalizer", RT(VOID), - P1(VOIDPTR), 0) + P1(VOIDPTR), 0, ".w") /* Used for casting to a class or interface. */ DEF_D_RUNTIME (DYNAMIC_CAST, "_d_dynamic_cast", RT(OBJECT), - P2(OBJECT, CLASSINFO), ECF_CONST | ECF_LEAF) + P2(OBJECT, CLASSINFO), ECF_CONST | ECF_LEAF, ".rR") DEF_D_RUNTIME (INTERFACE_CAST, "_d_interface_cast", RT(OBJECT), - P2(OBJECT, CLASSINFO), ECF_CONST | ECF_LEAF) + P2(OBJECT, CLASSINFO), ECF_CONST | ECF_LEAF, ".rR") /* Used when calling new on a pointer. The `i' variant is for when the initialiser is non-zero. */ DEF_D_RUNTIME (NEWITEMT, "_d_newitemT", RT(VOIDPTR), P1(CONST_TYPEINFO), - ECF_LEAF) + ECF_LEAF, "mR") DEF_D_RUNTIME (NEWITEMIT, "_d_newitemiT", RT(VOIDPTR), P1(CONST_TYPEINFO), - ECF_LEAF) + ECF_LEAF, "mR") /* Used when calling delete on a pointer. */ DEF_D_RUNTIME (DELMEMORY, "_d_delmemory", RT(VOID), P1(POINTER_VOIDPTR), - ECF_LEAF) + ECF_LEAF, ".w") DEF_D_RUNTIME (DELSTRUCT, "_d_delstruct", RT(VOID), - P2(POINTER_VOIDPTR, TYPEINFO), 0) + P2(POINTER_VOIDPTR, TYPEINFO), 0, ".wR") /* Used when calling new on an array. The `i' variant is for when the initialiser is non-zero, and the `m' variant is when initialising a multi-dimensional array. */ DEF_D_RUNTIME (NEWARRAYT, "_d_newarrayT", RT(ARRAY_VOID), - P2(CONST_TYPEINFO, SIZE_T), ECF_LEAF) + P2(CONST_TYPEINFO, SIZE_T), ECF_LEAF, "mRR") DEF_D_RUNTIME (NEWARRAYIT, "_d_newarrayiT", RT(ARRAY_VOID), - P2(CONST_TYPEINFO, SIZE_T), ECF_LEAF) + P2(CONST_TYPEINFO, SIZE_T), ECF_LEAF, "mRR") DEF_D_RUNTIME (NEWARRAYMTX, "_d_newarraymTX", RT(ARRAY_VOID), - P2(CONST_TYPEINFO, ARRAY_SIZE_T), ECF_LEAF) + P2(CONST_TYPEINFO, ARRAY_SIZE_T), ECF_LEAF, "mRR") DEF_D_RUNTIME (NEWARRAYMITX, "_d_newarraymiTX", RT(ARRAY_VOID), - P2(CONST_TYPEINFO, ARRAY_SIZE_T), ECF_LEAF) + P2(CONST_TYPEINFO, ARRAY_SIZE_T), ECF_LEAF, "mRR") /* Used for allocating an array literal on the GC heap. */ DEF_D_RUNTIME (ARRAYLITERALTX, "_d_arrayliteralTX", RT(VOIDPTR), - P2(CONST_TYPEINFO, SIZE_T), ECF_LEAF) + P2(CONST_TYPEINFO, SIZE_T), ECF_LEAF, "mRR") /* Used when calling delete on an array. */ DEF_D_RUNTIME (DELARRAYT, "_d_delarray_t", RT(VOID), - P2(ARRAYPTR_VOID, CONST_TYPEINFO), 0) + P2(ARRAYPTR_VOID, CONST_TYPEINFO), 0, ".wR") /* Used for value equality (x == y) and comparisons (x < y) of non-trivial arrays. Such as an array of structs or classes. */ DEF_D_RUNTIME (ADEQ2, "_adEq2", RT(INT), - P3(ARRAY_VOID, ARRAY_VOID, CONST_TYPEINFO), 0) + P3(ARRAY_VOID, ARRAY_VOID, CONST_TYPEINFO), 0, ".RRR") DEF_D_RUNTIME (ADCMP2, "_adCmp2", RT(INT), - P3(ARRAY_VOID, ARRAY_VOID, CONST_TYPEINFO), 0) + P3(ARRAY_VOID, ARRAY_VOID, CONST_TYPEINFO), 0, ".RRR") /* Used when casting from one array type to another where the index type - sizes differ. Such as from int[] to short[]. */ + sizes differ, such as from int[] to short[]. + TODO: This function returns its third argument, but the backend is does + not handle this for aggregates properly. */ DEF_D_RUNTIME (ARRAYCAST, "_d_arraycast", RT(ARRAY_VOID), - P3(SIZE_T, SIZE_T, ARRAY_VOID), ECF_CONST | ECF_LEAF) + P3(SIZE_T, SIZE_T, ARRAY_VOID), ECF_CONST | ECF_LEAF, ".RRw") /* Used for (array.length = n) expressions. The `i' variant is for when the initialiser is non-zero. */ DEF_D_RUNTIME (ARRAYSETLENGTHT, "_d_arraysetlengthT", RT(ARRAY_VOID), - P3(CONST_TYPEINFO, SIZE_T, ARRAYPTR_VOID), 0) + P3(CONST_TYPEINFO, SIZE_T, ARRAYPTR_VOID), 0, ".RR.") DEF_D_RUNTIME (ARRAYSETLENGTHIT, "_d_arraysetlengthiT", RT(ARRAY_VOID), - P3(CONST_TYPEINFO, SIZE_T, ARRAYPTR_VOID), 0) + P3(CONST_TYPEINFO, SIZE_T, ARRAYPTR_VOID), 0, ".RR.") /* Used for allocating closures on the GC heap. */ DEF_D_RUNTIME (ALLOCMEMORY, "_d_allocmemory", RT(VOIDPTR), P1(SIZE_T), - ECF_LEAF | ECF_MALLOC | ECF_PURE) + ECF_LEAF | ECF_MALLOC | ECF_PURE, "mR") /* Used for copying an array into a slice, adds an enforcment that the source - and destination are equal in size and do not overlap. */ + and destination are equal in size and do not overlap. + TODO: This function returns its third argument, but the backend is does + not handle this for aggregates properly. */ DEF_D_RUNTIME (ARRAYCOPY, "_d_arraycopy", RT(ARRAY_VOID), - P3(SIZE_T, ARRAY_VOID, ARRAY_VOID), ECF_LEAF) + P3(SIZE_T, ARRAY_VOID, ARRAY_VOID), ECF_LEAF, ".RRw") /* Used for array assignments from an existing array. The `set' variant is for - when the assignment value is a single element. */ + when the assignment value is a single element. + TODO: These functions return their third argument, but the backend is does + not handle this for aggregates properly. */ DEF_D_RUNTIME (ARRAYASSIGN, "_d_arrayassign", RT(ARRAY_VOID), - P3(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID), 0) + P3(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID), 0, ".RR.") DEF_D_RUNTIME (ARRAYASSIGN_L, "_d_arrayassign_l", RT(ARRAY_VOID), - P4(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID, VOIDPTR), 0) + P4(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID, VOIDPTR), 0, ".RR.W") DEF_D_RUNTIME (ARRAYASSIGN_R, "_d_arrayassign_r", RT(ARRAY_VOID), - P4(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID, VOIDPTR), 0) + P4(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID, VOIDPTR), 0, ".RRwW") DEF_D_RUNTIME (ARRAYSETASSIGN, "_d_arraysetassign", RT(VOIDPTR), - P4(VOIDPTR, VOIDPTR, SIZE_T, CONST_TYPEINFO), 0) + P4(VOIDPTR, VOIDPTR, SIZE_T, CONST_TYPEINFO), 0, "1.RRR") /* Used for constructing a new array from an existing array. The `set' variant - is for when the constructor value is a single element. */ + is for when the constructor value is a single element. + TODO: This function returns its third argument, but the backend is does + not handle this for aggregates properly. */ DEF_D_RUNTIME (ARRAYCTOR, "_d_arrayctor", RT(ARRAY_VOID), - P3(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID), 0) + P3(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID), 0, ".RR.") DEF_D_RUNTIME (ARRAYSETCTOR, "_d_arraysetctor", RT(VOIDPTR), - P4(VOIDPTR, VOIDPTR, SIZE_T, CONST_TYPEINFO), 0) + P4(VOIDPTR, VOIDPTR, SIZE_T, CONST_TYPEINFO), 0, "1.RRR") /* Used for concatenating two or more arrays together. Then `n' variant is for when there is more than two arrays to handle. */ DEF_D_RUNTIME (ARRAYCATT, "_d_arraycatT", RT(ARRAY_BYTE), - P3(CONST_TYPEINFO, ARRAY_BYTE, ARRAY_BYTE), 0) + P3(CONST_TYPEINFO, ARRAY_BYTE, ARRAY_BYTE), 0, "mRRR") DEF_D_RUNTIME (ARRAYCATNTX, "_d_arraycatnTX", RT(ARRAY_VOID), - P2(CONST_TYPEINFO, ARRAYARRAY_BYTE), 0) + P2(CONST_TYPEINFO, ARRAYARRAY_BYTE), 0, "mRR") /* Used for appending a single element to an array. */ DEF_D_RUNTIME (ARRAYAPPENDCTX, "_d_arrayappendcTX", RT(ARRAY_BYTE), - P3(CONST_TYPEINFO, ARRAYPTR_BYTE, SIZE_T), 0) + P3(CONST_TYPEINFO, ARRAYPTR_BYTE, SIZE_T), 0, ".R.R") /* Same as appending a single element to an array, but specific for when the source is a UTF-32 character, and the destination is a UTF-8 or 16 array. */ DEF_D_RUNTIME (ARRAYAPPENDCD, "_d_arrayappendcd", RT(ARRAY_VOID), - P2(ARRAYPTR_BYTE, DCHAR), ECF_LEAF) + P2(ARRAYPTR_BYTE, DCHAR), ECF_LEAF, ".wR") DEF_D_RUNTIME (ARRAYAPPENDWD, "_d_arrayappendwd", RT(ARRAY_VOID), - P2(ARRAYPTR_BYTE, DCHAR), ECF_LEAF) + P2(ARRAYPTR_BYTE, DCHAR), ECF_LEAF, ".wR") /* Used for appending an existing array to another. */ DEF_D_RUNTIME (ARRAYAPPENDT, "_d_arrayappendT", RT(ARRAY_VOID), - P3(TYPEINFO, ARRAYPTR_BYTE, ARRAY_BYTE), 0) + P3(TYPEINFO, ARRAYPTR_BYTE, ARRAY_BYTE), 0, ".R.R") /* Used for allocating a new associative array. */ DEF_D_RUNTIME (ASSOCARRAYLITERALTX, "_d_assocarrayliteralTX", RT(VOIDPTR), - P3(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID), 0) + P3(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID), 0, "mRRR") /* Used for value equality of two associative arrays. */ DEF_D_RUNTIME (AAEQUAL, "_aaEqual", RT(INT), - P3(CONST_TYPEINFO, ASSOCARRAY, ASSOCARRAY), 0) + P3(CONST_TYPEINFO, ASSOCARRAY, ASSOCARRAY), 0, ".RRR") /* Used to determine is a key exists in an associative array. */ DEF_D_RUNTIME (AAINX, "_aaInX", RT(VOIDPTR), - P3(ASSOCARRAY, CONST_TYPEINFO, VOIDPTR), ECF_CONST | ECF_LEAF) + P3(ASSOCARRAY, CONST_TYPEINFO, VOIDPTR), + ECF_CONST | ECF_LEAF, ".RRR") /* Used to retrieve a value from an associative array index by a key. The `Rvalue' variant returns null if the key is not found, where as aaGetY will create new key entry for assignment. */ DEF_D_RUNTIME (AAGETY, "_aaGetY", RT(VOIDPTR), - P4(POINTER_ASSOCARRAY, CONST_TYPEINFO, SIZE_T, VOIDPTR), 0) + P4(POINTER_ASSOCARRAY, CONST_TYPEINFO, SIZE_T, VOIDPTR), + 0, ".wRRR") DEF_D_RUNTIME (AAGETRVALUEX, "_aaGetRvalueX", RT(VOIDPTR), P4(ASSOCARRAY, CONST_TYPEINFO, SIZE_T, VOIDPTR), - ECF_CONST | ECF_LEAF) + ECF_CONST | ECF_LEAF, ".RRRR") /* Used when calling delete on a key entry in an associative array. */ DEF_D_RUNTIME (AADELX, "_aaDelX", RT(BOOL), - P3(ASSOCARRAY, CONST_TYPEINFO, VOIDPTR), ECF_LEAF) + P3(ASSOCARRAY, CONST_TYPEINFO, VOIDPTR), ECF_LEAF, ".wRR") /* Used for throw() expressions. */ -DEF_D_RUNTIME (THROW, "_d_throw", RT(VOID), P1(OBJECT), ECF_NORETURN) +DEF_D_RUNTIME (THROW, "_d_throw", RT(VOID), P1(OBJECT), ECF_NORETURN, NULL) DEF_D_RUNTIME (BEGIN_CATCH, "__gdc_begin_catch", RT(VOIDPTR), P1(VOIDPTR), - ECF_NOTHROW) + ECF_NOTHROW, NULL) /* C++ exception handlers. */ DEF_D_RUNTIME (CXA_BEGIN_CATCH, "__cxa_begin_catch", RT(VOIDPTR), P1(VOIDPTR), - ECF_NOTHROW) -DEF_D_RUNTIME (CXA_END_CATCH, "__cxa_end_catch", RT(VOID), P0(), 0) + ECF_NOTHROW, NULL) +DEF_D_RUNTIME (CXA_END_CATCH, "__cxa_end_catch", RT(VOID), P0(), 0, NULL) /* When invariant() contracts are turned on, used after testing whether a class != null for validating the state of a class. */ DEF_D_RUNTIME (INVARIANT, "_D9invariant12_d_invariantFC6ObjectZv", RT(VOID), - P1(OBJECT), 0) + P1(OBJECT), 0, ".r") /* Used when performing a switch/cases on a string. The `u' and `d' variants are for UTF-16 and UTF-32 strings respectively. */ DEF_D_RUNTIME (SWITCH_STRING, "_d_switch_string", RT(INT), - P2(ARRAY_STRING, STRING), ECF_CONST | ECF_LEAF) + P2(ARRAY_STRING, STRING), ECF_CONST | ECF_LEAF, ".RR") DEF_D_RUNTIME (SWITCH_USTRING, "_d_switch_ustring", RT(INT), - P2(ARRAY_WSTRING, WSTRING), ECF_CONST | ECF_LEAF) + P2(ARRAY_WSTRING, WSTRING), ECF_CONST | ECF_LEAF, ".RR") DEF_D_RUNTIME (SWITCH_DSTRING, "_d_switch_dstring", RT(INT), - P2(ARRAY_DSTRING, DSTRING), ECF_CONST | ECF_LEAF) + P2(ARRAY_DSTRING, DSTRING), ECF_CONST | ECF_LEAF, ".RR") /* Used when throwing an error that a switch statement has no default case, and yet none of the existing cases matched. */ DEF_D_RUNTIME (SWITCH_ERROR, "_d_switch_error", RT(VOID), P2(STRING, UINT), - ECF_COLD | ECF_LEAF | ECF_NORETURN) + ECF_COLD | ECF_LEAF | ECF_NORETURN, ".RR") #undef P0 #undef P1