Skip to content

Commit 5d25bd6

Browse files
committed
libgccjit: Add support for machine-dependent builtins
gcc/config/i386: PR jit/TODO * i386-builtins.cc: New function (clear_builtin_types). gcc/jit: PR jit/TODO * dummy-frontend.cc: Include headers target.h, jit-recording.h, unordered_map and string, new variables (target_function_types, and target_builtins_ctxt), new function (tree_type_to_jit_type). * jit-builtins.cc: Specify that the function types are not from target builtins. * jit-playback.cc: New argument is_target_builtin to new_function. * jit-playback.h * jit-recording.cc * jit-recording.h * libgccjit.cc * libgccjit.h * libgccjit.map gcc/testsuite/jit.dg: PR jit/TODO * all-non-failing-tests.h * test-target-builtins.c
1 parent 561b4ca commit 5d25bd6

13 files changed

+1057
-24
lines changed

gcc/config/i386/i386-builtins.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,22 @@ static GTY(()) tree ix86_builtins[(int) IX86_BUILTIN_MAX];
226226

227227
struct builtin_isa ix86_builtins_isa[(int) IX86_BUILTIN_MAX];
228228

229+
static void
230+
clear_builtin_types (void)
231+
{
232+
for (int i = 0 ; i < IX86_BT_LAST_CPTR + 1 ; i++)
233+
ix86_builtin_type_tab[i] = NULL;
234+
235+
for (int i = 0 ; i < IX86_BUILTIN_MAX ; i++)
236+
{
237+
ix86_builtins[i] = NULL;
238+
ix86_builtins_isa[i].set_and_not_built_p = true;
239+
}
240+
241+
for (int i = 0 ; i < IX86_BT_LAST_ALIAS + 1 ; i++)
242+
ix86_builtin_func_type_tab[i] = NULL;
243+
}
244+
229245
tree get_ix86_builtin (enum ix86_builtins c)
230246
{
231247
return ix86_builtins[c];
@@ -1443,6 +1459,8 @@ ix86_init_builtins (void)
14431459
{
14441460
tree ftype, decl;
14451461

1462+
clear_builtin_types ();
1463+
14461464
ix86_init_builtin_types ();
14471465

14481466
/* Builtins to get CPU type and features. */

gcc/jit/dummy-frontend.cc

Lines changed: 219 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
2020
#include "config.h"
2121
#include "system.h"
2222
#include "coretypes.h"
23+
#include "target.h"
2324
#include "jit-playback.h"
2425
#include "stor-layout.h"
2526
#include "debug.h"
@@ -29,8 +30,14 @@ along with GCC; see the file COPYING3. If not see
2930
#include "options.h"
3031
#include "stringpool.h"
3132
#include "attribs.h"
33+
#include "jit-recording.h"
34+
#include "print-tree.h"
3235

3336
#include <mpfr.h>
37+
#include <unordered_map>
38+
#include <string>
39+
40+
using namespace gcc::jit;
3441

3542
/* Attribute handling. */
3643

@@ -86,6 +93,10 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
8693
ATTR_EXCL (NULL, false, false, false)
8794
};
8895

96+
hash_map<nofree_string_hash, tree> target_builtins{};
97+
std::unordered_map<std::string, recording::function_type*> target_function_types{};
98+
recording::context target_builtins_ctxt{NULL};
99+
89100
/* Table of machine-independent attributes supported in libgccjit. */
90101
const struct attribute_spec jit_attribute_table[] =
91102
{
@@ -609,6 +620,8 @@ jit_langhook_init (void)
609620
eventually be controllable by a command line option. */
610621
mpfr_set_default_prec (256);
611622

623+
targetm.init_builtins ();
624+
612625
return true;
613626
}
614627

@@ -676,11 +689,216 @@ jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
676689
return NULL;
677690
}
678691

