@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
2121#include " config.h"
2222#include " system.h"
2323#include " coretypes.h"
24+ #include " target.h"
2425#include " jit-playback.h"
2526#include " stor-layout.h"
2627#include " debug.h"
@@ -34,8 +35,12 @@ along with GCC; see the file COPYING3. If not see
3435#include " target.h"
3536#include " diagnostic-format-text.h"
3637#include " make-unique.h"
38+ #include " print-tree.h"
3739
3840#include < mpfr.h>
41+ #include < unordered_map>
42+
43+ using namespace gcc ::jit;
3944
4045/* Attribute handling. */
4146
@@ -140,6 +145,14 @@ static const struct attribute_spec::exclusions attr_target_exclusions[] =
140145 ATTR_EXCL (NULL , false , false , false ),
141146};
142147
148+ /* These variables act as a cache for the target builtins. This is needed in
149+ order to be able to type-check the calls since we can only get those types
150+ in the playback phase while we need them in the recording phase. */
151+ hash_map<nofree_string_hash, tree> target_builtins{};
152+ std::unordered_map<std::string, recording::function_type*> target_function_types
153+ {};
154+ recording::context target_builtins_ctxt{NULL };
155+
143156/* Table of machine-independent attributes supported in libgccjit. */
144157static const attribute_spec jit_gnu_attributes[] =
145158{
@@ -1079,13 +1092,16 @@ jit_langhook_init (void)
10791092
10801093 build_common_tree_nodes (flag_signed_char);
10811094
1095+ target_builtins.empty ();
10821096 build_common_builtin_nodes ();
10831097
10841098 /* The default precision for floating point numbers. This is used
10851099 for floating point constants with abstract type. This may
10861100 eventually be controllable by a command line option. */
10871101 mpfr_set_default_prec (256 );
10881102
1103+ targetm.init_builtins ();
1104+
10891105 return true ;
10901106}
10911107
@@ -1153,11 +1169,198 @@ jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
11531169 return NULL ;
11541170}
11551171
1156- /* Record a builtin function. We just ignore builtin functions. */
1172+ recording::type* tree_type_to_jit_type (tree type)
1173+ {
1174+ if (TREE_CODE (type) == VECTOR_TYPE)
1175+ {
1176+ tree inner_type = TREE_TYPE (type);
1177+ recording::type* element_type = tree_type_to_jit_type (inner_type);
1178+ poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
1179+ long constant_size = size.to_constant ();
1180+ if (element_type != NULL )
1181+ return element_type->get_vector (constant_size);
1182+ return NULL ;
1183+ }
1184+ if (TREE_CODE (type) == REFERENCE_TYPE)
1185+ // For __builtin_ms_va_start.
1186+ // FIXME: wrong type.
1187+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1188+ GCC_JIT_TYPE_VOID);
1189+ if (TREE_CODE (type) == RECORD_TYPE)
1190+ // For __builtin_sysv_va_copy.
1191+ // FIXME: wrong type.
1192+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1193+ GCC_JIT_TYPE_VOID);
1194+ /* TODO: Remove when we add support for sized floating-point types. */
1195+ for (int i = 0 ; i < NUM_FLOATN_NX_TYPES; i++)
1196+ if (type == FLOATN_NX_TYPE_NODE (i))
1197+ // FIXME: wrong type.
1198+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1199+ GCC_JIT_TYPE_VOID);
1200+ if (type == void_type_node)
1201+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1202+ GCC_JIT_TYPE_VOID);
1203+ else if (type == ptr_type_node)
1204+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1205+ GCC_JIT_TYPE_VOID_PTR);
1206+ else if (type == const_ptr_type_node)
1207+ {
1208+ // Void const ptr.
1209+ recording::type* result =
1210+ new recording::memento_of_get_type (&target_builtins_ctxt,
1211+ GCC_JIT_TYPE_VOID_PTR);
1212+ return new recording::memento_of_get_const (result);
1213+ }
1214+ else if (type == unsigned_type_node)
1215+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1216+ GCC_JIT_TYPE_UNSIGNED_INT);
1217+ else if (type == long_unsigned_type_node)
1218+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1219+ GCC_JIT_TYPE_UNSIGNED_LONG);
1220+ else if (type == integer_type_node)
1221+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1222+ GCC_JIT_TYPE_INT);
1223+ else if (type == long_integer_type_node)
1224+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1225+ GCC_JIT_TYPE_LONG);
1226+ else if (type == long_long_integer_type_node)
1227+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1228+ GCC_JIT_TYPE_LONG_LONG);
1229+ else if (type == signed_char_type_node)
1230+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1231+ GCC_JIT_TYPE_SIGNED_CHAR);
1232+ else if (type == char_type_node)
1233+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1234+ GCC_JIT_TYPE_CHAR);
1235+ else if (type == unsigned_intQI_type_node)
1236+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1237+ GCC_JIT_TYPE_UINT8_T);
1238+ else if (type == short_integer_type_node)
1239+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1240+ GCC_JIT_TYPE_SHORT);
1241+ else if (type == short_unsigned_type_node)
1242+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1243+ GCC_JIT_TYPE_UNSIGNED_SHORT);
1244+ else if (type == complex_float_type_node)
1245+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1246+ GCC_JIT_TYPE_COMPLEX_FLOAT);
1247+ else if (type == complex_double_type_node)
1248+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1249+ GCC_JIT_TYPE_COMPLEX_DOUBLE);
1250+ else if (type == complex_long_double_type_node)
1251+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1252+ GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
1253+ else if (type == float_type_node)
1254+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1255+ GCC_JIT_TYPE_FLOAT);
1256+ else if (type == double_type_node)
1257+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1258+ GCC_JIT_TYPE_DOUBLE);
1259+ else if (type == long_double_type_node)
1260+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1261+ GCC_JIT_TYPE_LONG_DOUBLE);
1262+ else if (type == bfloat16_type_node)
1263+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1264+ GCC_JIT_TYPE_BFLOAT16);
1265+ else if (type == dfloat128_type_node)
1266+ // FIXME: wrong type.
1267+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1268+ GCC_JIT_TYPE_VOID);
1269+ else if (type == long_long_unsigned_type_node)
1270+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1271+ GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
1272+ else if (type == boolean_type_node)
1273+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1274+ GCC_JIT_TYPE_BOOL);
1275+ else if (type == size_type_node)
1276+ return new recording::memento_of_get_type (&target_builtins_ctxt,
1277+ GCC_JIT_TYPE_SIZE_T);
1278+ else if (TREE_CODE (type) == POINTER_TYPE)
1279+ {
1280+ tree inner_type = TREE_TYPE (type);
1281+ recording::type* element_type = tree_type_to_jit_type (inner_type);
1282+ return element_type->get_pointer ();
1283+ }
1284+ else
1285+ {
1286+ // Attempt to find an unqualified type when the current type has qualifiers.
1287+ tree tp = TYPE_MAIN_VARIANT (type);
1288+ for ( ; tp != NULL ; tp = TYPE_NEXT_VARIANT (tp))
1289+ {
1290+ if (TYPE_QUALS (tp) == 0 && type != tp)
1291+ {
1292+ recording::type* result = tree_type_to_jit_type (tp);
1293+ if (result != NULL )
1294+ {
1295+ if (TYPE_READONLY (tp))
1296+ result = new recording::memento_of_get_const (result);
1297+ if (TYPE_VOLATILE (tp))
1298+ result = new recording::memento_of_get_volatile (result);
1299+ return result;
1300+ }
1301+ }
1302+ }
1303+
1304+ fprintf (stderr, " Unknown type:\n " );
1305+ debug_tree (type);
1306+ abort ();
1307+ }
1308+
1309+ return NULL ;
1310+ }
1311+
1312+ /* Record a builtin function. We save their types to be able to check types
1313+ in recording and for reflection. */
11571314
11581315static tree
11591316jit_langhook_builtin_function (tree decl)
11601317{
1318+ if (TREE_CODE (decl) == FUNCTION_DECL)
1319+ {
1320+ const char * name = IDENTIFIER_POINTER (DECL_NAME (decl));
1321+ target_builtins.put (name, decl);
1322+
1323+ std::string string_name (name);
1324+ if (target_function_types.count (string_name) == 0 )
1325+ {
1326+ tree function_type = TREE_TYPE (decl);
1327+ tree arg = TYPE_ARG_TYPES (function_type);
1328+ bool is_variadic = false ;
1329+
1330+ auto_vec <recording::type *> param_types;
1331+
1332+ while (arg != void_list_node)
1333+ {
1334+ if (arg == NULL )
1335+ {
1336+ is_variadic = true ;
1337+ break ;
1338+ }
1339+ if (arg != void_list_node)
1340+ {
1341+ recording::type* arg_type = tree_type_to_jit_type (TREE_VALUE (arg));
1342+ if (arg_type == NULL )
1343+ return decl;
1344+ param_types.safe_push (arg_type);
1345+ }
1346+ arg = TREE_CHAIN (arg);
1347+ }
1348+
1349+ tree result_type = TREE_TYPE (function_type);
1350+ recording::type* return_type = tree_type_to_jit_type (result_type);
1351+
1352+ if (return_type == NULL )
1353+ return decl;
1354+
1355+ recording::function_type* func_type =
1356+ new recording::function_type (&target_builtins_ctxt, return_type,
1357+ param_types.length (),
1358+ param_types.address (), is_variadic,
1359+ false );
1360+
1361+ target_function_types[string_name] = func_type;
1362+ }
1363+ }
11611364 return decl;
11621365}
11631366
0 commit comments