This patch builds access to the gcc builtins clz, clzl, clzll,
ctz, ctzl and ctzll within m2builtins.cc. The patch provides
modula2 api access to clz, clzll, ctz and ctzll though the
Builtins definition module. This PR was raised because of
PR118689.
gcc/m2/ChangeLog:
PR modula2/118703
* gm2-gcc/m2builtins.cc (define_builtin_gcc): New function.
(m2builtins_init): Call define_builtin_gcc.
* gm2-libs/Builtins.def (clz): New procedure function.
(clzll): Ditto.
(ctz): Ditto.
(ctzll): Ditto.
* gm2-libs/Builtins.mod (clz): New procedure function.
(clzll): Ditto.
(ctz): Ditto.
(ctzll): Ditto.
* gm2-libs/cbuiltin.def (clz): New procedure function.
(clzll): Ditto.
(ctz): Ditto.
(ctzll): Ditto.
gcc/testsuite/ChangeLog:
PR modula2/118703
* gm2/builtins/run/pass/testbitfns.mod: New test.
(cherry picked from commit
e2d32c81a993a27f3e9b5408f5d20580fe58feca)
Signed-off-by: Gaius Mulley <gaiusmod2@gmail.com>
BUILT_IN_NORMAL, "strchr", NULL, NULL, bf_default_lib },
{ "__builtin_strrchr", BT_FN_STRING_CONST_STRING_INT, BUILT_IN_STRCHR,
BUILT_IN_NORMAL, "strrchr", NULL, NULL, bf_default_lib },
+
{ "__builtin_frame_address", BT_FN_PTR_UNSIGNED, BUILT_IN_FRAME_ADDRESS,
BUILT_IN_NORMAL, "frame_address", NULL, NULL, bf_gcc },
{ "__builtin_return_address", BT_FN_PTR_UNSIGNED, BUILT_IN_RETURN_ADDRESS,
static GTY (()) tree doubleptr_type_node;
static GTY (()) tree floatptr_type_node;
static GTY (()) tree builtin_ftype_int_var;
+static GTY (()) tree builtin_ftype_int_uint;
+static GTY (()) tree builtin_ftype_int_ulong;
+static GTY (()) tree builtin_ftype_int_ulonglong;
static GTY (()) vec<builtin_macro_definition, va_gc> *builtin_macros;
/* Prototypes for locally defined functions. */
versions as well? */
}
+/* Define gcc specific builtins. */
+
+static
+void
+define_builtin_gcc (void)
+{
+ /* Bit count functions. */
+ define_builtin (BUILT_IN_CLZ, "clz", builtin_ftype_int_uint,
+ "__builtin_clz", ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+ define_builtin (BUILT_IN_CLZL, "clzl", builtin_ftype_int_ulong,
+ "__builtin_clzl", ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+ define_builtin (BUILT_IN_CLZLL, "clzll", builtin_ftype_int_ulonglong,
+ "__builtin_clzll", ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+ define_builtin (BUILT_IN_CTZ, "ctz", builtin_ftype_int_uint,
+ "__builtin_ctz", ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+ define_builtin (BUILT_IN_CTZL, "ctzl", builtin_ftype_int_ulong,
+ "__builtin_ctzl", ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+ define_builtin (BUILT_IN_CTZLL, "ctzll", builtin_ftype_int_ulonglong,
+ "__builtin_ctzll", ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+}
+
void
m2builtins_init (location_t location)
{
builtin_ftype_int_var = build_function_type (
integer_type_node, tree_cons (NULL_TREE, double_type_node, endlink));
+ builtin_ftype_int_uint = build_function_type (
+ integer_type_node, tree_cons (NULL_TREE, unsigned_type_node, endlink));
+
+ builtin_ftype_int_ulong = build_function_type (
+ integer_type_node, tree_cons (NULL_TREE, long_unsigned_type_node, endlink));
+
+ builtin_ftype_int_ulonglong = build_function_type (
+ integer_type_node, tree_cons (NULL_TREE, long_long_unsigned_type_node, endlink));
+
for (i = 0; list_of_builtins[i].name != NULL; i++)
create_function_prototype (location, &list_of_builtins[i]);
define_builtin_math (BUILT_IN_ISINF_SIGN, "isinf_sign", builtin_ftype_int_var,
"__builtin_isinf_sign", ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+ define_builtin_gcc ();
+
gm2_alloca_node = find_builtin_tree ("__builtin_alloca");
gm2_memcpy_node = find_builtin_tree ("__builtin_memcpy");
gm2_memset_node = find_builtin_tree ("__builtin_memset");
PROCEDURE __BUILTIN__ strchr (s: ADDRESS; c: INTEGER) : ADDRESS ;
PROCEDURE __BUILTIN__ strrchr (s: ADDRESS; c: INTEGER) : ADDRESS ;
+PROCEDURE __BUILTIN__ clz (value: CARDINAL) : INTEGER ;
+PROCEDURE __BUILTIN__ clzll (value: LONGCARD) : INTEGER ;
+PROCEDURE __BUILTIN__ ctz (value: CARDINAL) : INTEGER ;
+PROCEDURE __BUILTIN__ ctzll (value: LONGCARD) : INTEGER ;
+
(*
longjmp - this GCC builtin restricts the val to always 1.
*)
RETURN 1
END isinf_signl ;
+PROCEDURE __ATTRIBUTE__ __BUILTIN__ ((__builtin_clz)) clz (value: CARDINAL) : INTEGER ;
+BEGIN
+ RETURN 1
+END clz ;
+
+PROCEDURE __ATTRIBUTE__ __BUILTIN__ ((__builtin_clzll)) clzll (value: LONGCARD) : INTEGER ;
+BEGIN
+ RETURN 1
+END clzll ;
+
+PROCEDURE __ATTRIBUTE__ __BUILTIN__ ((__builtin_ctz)) ctz (value: CARDINAL) : INTEGER ;
+BEGIN
+ RETURN 1
+END ctz ;
+
+PROCEDURE __ATTRIBUTE__ __BUILTIN__ ((__builtin_ctzll)) ctzll (value: LONGCARD) : INTEGER ;
+BEGIN
+ RETURN 1
+END ctzll ;
+
PROCEDURE __ATTRIBUTE__ __BUILTIN__ ((__builtin_longjmp)) longjmp (env: ADDRESS; val: INTEGER) ;
BEGIN
(* Empty, replaced internally by gcc. *)
index, rindex,
memcmp, memset, memmove,
strcat, strncat, strcpy, strncpy, strcmp, strncmp,
- strlen, strstr, strpbrk, strspn, strcspn, strchr, strrchr ;
+ strlen, strstr, strpbrk, strspn, strcspn, strchr, strrchr,
+
+ clz, clzll,
+ ctz, ctzll ;
PROCEDURE alloca (i: CARDINAL) : ADDRESS ;
PROCEDURE memcpy (dest, src: ADDRESS; n: CARDINAL) : ADDRESS ;
PROCEDURE strchr (s: ADDRESS; c: INTEGER) : ADDRESS ;
PROCEDURE strrchr (s: ADDRESS; c: INTEGER) : ADDRESS ;
+PROCEDURE clz (value: CARDINAL) : INTEGER ;
+PROCEDURE clzll (value: CARDINAL) : INTEGER ;
+PROCEDURE ctz (value: CARDINAL) : INTEGER ;
+PROCEDURE ctzll (value: CARDINAL) : INTEGER ;
+
+
END cbuiltin.
--- /dev/null
+MODULE testbitfns ;
+
+FROM libc IMPORT printf, exit ;
+FROM Builtins IMPORT clz, clzll, ctz, ctzll ;
+
+
+(*
+ Assert -
+*)
+
+PROCEDURE Assert (name: ARRAY OF CHAR;
+ input, left, right: INTEGER; line: CARDINAL) ;
+BEGIN
+ IF left = right
+ THEN
+ printf ("pass: %s (%d) = %d\n", name, input, left)
+ ELSE
+ printf ("fail: %s (%d) # %d (should be %d)\n", name, input, left, right) ;
+ exitcode := 1
+ END
+END Assert ;
+
+
+(*
+ runtests -
+*)
+
+PROCEDURE runtests ;
+VAR
+ c : CARDINAL ;
+ l : LONGCARD ;
+ result: INTEGER ;
+BEGIN
+ c := 16 ;
+ result := ctz (c) ;
+ Assert ("ctz", c, result, 4, __LINE__) ;
+ c := 4 ;
+ result := ctz (c) ;
+ Assert ("ctz", c, result, 2, __LINE__) ;
+ c := 14 ;
+ result := ctz (c) ;
+ Assert ("ctz", c, result, 1, __LINE__) ;
+ l := 16 ;
+ result := ctzll (l) ;
+ Assert ("ctzll", l, result, 4, __LINE__) ;
+ l := 4 ;
+ result := ctzll (l) ;
+ Assert ("ctzll", l, result, 2, __LINE__) ;
+ l := 14 ;
+ result := ctzll (l) ;
+ Assert ("ctzll", l, result, 1, __LINE__) ;
+
+ IF SIZE (c) = 4
+ THEN
+ c := 16 ;
+ result := clz (c) ;
+ Assert ("clz", c, result, 27, __LINE__) ;
+ c := 4 ;
+ result := clz (c) ;
+ Assert ("clz", c, result, 29, __LINE__) ;
+ c := 14 ;
+ result := clz (c) ;
+ Assert ("clz", c, result, 28, __LINE__) ;
+ IF SIZE (l) = 8
+ THEN
+ l := 16 ;
+ result := clzll (l) ;
+ Assert ("clzll", l, result, 59, __LINE__) ;
+ l := 4 ;
+ result := clzll (l) ;
+ Assert ("clzll", l, result, 61, __LINE__) ;
+ l := 14 ;
+ result := clzll (l) ;
+ Assert ("ctzll", l, result, 60, __LINE__)
+ END
+ END
+END runtests ;
+
+
+VAR
+ exitcode: INTEGER ;
+BEGIN
+ exitcode := 0 ;
+ runtests ;
+ IF exitcode = 0
+ THEN
+ printf ("all tests pass!\n")
+ END ;
+ exit (exitcode)
+END testbitfns.