679-
/* Record a builtin function. We just ignore builtin functions. */
692+
recording::type* tree_type_to_jit_type (tree type)
693+
{
694+
if (TREE_CODE (type) == VECTOR_TYPE)
695+
{
696+
tree inner_type = TREE_TYPE (type);
697+
recording::type* element_type = tree_type_to_jit_type (inner_type);
698+
poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
699+
long constant_size = size.to_constant();
700+
if (element_type != NULL)
701+
return element_type->get_vector (constant_size);
702+
return NULL;
703+
}
704+
if (TREE_CODE (type) == REFERENCE_TYPE)
705+
{
706+
// For __builtin_ms_va_start.
707+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID); // FIXME: wrong type.
708+
}
709+
if (TREE_CODE (type) == RECORD_TYPE)
710+
{
711+
// For __builtin_sysv_va_copy.
712+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID); // FIXME: wrong type.
713+
}
714+
for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
715+
{
716+
if (type == FLOATN_NX_TYPE_NODE (i))
717+
{
718+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID); // FIXME: wrong type.
719+
}
720+
}
721+
if (type == void_type_node)
722+
{
723+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID);
724+
}
725+
else if (type == ptr_type_node)
726+
{
727+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID_PTR);
728+
}
729+
else if (type == const_ptr_type_node)
730+
{
731+
// Void const ptr.
732+
recording::type* result = new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID_PTR);
733+
return new recording::memento_of_get_const (result);
734+
}
735+
else if (type == unsigned_type_node)
736+
{
737+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_UNSIGNED_INT);
738+
}
739+
else if (type == long_unsigned_type_node)
740+
{
741+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_UNSIGNED_LONG);
742+
}
743+
else if (type == integer_type_node)
744+
{
745+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_INT);
746+
}
747+
else if (type == long_integer_type_node)
748+
{
749+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_LONG);
750+
}
751+
else if (type == long_long_integer_type_node)
752+
{
753+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_LONG_LONG);
754+
}
755+
else if (type == signed_char_type_node)
756+
{
757+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_SIGNED_CHAR);
758+
}
759+
else if (type == char_type_node)
760+
{
761+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_CHAR);
762+
}
763+
else if (type == unsigned_intQI_type_node)
764+
{
765+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_UINT8_T);
766+
}
767+
else if (type == short_integer_type_node)
768+
{
769+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_SHORT);
770+
}
771+
else if (type == short_unsigned_type_node)
772+
{
773+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_UNSIGNED_SHORT);
774+
}
775+
else if (type == complex_float_type_node)
776+
{
777+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_COMPLEX_FLOAT);
778+
}
779+
else if (type == complex_double_type_node)
780+
{
781+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_COMPLEX_DOUBLE);
782+
}
783+
else if (type == complex_long_double_type_node)
784+
{
785+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
786+
}
787+
else if (type == float_type_node)
788+
{
789+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_FLOAT);
790+
}
791+
else if (type == double_type_node)
792+
{
793+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_DOUBLE);
794+
}
795+
else if (type == long_double_type_node)
796+
{
797+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_LONG_DOUBLE);
798+
}
799+
else if (type == bfloat16_type_node)
800+
{
801+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_BFLOAT16);
802+
}
803+
else if (type == dfloat128_type_node)
804+
{
805+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID); // FIXME: wrong type.
806+
}
807+
else if (type == long_long_unsigned_type_node)
808+
{
809+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
810+
}
811+
else if (type == boolean_type_node)
812+
{
813+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_BOOL);
814+
}
815+
else if (type == size_type_node)
816+
{
817+
return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_SIZE_T);
818+
}
819+
else if (TREE_CODE (type) == POINTER_TYPE)
820+
{
821+
tree inner_type = TREE_TYPE (type);
822+
recording::type* element_type = tree_type_to_jit_type (inner_type);
823+
return element_type->get_pointer();
824+
}
825+
else
826+
{
827+
// Attempt to find an unqualified type when the current type has qualifiers.
828+
tree tp = TYPE_MAIN_VARIANT (type);
829+
for ( ; tp != NULL ; tp = TYPE_NEXT_VARIANT (tp))
830+
{
831+
if (TYPE_QUALS (tp) == 0 && type != tp)
832+
{
833+
recording::type* result = tree_type_to_jit_type (tp);
834+
if (result != NULL)
835+
{
836+
if (TYPE_READONLY (tp))
837+
result = new recording::memento_of_get_const (result);
838+
if (TYPE_VOLATILE (tp))
839+
result = new recording::memento_of_get_volatile (result);
840+
return result;
841+
}
842+
}
843+
}
844+
845+
fprintf (stderr, "Unknown type:\n");
846+
debug_tree (type);
847+
abort ();
848+
}
849+
850+
return NULL;
851+
}
852+
853+
/* Record a builtin function. We save their types to be able to check types
854+
in recording and for reflection. */
680855

681856
static tree
682857
jit_langhook_builtin_function (tree decl)
683858
{
859+
if (TREE_CODE (decl) == FUNCTION_DECL)
860+
{
861+
const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
862+
target_builtins.put (name, decl);
863+
864+
std::string string_name(name);
865+
if (target_function_types.count (string_name) == 0)
866+
{
867+
tree function_type = TREE_TYPE (decl);
868+
tree arg = TYPE_ARG_TYPES (function_type);
869+
bool is_variadic = false;
870+
871+
auto_vec <recording::type *> param_types;
872+
873+
while (arg != void_list_node)
874+
{
875+
if (arg == NULL)
876+
{
877+
is_variadic = true;
878+
break;
879+
}
880+
if (arg != void_list_node)
881+
{
882+
recording::type* arg_type = tree_type_to_jit_type(TREE_VALUE (arg));
883+
if (arg_type == NULL)
884+
return decl;
885+
param_types.safe_push (arg_type);
886+
}
887+
arg = TREE_CHAIN (arg);
888+
}
889+
890+
tree result_type = TREE_TYPE (function_type);
891+
recording::type* return_type = tree_type_to_jit_type(result_type);
892+
893+
if (return_type == NULL)
894+
return decl;
895+
896+
recording::function_type* func_type = new recording::function_type (&target_builtins_ctxt, return_type, param_types.length (),
897+
param_types.address (), is_variadic, false);
898+
899+
target_function_types[string_name] = func_type;
900+
}
901+
}
684902
return decl;
685903
}
686904

gcc/jit/jit-builtins.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ builtins_manager::make_builtin_function (enum built_in_function builtin_id)
215215
param_types.length (),
216216
params,
217217
func_type->is_variadic (),
218-
builtin_id);
218+
builtin_id,
219+
false);
219220
delete[] params;
220221

221222
/* PR/64020 - If the client code is using builtin cos or sin,
@@ -582,7 +583,8 @@ builtins_manager::make_fn_type (enum jit_builtin_type,
582583
result = m_ctxt->new_function_type (return_type,
583584
num_args,
584585
param_types,
585-
is_variadic);
586+
is_variadic,
587+
false);
586588

587589
error:
588590
delete[] param_types;

gcc/jit/jit-common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see
3636
#endif
3737
#endif
3838

39-
const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_INT128_T + 1;
39+
const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_BFLOAT16 + 1;
4040

4141
/* This comment is included by the docs.
4242

0 commit comments

Comments
 (0)