1 /* PRU target specific passes
2 Copyright (C) 2017-2024 Free Software Foundation, Inc.
3 Dimitar Dimitrov <dimitar@dinux.eu>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #define IN_TARGET_CODE 1
25 #include "coretypes.h"
32 #include "diagnostic-core.h"
35 #include "gimple-iterator.h"
36 #include "gimple-walk.h"
37 #include "gimple-expr.h"
38 #include "tree-pass.h"
40 #include "pru-protos.h"
44 /* Scan the tree to ensure that the compiled code by GCC
45 conforms to the TI ABI specification. If GCC cannot
46 output a conforming code, raise an error. */
47 const pass_data pass_data_pru_tiabi_check
=
49 GIMPLE_PASS
, /* type */
50 "*pru_tiabi_check", /* name */
51 OPTGROUP_NONE
, /* optinfo_flags */
53 PROP_gimple_any
, /* properties_required */
54 0, /* properties_provided */
55 0, /* properties_destroyed */
56 0, /* todo_flags_start */
57 0, /* todo_flags_finish */
60 /* Implementation class for the TI ABI compliance-check pass. */
61 class pass_pru_tiabi_check
: public gimple_opt_pass
64 pass_pru_tiabi_check (gcc::context
*ctxt
)
65 : gimple_opt_pass (pass_data_pru_tiabi_check
, ctxt
)
68 /* opt_pass methods: */
69 virtual unsigned int execute (function
*);
71 virtual bool gate (function
*)
73 return pru_current_abi
== PRU_ABI_TI
;
76 }; // class pass_pru_tiabi_check
78 /* Return 1 if type TYPE is a pointer to function type or a
79 structure having a pointer to function type as one of its fields.
80 Otherwise return 0. */
82 chkp_type_has_function_pointer (const_tree type
)
86 if (POINTER_TYPE_P (type
) && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (type
)))
88 else if (RECORD_OR_UNION_TYPE_P (type
))
92 for (field
= TYPE_FIELDS (type
); field
; field
= DECL_CHAIN (field
))
93 if (TREE_CODE (field
) == FIELD_DECL
)
94 res
= res
|| chkp_type_has_function_pointer (TREE_TYPE (field
));
96 else if (TREE_CODE (type
) == ARRAY_TYPE
)
97 res
= chkp_type_has_function_pointer (TREE_TYPE (type
));
102 /* Check the function declaration FNTYPE for TI ABI compatibility. */
104 chk_function_decl (const_tree fntype
, location_t call_location
)
106 /* GCC does not check if the RETURN VALUE pointer is NULL,
107 so do not allow GCC functions with large return values. */
108 if (!VOID_TYPE_P (TREE_TYPE (fntype
))
109 && pru_return_in_memory (TREE_TYPE (fntype
), fntype
))
110 error_at (call_location
,
111 "large return values not supported with %<-mabi=ti%> option");
113 /* Check this function's arguments. */
114 for (tree p
= TYPE_ARG_TYPES (fntype
); p
; p
= TREE_CHAIN (p
))
116 tree arg_type
= TREE_VALUE (p
);
117 if (chkp_type_has_function_pointer (arg_type
))
118 error_at (call_location
,
119 "function pointers not supported with %<-mabi=ti%> option");
123 /* Callback for walk_gimple_seq that checks TP tree for TI ABI compliance. */
125 check_op_callback (tree
*tp
, int *walk_subtrees
, void *data
)
127 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
129 if (RECORD_OR_UNION_TYPE_P (*tp
) || TREE_CODE (*tp
) == ENUMERAL_TYPE
)
131 /* Forward declarations have NULL tree type. Skip them. */
132 if (TREE_TYPE (*tp
) == NULL
)
136 /* TODO - why C++ leaves INTEGER_TYPE forward declarations around? */
137 if (TREE_TYPE (*tp
) == NULL
)
140 const tree type
= TREE_TYPE (*tp
);
142 /* Direct function calls are allowed, obviously. */
143 gcall
*call
= dyn_cast
<gcall
*> (gsi_stmt (wi
->gsi
));
145 && tp
== gimple_call_fn_ptr (call
)
146 && gimple_call_fndecl (call
))
149 switch (TREE_CODE (type
))
154 /* Note: Do not enforce a small return value. It is safe to
155 call any TI ABI function from GCC, since GCC will
158 /* Check arguments for function pointers. */
159 for (tree p
= TYPE_ARG_TYPES (type
); p
; p
= TREE_CHAIN (p
))
161 tree arg_type
= TREE_VALUE (p
);
162 if (chkp_type_has_function_pointer (arg_type
))
163 error_at (gimple_location (wi
->stmt
), "function pointers "
164 "not supported with %<-mabi=ti%> option");
170 case QUAL_UNION_TYPE
:
173 if (chkp_type_has_function_pointer (type
))
175 error_at (gimple_location (wi
->stmt
),
176 "function pointers not supported with "
177 "%<-mabi=ti%> option");
178 *walk_subtrees
= false;
188 /* Pass implementation. */
190 pass_pru_tiabi_check::execute (function
*fun
)
192 struct walk_stmt_info wi
;
193 const_tree fntype
= TREE_TYPE (fun
->decl
);
195 gimple_seq body
= gimple_body (current_function_decl
);
197 memset (&wi
, 0, sizeof (wi
));
199 wi
.want_locations
= true;
201 /* Check the function body. */
202 walk_gimple_seq (body
, NULL
, check_op_callback
, &wi
);
204 /* Check the function declaration. */
205 chk_function_decl (fntype
, fun
->function_start_locus
);
213 make_pru_tiabi_check (gcc::context
*ctxt
)
215 return new pass_pru_tiabi_check (ctxt
);
220 /* Scan the tree to ensure that the compiled code by GCC
221 conforms to the non-standard minimal runtime. */
222 const pass_data pass_data_pru_minrt_check
=
224 GIMPLE_PASS
, /* type */
225 "*pru_minrt_check", /* name */
226 OPTGROUP_NONE
, /* optinfo_flags */
228 PROP_gimple_any
, /* properties_required */
229 0, /* properties_provided */
230 0, /* properties_destroyed */
231 0, /* todo_flags_start */
232 0, /* todo_flags_finish */
235 /* Implementation class for the minrt compliance-check pass. */
236 class pass_pru_minrt_check
: public gimple_opt_pass
239 pass_pru_minrt_check (gcc::context
*ctxt
)
240 : gimple_opt_pass (pass_data_pru_minrt_check
, ctxt
)
243 /* opt_pass methods: */
244 virtual unsigned int execute (function
*);
246 virtual bool gate (function
*)
251 }; // class pass_pru_minrt_check
253 /* Pass implementation. */
255 pass_pru_minrt_check::execute (function
*fun
)
257 const_tree fntype
= TREE_TYPE (fun
->decl
);
259 if (id_equal (DECL_NAME (fun
->decl
), "main"))
261 /* Argument list always ends with VOID_TYPE, so subtract one
262 to get the number of function arguments. */
263 const unsigned num_args
= list_length (TYPE_ARG_TYPES (fntype
)) - 1;
266 error_at (DECL_SOURCE_LOCATION (fun
->decl
), "function %<main%> "
267 "must have no arguments when using the "
268 "%<-minrt%> option");
270 /* The required CFG analysis to detect when a functions would never
271 return is available only with -O1 and higher. */
272 if (optimize
>= 1 && !TREE_THIS_VOLATILE (fun
->decl
))
273 error_at (DECL_SOURCE_LOCATION (fun
->decl
), "function %<main%> "
274 "must never return when using the "
275 "%<-minrt%> option");
283 make_pru_minrt_check (gcc::context
*ctxt
)
285 return new pass_pru_minrt_check (ctxt
);