]>
Commit | Line | Data |
---|---|---|
35485da9 | 1 | /* Implementation of the C API; all wrappers into the internal C++ API |
7adcbafe | 2 | Copyright (C) 2013-2022 Free Software Foundation, Inc. |
35485da9 DM |
3 | Contributed by David Malcolm <dmalcolm@redhat.com>. |
4 | ||
5 | This file is part of GCC. | |
6 | ||
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 by | |
9 | the Free Software Foundation; either version 3, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but | |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | General Public License for more details. | |
16 | ||
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/>. */ | |
20 | ||
21 | #include "config.h" | |
22 | #include "system.h" | |
23 | #include "coretypes.h" | |
2adfab87 | 24 | #include "timevar.h" |
ec5d0088 | 25 | #include "typed-splay-tree.h" |
63b2923d A |
26 | #include "cppbuiltin.h" |
27 | #include <pthread.h> | |
35485da9 DM |
28 | |
29 | #include "libgccjit.h" | |
35485da9 | 30 | #include "jit-recording.h" |
56dea35f | 31 | #include "jit-result.h" |
35485da9 DM |
32 | |
33 | /* The opaque types used by the public API are actually subclasses | |
34 | of the gcc::jit::recording classes. */ | |
35 | ||
36 | struct gcc_jit_context : public gcc::jit::recording::context | |
37 | { | |
38 | gcc_jit_context (gcc_jit_context *parent_ctxt) : | |
39 | context (parent_ctxt) | |
40 | {} | |
41 | }; | |
42 | ||
43 | struct gcc_jit_result : public gcc::jit::result | |
44 | { | |
45 | }; | |
46 | ||
47 | struct gcc_jit_object : public gcc::jit::recording::memento | |
48 | { | |
49 | }; | |
50 | ||
51 | struct gcc_jit_location : public gcc::jit::recording::location | |
52 | { | |
53 | }; | |
54 | ||
55 | struct gcc_jit_type : public gcc::jit::recording::type | |
56 | { | |
57 | }; | |
58 | ||
59 | struct gcc_jit_struct : public gcc::jit::recording::struct_ | |
60 | { | |
61 | }; | |
62 | ||
cfe8dbd9 AB |
63 | struct gcc_jit_function_type : public gcc::jit::recording::function_type |
64 | { | |
65 | }; | |
66 | ||
67 | struct gcc_jit_vector_type : public gcc::jit::recording::vector_type | |
68 | { | |
69 | }; | |
70 | ||
35485da9 DM |
71 | struct gcc_jit_field : public gcc::jit::recording::field |
72 | { | |
73 | }; | |
74 | ||
ee118c14 AC |
75 | struct gcc_jit_bitfield : public gcc::jit::recording::bitfield |
76 | { | |
77 | }; | |
78 | ||
35485da9 DM |
79 | struct gcc_jit_function : public gcc::jit::recording::function |
80 | { | |
81 | }; | |
82 | ||
83 | struct gcc_jit_block : public gcc::jit::recording::block | |
84 | { | |
85 | }; | |
86 | ||
87 | struct gcc_jit_rvalue : public gcc::jit::recording::rvalue | |
88 | { | |
89 | }; | |
90 | ||
91 | struct gcc_jit_lvalue : public gcc::jit::recording::lvalue | |
92 | { | |
93 | }; | |
94 | ||
95 | struct gcc_jit_param : public gcc::jit::recording::param | |
96 | { | |
97 | }; | |
98 | ||
ec5d0088 DM |
99 | struct gcc_jit_case : public gcc::jit::recording::case_ |
100 | { | |
101 | }; | |
102 | ||
afed3459 DM |
103 | struct gcc_jit_timer : public timer |
104 | { | |
105 | }; | |
106 | ||
421d0d0f DM |
107 | struct gcc_jit_extended_asm : public gcc::jit::recording::extended_asm |
108 | { | |
109 | }; | |
110 | ||
111 | ||
35485da9 DM |
112 | /********************************************************************** |
113 | Error-handling. | |
114 | ||
115 | We try to gracefully handle API usage errors by being defensive | |
116 | at the API boundary. | |
117 | **********************************************************************/ | |
118 | ||
119 | #define JIT_BEGIN_STMT do { | |
120 | #define JIT_END_STMT } while(0) | |
121 | ||
122 | /* Each of these error-handling macros determines if TEST_EXPR holds. | |
123 | ||
124 | If TEXT_EXPR fails to hold we return from the enclosing function and | |
125 | print an error, either via adding an error on the given context CTXT | |
126 | if CTXT is non-NULL, falling back to simply printing to stderr if CTXT | |
127 | is NULL. | |
128 | ||
129 | They have to be macros since they inject their "return" into the | |
130 | function they are placed in. | |
131 | ||
132 | The variant macros express: | |
133 | ||
134 | (A) whether or not we need to return a value: | |
135 | RETURN_VAL_IF_FAIL* vs | |
136 | RETURN_IF_FAIL*, | |
137 | with the former returning RETURN_EXPR, and | |
138 | RETURN_NULL_IF_FAIL* | |
139 | for the common case where a NULL value is to be returned on | |
140 | error, and | |
141 | ||
142 | (B) whether the error message is to be directly printed: | |
143 | RETURN_*IF_FAIL | |
144 | or is a format string with some number of arguments: | |
145 | RETURN_*IF_FAIL_PRINTF* | |
146 | ||
147 | They all use JIT_BEGIN_STMT/JIT_END_STMT so they can be written with | |
148 | trailing semicolons. | |
149 | */ | |
150 | ||
151 | #define RETURN_VAL_IF_FAIL(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_MSG) \ | |
152 | JIT_BEGIN_STMT \ | |
153 | if (!(TEST_EXPR)) \ | |
154 | { \ | |
155 | jit_error ((CTXT), (LOC), "%s: %s", __func__, (ERR_MSG)); \ | |
156 | return (RETURN_EXPR); \ | |
157 | } \ | |
158 | JIT_END_STMT | |
159 | ||
160 | #define RETURN_VAL_IF_FAIL_PRINTF1(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0) \ | |
161 | JIT_BEGIN_STMT \ | |
162 | if (!(TEST_EXPR)) \ | |
163 | { \ | |
164 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ | |
165 | __func__, (A0)); \ | |
166 | return (RETURN_EXPR); \ | |
167 | } \ | |
168 | JIT_END_STMT | |
169 | ||
170 | #define RETURN_VAL_IF_FAIL_PRINTF2(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0, A1) \ | |
171 | JIT_BEGIN_STMT \ | |
172 | if (!(TEST_EXPR)) \ | |
173 | { \ | |
174 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ | |
175 | __func__, (A0), (A1)); \ | |
176 | return (RETURN_EXPR); \ | |
177 | } \ | |
178 | JIT_END_STMT | |
179 | ||
180 | #define RETURN_VAL_IF_FAIL_PRINTF3(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2) \ | |
181 | JIT_BEGIN_STMT \ | |
182 | if (!(TEST_EXPR)) \ | |
183 | { \ | |
184 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ | |
185 | __func__, (A0), (A1), (A2)); \ | |
186 | return (RETURN_EXPR); \ | |
187 | } \ | |
188 | JIT_END_STMT | |
189 | ||
190 | #define RETURN_VAL_IF_FAIL_PRINTF4(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3) \ | |
191 | JIT_BEGIN_STMT \ | |
192 | if (!(TEST_EXPR)) \ | |
193 | { \ | |
194 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ | |
195 | __func__, (A0), (A1), (A2), (A3)); \ | |
196 | return (RETURN_EXPR); \ | |
197 | } \ | |
198 | JIT_END_STMT | |
199 | ||
f6f2b019 DM |
200 | #define RETURN_VAL_IF_FAIL_PRINTF5(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4) \ |
201 | JIT_BEGIN_STMT \ | |
202 | if (!(TEST_EXPR)) \ | |
203 | { \ | |
204 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ | |
205 | __func__, (A0), (A1), (A2), (A3), (A4)); \ | |
206 | return (RETURN_EXPR); \ | |
207 | } \ | |
208 | JIT_END_STMT | |
209 | ||
35485da9 DM |
210 | #define RETURN_VAL_IF_FAIL_PRINTF6(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4, A5) \ |
211 | JIT_BEGIN_STMT \ | |
212 | if (!(TEST_EXPR)) \ | |
213 | { \ | |
214 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ | |
215 | __func__, (A0), (A1), (A2), (A3), (A4), (A5)); \ | |
216 | return (RETURN_EXPR); \ | |
217 | } \ | |
218 | JIT_END_STMT | |
219 | ||
220 | #define RETURN_NULL_IF_FAIL(TEST_EXPR, CTXT, LOC, ERR_MSG) \ | |
221 | RETURN_VAL_IF_FAIL ((TEST_EXPR), NULL, (CTXT), (LOC), (ERR_MSG)) | |
222 | ||
223 | #define RETURN_NULL_IF_FAIL_PRINTF1(TEST_EXPR, CTXT, LOC, ERR_FMT, A0) \ | |
224 | RETURN_VAL_IF_FAIL_PRINTF1 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0) | |
225 | ||
226 | #define RETURN_NULL_IF_FAIL_PRINTF2(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1) \ | |
227 | RETURN_VAL_IF_FAIL_PRINTF2 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1) | |
228 | ||
229 | #define RETURN_NULL_IF_FAIL_PRINTF3(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2) \ | |
230 | RETURN_VAL_IF_FAIL_PRINTF3 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2) | |
231 | ||
232 | #define RETURN_NULL_IF_FAIL_PRINTF4(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3) \ | |
233 | RETURN_VAL_IF_FAIL_PRINTF4 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2, A3) | |
234 | ||
f6f2b019 DM |
235 | #define RETURN_NULL_IF_FAIL_PRINTF5(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4) \ |
236 | RETURN_VAL_IF_FAIL_PRINTF5 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4) | |
237 | ||
35485da9 DM |
238 | #define RETURN_NULL_IF_FAIL_PRINTF6(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4, A5) \ |
239 | RETURN_VAL_IF_FAIL_PRINTF6 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4, A5) | |
240 | ||
241 | #define RETURN_IF_FAIL(TEST_EXPR, CTXT, LOC, ERR_MSG) \ | |
242 | JIT_BEGIN_STMT \ | |
243 | if (!(TEST_EXPR)) \ | |
244 | { \ | |
245 | jit_error ((CTXT), (LOC), "%s: %s", __func__, (ERR_MSG)); \ | |
246 | return; \ | |
247 | } \ | |
248 | JIT_END_STMT | |
249 | ||
250 | #define RETURN_IF_FAIL_PRINTF1(TEST_EXPR, CTXT, LOC, ERR_FMT, A0) \ | |
251 | JIT_BEGIN_STMT \ | |
252 | if (!(TEST_EXPR)) \ | |
253 | { \ | |
254 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ | |
255 | __func__, (A0)); \ | |
256 | return; \ | |
257 | } \ | |
258 | JIT_END_STMT | |
259 | ||
260 | #define RETURN_IF_FAIL_PRINTF2(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1) \ | |
261 | JIT_BEGIN_STMT \ | |
262 | if (!(TEST_EXPR)) \ | |
263 | { \ | |
264 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ | |
265 | __func__, (A0), (A1)); \ | |
266 | return; \ | |
267 | } \ | |
268 | JIT_END_STMT | |
269 | ||
270 | #define RETURN_IF_FAIL_PRINTF4(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3) \ | |
271 | JIT_BEGIN_STMT \ | |
272 | if (!(TEST_EXPR)) \ | |
273 | { \ | |
274 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ | |
275 | __func__, (A0), (A1), (A2), (A3)); \ | |
276 | return; \ | |
277 | } \ | |
278 | JIT_END_STMT | |
279 | ||
280 | /* Check that BLOCK is non-NULL, and that it's OK to add statements to | |
281 | it. This will fail if BLOCK has already been terminated by some | |
282 | kind of jump or a return. */ | |
283 | #define RETURN_IF_NOT_VALID_BLOCK(BLOCK, LOC) \ | |
284 | JIT_BEGIN_STMT \ | |
285 | RETURN_IF_FAIL ((BLOCK), NULL, (LOC), "NULL block"); \ | |
286 | RETURN_IF_FAIL_PRINTF2 ( \ | |
287 | !(BLOCK)->has_been_terminated (), \ | |
288 | (BLOCK)->get_context (), \ | |
289 | (LOC), \ | |
290 | "adding to terminated block: %s (already terminated by: %s)", \ | |
291 | (BLOCK)->get_debug_string (), \ | |
292 | (BLOCK)->get_last_statement ()->get_debug_string ()); \ | |
293 | JIT_END_STMT | |
294 | ||
295 | /* As RETURN_IF_NOT_VALID_BLOCK, but injecting a "return NULL;" if it | |
296 | fails. */ | |
297 | #define RETURN_NULL_IF_NOT_VALID_BLOCK(BLOCK, LOC) \ | |
298 | JIT_BEGIN_STMT \ | |
299 | RETURN_NULL_IF_FAIL ((BLOCK), NULL, (LOC), "NULL block"); \ | |
300 | RETURN_NULL_IF_FAIL_PRINTF2 ( \ | |
301 | !(BLOCK)->has_been_terminated (), \ | |
302 | (BLOCK)->get_context (), \ | |
303 | (LOC), \ | |
304 | "adding to terminated block: %s (already terminated by: %s)", \ | |
305 | (BLOCK)->get_debug_string (), \ | |
306 | (BLOCK)->get_last_statement ()->get_debug_string ()); \ | |
307 | JIT_END_STMT | |
308 | ||
309 | /* Format the given string, and report it as an error, either on CTXT | |
310 | if non-NULL, or by printing to stderr if we have a NULL context. | |
311 | LOC gives the source location where the error occcurred, and can be | |
312 | NULL. */ | |
313 | ||
314 | static void | |
315 | jit_error (gcc::jit::recording::context *ctxt, | |
421d0d0f | 316 | gcc::jit::recording::location *loc, |
35485da9 DM |
317 | const char *fmt, ...) |
318 | GNU_PRINTF(3, 4); | |
319 | ||
320 | static void | |
321 | jit_error (gcc::jit::recording::context *ctxt, | |
421d0d0f | 322 | gcc::jit::recording::location *loc, |
35485da9 DM |
323 | const char *fmt, ...) |
324 | { | |
325 | va_list ap; | |
326 | va_start (ap, fmt); | |
327 | ||
328 | if (ctxt) | |
329 | ctxt->add_error_va (loc, fmt, ap); | |
330 | else | |
331 | { | |
332 | /* No context? Send to stderr. */ | |
333 | vfprintf (stderr, fmt, ap); | |
334 | fprintf (stderr, "\n"); | |
335 | } | |
336 | ||
337 | va_end (ap); | |
338 | } | |
339 | ||
340 | /* Determine whether or not we can write to lvalues of type LTYPE from | |
341 | rvalues of type RTYPE, detecting type errors such as attempting to | |
342 | write to an int with a string literal (without an explicit cast). | |
343 | ||
344 | This is implemented by calling the | |
345 | gcc::jit::recording::type::accepts_writes_from virtual function on | |
346 | LTYPE. */ | |
347 | ||
348 | static bool | |
349 | compatible_types (gcc::jit::recording::type *ltype, | |
350 | gcc::jit::recording::type *rtype) | |
351 | { | |
352 | return ltype->accepts_writes_from (rtype); | |
353 | } | |
354 | ||
355 | /* Public entrypoint for acquiring a gcc_jit_context. | |
356 | Note that this creates a new top-level context; contrast with | |
357 | gcc_jit_context_new_child_context below. | |
358 | ||
359 | The real work is done in the constructor for | |
e53b6e56 | 360 | gcc::jit::recording::context in jit-recording.cc. */ |
35485da9 DM |
361 | |
362 | gcc_jit_context * | |
363 | gcc_jit_context_acquire (void) | |
364 | { | |
eb4c16eb DM |
365 | gcc_jit_context *ctxt = new gcc_jit_context (NULL); |
366 | ctxt->log ("new top-level ctxt: %p", (void *)ctxt); | |
367 | return ctxt; | |
35485da9 DM |
368 | } |
369 | ||
370 | /* Public entrypoint for releasing a gcc_jit_context. | |
371 | The real work is done in the destructor for | |
e53b6e56 | 372 | gcc::jit::recording::context in jit-recording.cc. */ |
35485da9 DM |
373 | |
374 | void | |
375 | gcc_jit_context_release (gcc_jit_context *ctxt) | |
376 | { | |
eb4c16eb DM |
377 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL ctxt"); |
378 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
379 | ctxt->log ("deleting ctxt: %p", (void *)ctxt); | |
35485da9 DM |
380 | delete ctxt; |
381 | } | |
382 | ||
383 | /* Public entrypoint for creating a child context within | |
384 | PARENT_CTXT. See description in libgccjit.h. | |
385 | ||
386 | The real work is done in the constructor for | |
e53b6e56 | 387 | gcc::jit::recording::context in jit-recording.cc. */ |
35485da9 DM |
388 | |
389 | gcc_jit_context * | |
390 | gcc_jit_context_new_child_context (gcc_jit_context *parent_ctxt) | |
391 | { | |
eb4c16eb DM |
392 | RETURN_NULL_IF_FAIL (parent_ctxt, NULL, NULL, "NULL parent ctxt"); |
393 | JIT_LOG_FUNC (parent_ctxt->get_logger ()); | |
394 | parent_ctxt->log ("parent_ctxt: %p", (void *)parent_ctxt); | |
395 | gcc_jit_context *child_ctxt = new gcc_jit_context (parent_ctxt); | |
396 | child_ctxt->log ("new child_ctxt: %p", (void *)child_ctxt); | |
397 | return child_ctxt; | |
35485da9 DM |
398 | } |
399 | ||
400 | /* Public entrypoint. See description in libgccjit.h. | |
401 | ||
402 | After error-checking, the real work is done by the | |
403 | gcc::jit::recording::context::new_location | |
e53b6e56 | 404 | method in jit-recording.cc. */ |
35485da9 DM |
405 | |
406 | gcc_jit_location * | |
407 | gcc_jit_context_new_location (gcc_jit_context *ctxt, | |
408 | const char *filename, | |
409 | int line, | |
410 | int column) | |
411 | { | |
412 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 413 | JIT_LOG_FUNC (ctxt->get_logger ()); |
86d0ac88 | 414 | return (gcc_jit_location *)ctxt->new_location (filename, line, column, true); |
35485da9 DM |
415 | } |
416 | ||
417 | /* Public entrypoint. See description in libgccjit.h. | |
418 | ||
419 | After error-checking, this calls the trivial | |
420 | gcc::jit::recording::memento::as_object method (a location is a | |
421 | memento), in jit-recording.h. */ | |
422 | ||
423 | gcc_jit_object * | |
424 | gcc_jit_location_as_object (gcc_jit_location *loc) | |
425 | { | |
426 | RETURN_NULL_IF_FAIL (loc, NULL, NULL, "NULL location"); | |
427 | ||
428 | return static_cast <gcc_jit_object *> (loc->as_object ()); | |
429 | } | |
430 | ||
431 | /* Public entrypoint. See description in libgccjit.h. | |
432 | ||
433 | After error-checking, this calls the trivial | |
434 | gcc::jit::recording::memento::as_object method (a type is a | |
435 | memento), in jit-recording.h. */ | |
436 | ||
437 | gcc_jit_object * | |
438 | gcc_jit_type_as_object (gcc_jit_type *type) | |
439 | { | |
440 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); | |
441 | ||
442 | return static_cast <gcc_jit_object *> (type->as_object ()); | |
443 | } | |
444 | ||
445 | /* Public entrypoint for getting a specific type from a context. | |
446 | ||
447 | After error-checking, the real work is done by the | |
448 | gcc::jit::recording::context::get_type method, in | |
e53b6e56 | 449 | jit-recording.cc */ |
35485da9 DM |
450 | |
451 | gcc_jit_type * | |
452 | gcc_jit_context_get_type (gcc_jit_context *ctxt, | |
453 | enum gcc_jit_types type) | |
454 | { | |
455 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 456 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
457 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
458 | (type >= GCC_JIT_TYPE_VOID | |
459 | && type <= GCC_JIT_TYPE_FILE_PTR), | |
460 | ctxt, NULL, | |
461 | "unrecognized value for enum gcc_jit_types: %i", type); | |
462 | ||
463 | return (gcc_jit_type *)ctxt->get_type (type); | |
464 | } | |
465 | ||
466 | /* Public entrypoint for getting the integer type of the given size and | |
467 | signedness. | |
468 | ||
469 | After error-checking, the real work is done by the | |
470 | gcc::jit::recording::context::get_int_type method, | |
e53b6e56 | 471 | in jit-recording.cc. */ |
35485da9 DM |
472 | |
473 | gcc_jit_type * | |
474 | gcc_jit_context_get_int_type (gcc_jit_context *ctxt, | |
475 | int num_bytes, int is_signed) | |
476 | { | |
477 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 478 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
479 | RETURN_NULL_IF_FAIL (num_bytes >= 0, ctxt, NULL, "negative size"); |
480 | ||
481 | return (gcc_jit_type *)ctxt->get_int_type (num_bytes, is_signed); | |
482 | } | |
483 | ||
484 | /* Public entrypoint. See description in libgccjit.h. | |
485 | ||
486 | After error-checking, the real work is done by the | |
487 | gcc::jit::recording::type::get_pointer method, in | |
e53b6e56 | 488 | jit-recording.cc */ |
35485da9 DM |
489 | |
490 | gcc_jit_type * | |
491 | gcc_jit_type_get_pointer (gcc_jit_type *type) | |
492 | { | |
493 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); | |
494 | ||
495 | return (gcc_jit_type *)type->get_pointer (); | |
496 | } | |
497 | ||
498 | /* Public entrypoint. See description in libgccjit.h. | |
499 | ||
500 | After error-checking, the real work is done by the | |
501 | gcc::jit::recording::type::get_const method, in | |
e53b6e56 | 502 | jit-recording.cc. */ |
35485da9 DM |
503 | |
504 | gcc_jit_type * | |
505 | gcc_jit_type_get_const (gcc_jit_type *type) | |
506 | { | |
507 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); | |
508 | ||
509 | return (gcc_jit_type *)type->get_const (); | |
510 | } | |
511 | ||
512 | /* Public entrypoint. See description in libgccjit.h. | |
513 | ||
514 | After error-checking, the real work is done by the | |
515 | gcc::jit::recording::type::get_volatile method, in | |
e53b6e56 | 516 | jit-recording.cc. */ |
35485da9 DM |
517 | |
518 | gcc_jit_type * | |
519 | gcc_jit_type_get_volatile (gcc_jit_type *type) | |
520 | { | |
521 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); | |
522 | ||
523 | return (gcc_jit_type *)type->get_volatile (); | |
524 | } | |
525 | ||
cfe8dbd9 AB |
526 | /* Public entrypoint. See description in libgccjit.h. |
527 | ||
528 | After error-checking, the real work is done by the | |
529 | gcc::jit::recording::type::is_array method, in | |
e53b6e56 | 530 | jit-recording.cc. */ |
cfe8dbd9 AB |
531 | |
532 | gcc_jit_type * | |
533 | gcc_jit_type_dyncast_array (gcc_jit_type *type) | |
534 | { | |
535 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); | |
536 | ||
537 | return (gcc_jit_type *)type->is_array (); | |
538 | } | |
539 | ||
540 | /* Public entrypoint. See description in libgccjit.h. | |
541 | ||
542 | After error-checking, the real work is done by the | |
543 | gcc::jit::recording::type::is_bool method, in | |
e53b6e56 | 544 | jit-recording.cc. */ |
cfe8dbd9 AB |
545 | |
546 | int | |
547 | gcc_jit_type_is_bool (gcc_jit_type *type) | |
548 | { | |
549 | RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type"); | |
550 | ||
551 | return type->is_bool (); | |
552 | } | |
553 | ||
554 | /* Public entrypoint. See description in libgccjit.h. | |
555 | ||
556 | After error-checking, the real work is done by the | |
557 | gcc::jit::recording::type::is_pointer method, in | |
e53b6e56 | 558 | jit-recording.cc. */ |
cfe8dbd9 AB |
559 | |
560 | gcc_jit_type * | |
561 | gcc_jit_type_is_pointer (gcc_jit_type *type) | |
562 | { | |
563 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); | |
564 | ||
565 | return (gcc_jit_type *)type->is_pointer (); | |
566 | } | |
567 | ||
568 | /* Public entrypoint. See description in libgccjit.h. | |
569 | ||
570 | After error-checking, the real work is done by the | |
571 | gcc::jit::recording::type::is_int method, in | |
e53b6e56 | 572 | jit-recording.cc. */ |
cfe8dbd9 AB |
573 | |
574 | int | |
575 | gcc_jit_type_is_integral (gcc_jit_type *type) | |
576 | { | |
577 | RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type"); | |
578 | ||
579 | return type->is_int (); | |
580 | } | |
581 | ||
582 | /* Public entrypoint. See description in libgccjit.h. | |
583 | ||
584 | After error-checking, the real work is done by the | |
585 | gcc::jit::recording::type::is_vector method, in | |
e53b6e56 | 586 | jit-recording.cc. */ |
cfe8dbd9 AB |
587 | |
588 | gcc_jit_vector_type * | |
589 | gcc_jit_type_dyncast_vector (gcc_jit_type *type) | |
590 | { | |
591 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); | |
592 | gcc::jit::recording::vector_type *vector_type = type->is_vector (); | |
593 | return (gcc_jit_vector_type *)vector_type; | |
594 | } | |
595 | ||
596 | /* Public entrypoint. See description in libgccjit.h. | |
597 | ||
598 | After error-checking, the real work is done by the | |
599 | gcc::jit::recording::type::is_struct method, in | |
e53b6e56 | 600 | jit-recording.cc. */ |
cfe8dbd9 AB |
601 | |
602 | gcc_jit_struct * | |
603 | gcc_jit_type_is_struct (gcc_jit_type *type) | |
604 | { | |
605 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); | |
606 | gcc::jit::recording::struct_ *struct_type = type->is_struct (); | |
607 | return (gcc_jit_struct *)struct_type; | |
608 | } | |
609 | ||
610 | /* Public entrypoint. See description in libgccjit.h. | |
611 | ||
612 | After error-checking, the real work is done by the | |
613 | gcc::jit::recording::vector_type::get_num_units method, in | |
e53b6e56 | 614 | jit-recording.cc. */ |
cfe8dbd9 AB |
615 | |
616 | size_t | |
617 | gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type) | |
618 | { | |
619 | RETURN_VAL_IF_FAIL (vector_type, 0, NULL, NULL, "NULL vector_type"); | |
620 | return vector_type->get_num_units (); | |
621 | } | |
622 | ||
623 | /* Public entrypoint. See description in libgccjit.h. | |
624 | ||
625 | After error-checking, the real work is done by the | |
626 | gcc::jit::recording::vector_type::get_element_type method, in | |
e53b6e56 | 627 | jit-recording.cc. */ |
cfe8dbd9 AB |
628 | |
629 | gcc_jit_type * | |
630 | gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type) | |
631 | { | |
632 | RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type"); | |
633 | return (gcc_jit_type *)vector_type->get_element_type (); | |
634 | } | |
635 | ||
636 | /* Public entrypoint. See description in libgccjit.h. | |
637 | ||
638 | After error-checking, the real work is done by the | |
639 | gcc::jit::recording::type::unqualified method, in | |
e53b6e56 | 640 | jit-recording.cc. */ |
cfe8dbd9 AB |
641 | |
642 | gcc_jit_type * | |
643 | gcc_jit_type_unqualified (gcc_jit_type *type) | |
644 | { | |
645 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); | |
646 | ||
647 | return (gcc_jit_type *)type->unqualified (); | |
648 | } | |
649 | ||
650 | /* Public entrypoint. See description in libgccjit.h. | |
651 | ||
652 | After error-checking, the real work is done by the | |
653 | gcc::jit::recording::type::dyn_cast_function_type method, in | |
e53b6e56 | 654 | jit-recording.cc. */ |
cfe8dbd9 AB |
655 | |
656 | gcc_jit_function_type * | |
657 | gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type) | |
658 | { | |
659 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); | |
660 | gcc::jit::recording::type *func_ptr_type = type->dereference (); | |
661 | if (!func_ptr_type) | |
662 | { | |
663 | return NULL; | |
664 | } | |
665 | ||
666 | return (gcc_jit_function_type *)func_ptr_type->dyn_cast_function_type (); | |
667 | } | |
668 | ||
669 | /* Public entrypoint. See description in libgccjit.h. | |
670 | ||
671 | After error-checking, the real work is done by the | |
672 | gcc::jit::recording::function_type::get_return_type method, in | |
e53b6e56 | 673 | jit-recording.cc. */ |
cfe8dbd9 AB |
674 | |
675 | gcc_jit_type * | |
676 | gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type) | |
677 | { | |
678 | RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type"); | |
679 | return (gcc_jit_type *)function_type->get_return_type (); | |
680 | } | |
681 | ||
682 | /* Public entrypoint. See description in libgccjit.h. | |
683 | ||
684 | After error-checking, the real work is done by the | |
685 | gcc::jit::recording::function_type::get_param_types method, in | |
e53b6e56 | 686 | jit-recording.cc. */ |
cfe8dbd9 AB |
687 | |
688 | size_t | |
689 | gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type) | |
690 | { | |
691 | RETURN_VAL_IF_FAIL (function_type, 0, NULL, NULL, "NULL function_type"); | |
692 | return function_type->get_param_types ().length (); | |
693 | } | |
694 | ||
695 | /* Public entrypoint. See description in libgccjit.h. | |
696 | ||
697 | After error-checking, the real work is done by the | |
698 | gcc::jit::recording::function_type::get_param_types method, in | |
e53b6e56 | 699 | jit-recording.cc. */ |
cfe8dbd9 AB |
700 | |
701 | gcc_jit_type * | |
702 | gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type, | |
703 | size_t index) | |
704 | { | |
705 | RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type"); | |
706 | size_t num_params = function_type->get_param_types ().length (); | |
707 | gcc::jit::recording::context *ctxt = function_type->m_ctxt; | |
708 | RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params, | |
709 | ctxt, NULL, | |
1e534084 | 710 | "index of %zu is too large (%s has %zu params)", |
cfe8dbd9 AB |
711 | index, |
712 | function_type->get_debug_string (), | |
713 | num_params); | |
714 | return (gcc_jit_type *)function_type->get_param_types ()[index]; | |
715 | } | |
716 | ||
35485da9 DM |
717 | /* Public entrypoint. See description in libgccjit.h. |
718 | ||
719 | After error-checking, the real work is done by the | |
720 | gcc::jit::recording::context::new_array_type method, in | |
e53b6e56 | 721 | jit-recording.cc. */ |
35485da9 DM |
722 | |
723 | gcc_jit_type * | |
724 | gcc_jit_context_new_array_type (gcc_jit_context *ctxt, | |
725 | gcc_jit_location *loc, | |
726 | gcc_jit_type *element_type, | |
727 | int num_elements) | |
728 | { | |
729 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 730 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
731 | /* LOC can be NULL. */ |
732 | RETURN_NULL_IF_FAIL (element_type, ctxt, loc, "NULL type"); | |
733 | RETURN_NULL_IF_FAIL (num_elements >= 0, ctxt, NULL, "negative size"); | |
6f7585de DM |
734 | RETURN_NULL_IF_FAIL (!element_type->is_void (), ctxt, loc, |
735 | "void type for elements"); | |
35485da9 DM |
736 | |
737 | return (gcc_jit_type *)ctxt->new_array_type (loc, | |
738 | element_type, | |
739 | num_elements); | |
740 | } | |
741 | ||
742 | /* Public entrypoint. See description in libgccjit.h. | |
743 | ||
744 | After error-checking, the real work is done by the | |
745 | gcc::jit::recording::context::new_field method, in | |
e53b6e56 | 746 | jit-recording.cc. */ |
35485da9 DM |
747 | |
748 | gcc_jit_field * | |
749 | gcc_jit_context_new_field (gcc_jit_context *ctxt, | |
750 | gcc_jit_location *loc, | |
751 | gcc_jit_type *type, | |
752 | const char *name) | |
753 | { | |
754 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 755 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
756 | /* LOC can be NULL. */ |
757 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); | |
758 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); | |
58c5ad40 | 759 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
3457d39e DM |
760 | type->has_known_size (), |
761 | ctxt, loc, | |
58c5ad40 DM |
762 | "unknown size for field \"%s\" (type: %s)", |
763 | name, | |
3457d39e | 764 | type->get_debug_string ()); |
6f7585de DM |
765 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
766 | !type->is_void (), | |
767 | ctxt, loc, | |
768 | "void type for field \"%s\"", | |
769 | name); | |
35485da9 DM |
770 | |
771 | return (gcc_jit_field *)ctxt->new_field (loc, type, name); | |
772 | } | |
773 | ||
ee118c14 AC |
774 | /* Public entrypoint. See description in libgccjit.h. |
775 | ||
776 | After error-checking, the real work is done by the | |
777 | gcc::jit::recording::context::new_bitfield method, in | |
e53b6e56 | 778 | jit-recording.cc. */ |
ee118c14 AC |
779 | |
780 | gcc_jit_field * | |
781 | gcc_jit_context_new_bitfield (gcc_jit_context *ctxt, | |
782 | gcc_jit_location *loc, | |
783 | gcc_jit_type *type, | |
784 | int width, | |
785 | const char *name) | |
786 | { | |
787 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
788 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
789 | /* LOC can be NULL. */ | |
790 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); | |
791 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); | |
792 | RETURN_NULL_IF_FAIL_PRINTF2 (type->is_int () || type->is_bool (), | |
793 | ctxt, loc, | |
794 | "bit-field %s has non integral type %s", | |
795 | name, type->get_debug_string ()); | |
796 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
797 | width > 0, ctxt, loc, | |
798 | "invalid width %d for bitfield \"%s\" (must be > 0)", | |
799 | width, name); | |
800 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
801 | type->has_known_size (), | |
802 | ctxt, loc, | |
803 | "unknown size for field \"%s\" (type: %s)", | |
804 | name, | |
805 | type->get_debug_string ()); | |
806 | ||
807 | return (gcc_jit_field *)ctxt->new_bitfield (loc, type, width, name); | |
808 | } | |
809 | ||
35485da9 DM |
810 | /* Public entrypoint. See description in libgccjit.h. |
811 | ||
812 | After error-checking, this calls the trivial | |
813 | gcc::jit::recording::memento::as_object method (a field is a | |
814 | memento), in jit-recording.h. */ | |
815 | ||
816 | gcc_jit_object * | |
817 | gcc_jit_field_as_object (gcc_jit_field *field) | |
818 | { | |
819 | RETURN_NULL_IF_FAIL (field, NULL, NULL, "NULL field"); | |
820 | ||
821 | return static_cast <gcc_jit_object *> (field->as_object ()); | |
822 | } | |
823 | ||
824 | /* Public entrypoint. See description in libgccjit.h. | |
825 | ||
826 | After error-checking, the real work is done by the | |
827 | gcc::jit::recording::context::new_struct_type method, | |
828 | immediately followed by a "set_fields" call on the resulting | |
e53b6e56 | 829 | gcc::jit::recording::compound_type *, both in jit-recording.cc */ |
35485da9 DM |
830 | |
831 | gcc_jit_struct * | |
832 | gcc_jit_context_new_struct_type (gcc_jit_context *ctxt, | |
833 | gcc_jit_location *loc, | |
834 | const char *name, | |
835 | int num_fields, | |
836 | gcc_jit_field **fields) | |
837 | { | |
838 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 839 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
840 | /* LOC can be NULL. */ |
841 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); | |
842 | if (num_fields) | |
843 | RETURN_NULL_IF_FAIL (fields, ctxt, loc, "NULL fields ptr"); | |
844 | for (int i = 0; i < num_fields; i++) | |
845 | { | |
846 | RETURN_NULL_IF_FAIL (fields[i], ctxt, loc, "NULL field ptr"); | |
847 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
01512446 | 848 | fields[i]->get_container () == NULL, |
35485da9 DM |
849 | ctxt, loc, |
850 | "%s is already a field of %s", | |
851 | fields[i]->get_debug_string (), | |
852 | fields[i]->get_container ()->get_debug_string ()); | |
853 | } | |
854 | ||
855 | gcc::jit::recording::struct_ *result = | |
856 | ctxt->new_struct_type (loc, name); | |
857 | result->set_fields (loc, | |
858 | num_fields, | |
859 | (gcc::jit::recording::field **)fields); | |
860 | return static_cast<gcc_jit_struct *> (result); | |
861 | } | |
862 | ||
863 | /* Public entrypoint. See description in libgccjit.h. | |
864 | ||
865 | After error-checking, the real work is done by the | |
866 | gcc::jit::recording::context::new_struct_type method in | |
e53b6e56 | 867 | jit-recording.cc. */ |
35485da9 DM |
868 | |
869 | gcc_jit_struct * | |
870 | gcc_jit_context_new_opaque_struct (gcc_jit_context *ctxt, | |
871 | gcc_jit_location *loc, | |
872 | const char *name) | |
873 | { | |
874 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 875 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
876 | /* LOC can be NULL. */ |
877 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); | |
878 | ||
879 | return (gcc_jit_struct *)ctxt->new_struct_type (loc, name); | |
880 | } | |
881 | ||
882 | /* Public entrypoint. See description in libgccjit.h. | |
883 | ||
884 | After error-checking, this calls the trivial | |
885 | gcc::jit::recording::struct_::as_object method in | |
886 | jit-recording.h. */ | |
887 | ||
888 | gcc_jit_type * | |
889 | gcc_jit_struct_as_type (gcc_jit_struct *struct_type) | |
890 | { | |
891 | RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct_type"); | |
892 | ||
893 | return static_cast <gcc_jit_type *> (struct_type->as_type ()); | |
894 | } | |
895 | ||
896 | /* Public entrypoint. See description in libgccjit.h. | |
897 | ||
898 | After error-checking, the real work is done by the | |
899 | gcc::jit::recording::compound_type::set_fields method in | |
e53b6e56 | 900 | jit-recording.cc. */ |
35485da9 DM |
901 | |
902 | void | |
903 | gcc_jit_struct_set_fields (gcc_jit_struct *struct_type, | |
904 | gcc_jit_location *loc, | |
905 | int num_fields, | |
906 | gcc_jit_field **fields) | |
907 | { | |
908 | RETURN_IF_FAIL (struct_type, NULL, loc, "NULL struct_type"); | |
35485da9 | 909 | gcc::jit::recording::context *ctxt = struct_type->m_ctxt; |
eb4c16eb DM |
910 | JIT_LOG_FUNC (ctxt->get_logger ()); |
911 | /* LOC can be NULL. */ | |
35485da9 | 912 | RETURN_IF_FAIL_PRINTF1 ( |
01512446 | 913 | struct_type->get_fields () == NULL, ctxt, loc, |
35485da9 DM |
914 | "%s already has had fields set", |
915 | struct_type->get_debug_string ()); | |
916 | if (num_fields) | |
917 | RETURN_IF_FAIL (fields, ctxt, loc, "NULL fields ptr"); | |
918 | for (int i = 0; i < num_fields; i++) | |
919 | { | |
58c5ad40 DM |
920 | RETURN_IF_FAIL_PRINTF2 ( |
921 | fields[i], | |
922 | ctxt, loc, | |
923 | "%s: NULL field ptr at index %i", | |
924 | struct_type->get_debug_string (), | |
925 | i); | |
35485da9 | 926 | RETURN_IF_FAIL_PRINTF2 ( |
01512446 | 927 | fields[i]->get_container () == NULL, |
35485da9 DM |
928 | ctxt, loc, |
929 | "%s is already a field of %s", | |
930 | fields[i]->get_debug_string (), | |
931 | fields[i]->get_container ()->get_debug_string ()); | |
932 | } | |
933 | ||
934 | struct_type->set_fields (loc, num_fields, | |
935 | (gcc::jit::recording::field **)fields); | |
936 | } | |
937 | ||
cfe8dbd9 AB |
938 | |
939 | /* Public entrypoint. See description in libgccjit.h. | |
940 | ||
941 | After error-checking, the real work is done by the | |
942 | gcc::jit::recording::fields::get_field method in | |
e53b6e56 | 943 | jit-recording.cc. */ |
cfe8dbd9 AB |
944 | extern gcc_jit_field * |
945 | gcc_jit_struct_get_field (gcc_jit_struct *struct_type, | |
946 | size_t index) | |
947 | { | |
948 | RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type"); | |
949 | RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL, | |
950 | "NULL struct fields"); | |
951 | size_t num_fields = struct_type->get_fields ()->length (); | |
952 | RETURN_NULL_IF_FAIL_PRINTF3 (index < num_fields, | |
953 | NULL, NULL, | |
1e534084 | 954 | "index of %zu is too large (%s has %zu fields)", |
cfe8dbd9 AB |
955 | index, |
956 | struct_type->get_debug_string (), | |
957 | num_fields); | |
958 | return (gcc_jit_field *)struct_type->get_fields ()->get_field (index); | |
959 | } | |
960 | ||
961 | /* Public entrypoint. See description in libgccjit.h. | |
962 | ||
963 | After error-checking, this calls the trivial | |
964 | gcc::jit::recording::struct_::get_fields method in | |
965 | jit-recording.h. */ | |
966 | ||
967 | size_t | |
968 | gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type) | |
969 | { | |
970 | RETURN_VAL_IF_FAIL (struct_type, 0, NULL, NULL, "NULL struct type"); | |
971 | return struct_type->get_fields ()->length (); | |
972 | } | |
973 | ||
35485da9 DM |
974 | /* Public entrypoint. See description in libgccjit.h. |
975 | ||
976 | After error-checking, the real work is done by the | |
977 | gcc::jit::recording::context::new_union_type method, | |
978 | immediately followed by a "set_fields" call on the resulting | |
e53b6e56 | 979 | gcc::jit::recording::compound_type *, both in jit-recording.cc */ |
35485da9 DM |
980 | |
981 | gcc_jit_type * | |
982 | gcc_jit_context_new_union_type (gcc_jit_context *ctxt, | |
983 | gcc_jit_location *loc, | |
984 | const char *name, | |
985 | int num_fields, | |
986 | gcc_jit_field **fields) | |
987 | { | |
988 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 989 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
990 | /* LOC can be NULL. */ |
991 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); | |
992 | if (num_fields) | |
993 | RETURN_NULL_IF_FAIL (fields, ctxt, loc, "NULL fields ptr"); | |
994 | for (int i = 0; i < num_fields; i++) | |
995 | { | |
996 | RETURN_NULL_IF_FAIL (fields[i], ctxt, loc, "NULL field ptr"); | |
997 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
01512446 | 998 | fields[i]->get_container () == NULL, |
35485da9 DM |
999 | ctxt, loc, |
1000 | "%s is already a field of %s", | |
1001 | fields[i]->get_debug_string (), | |
1002 | fields[i]->get_container ()->get_debug_string ()); | |
1003 | } | |
1004 | ||
1005 | gcc::jit::recording::union_ *result = | |
1006 | ctxt->new_union_type (loc, name); | |
1007 | result->set_fields (loc, | |
1008 | num_fields, | |
1009 | (gcc::jit::recording::field **)fields); | |
1010 | return (gcc_jit_type *) (result); | |
1011 | } | |
1012 | ||
1013 | /* Public entrypoint. See description in libgccjit.h. | |
1014 | ||
1015 | After error-checking, the real work is done by the | |
1016 | gcc::jit::recording::context::new_function_ptr_type method, | |
e53b6e56 | 1017 | in jit-recording.cc */ |
35485da9 DM |
1018 | |
1019 | gcc_jit_type * | |
1020 | gcc_jit_context_new_function_ptr_type (gcc_jit_context *ctxt, | |
1021 | gcc_jit_location *loc, | |
1022 | gcc_jit_type *return_type, | |
1023 | int num_params, | |
1024 | gcc_jit_type **param_types, | |
1025 | int is_variadic) | |
1026 | { | |
1027 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 1028 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
1029 | /* LOC can be NULL. */ |
1030 | RETURN_NULL_IF_FAIL (return_type, ctxt, loc, "NULL return_type"); | |
1031 | RETURN_NULL_IF_FAIL ( | |
1032 | (num_params == 0) || param_types, | |
1033 | ctxt, loc, | |
1034 | "NULL param_types creating function pointer type"); | |
1035 | for (int i = 0; i < num_params; i++) | |
6f7585de DM |
1036 | { |
1037 | RETURN_NULL_IF_FAIL_PRINTF1 (param_types[i], | |
1038 | ctxt, loc, | |
1039 | "NULL parameter type %i" | |
1040 | " creating function pointer type", i); | |
1041 | RETURN_NULL_IF_FAIL_PRINTF1 (!param_types[i]->is_void (), | |
1042 | ctxt, loc, | |
1043 | "void type for param %i", i); | |
1044 | } | |
35485da9 DM |
1045 | |
1046 | return (gcc_jit_type*) | |
1047 | ctxt->new_function_ptr_type (loc, return_type, | |
1048 | num_params, | |
1049 | (gcc::jit::recording::type **)param_types, | |
1050 | is_variadic); | |
1051 | } | |
1052 | ||
1053 | /* Constructing functions. */ | |
1054 | ||
1055 | /* Public entrypoint. See description in libgccjit.h. | |
1056 | ||
1057 | After error-checking, the real work is done by the | |
e53b6e56 | 1058 | gcc::jit::recording::context::new_param method, in jit-recording.cc */ |
35485da9 DM |
1059 | |
1060 | gcc_jit_param * | |
1061 | gcc_jit_context_new_param (gcc_jit_context *ctxt, | |
1062 | gcc_jit_location *loc, | |
1063 | gcc_jit_type *type, | |
1064 | const char *name) | |
1065 | { | |
1066 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 1067 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
1068 | /* LOC can be NULL. */ |
1069 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); | |
1070 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); | |
6f7585de DM |
1071 | RETURN_NULL_IF_FAIL_PRINTF1 (!type->is_void (), |
1072 | ctxt, loc, | |
1073 | "void type for param \"%s\"", name); | |
35485da9 DM |
1074 | |
1075 | return (gcc_jit_param *)ctxt->new_param (loc, type, name); | |
1076 | } | |
1077 | ||
1078 | /* Public entrypoint. See description in libgccjit.h. | |
1079 | ||
1080 | After error-checking, this calls the trivial | |
1081 | gcc::jit::recording::memento::as_object method (a param is a memento), | |
1082 | in jit-recording.h. */ | |
1083 | ||
1084 | gcc_jit_object * | |
1085 | gcc_jit_param_as_object (gcc_jit_param *param) | |
1086 | { | |
1087 | RETURN_NULL_IF_FAIL (param, NULL, NULL, "NULL param"); | |
1088 | ||
1089 | return static_cast <gcc_jit_object *> (param->as_object ()); | |
1090 | } | |
1091 | ||
1092 | /* Public entrypoint. See description in libgccjit.h. | |
1093 | ||
1094 | After error-checking, this calls the trivial | |
1095 | gcc::jit::recording::param::as_lvalue method in jit-recording.h. */ | |
1096 | ||
1097 | gcc_jit_lvalue * | |
1098 | gcc_jit_param_as_lvalue (gcc_jit_param *param) | |
1099 | { | |
1100 | RETURN_NULL_IF_FAIL (param, NULL, NULL, "NULL param"); | |
1101 | ||
1102 | return (gcc_jit_lvalue *)param->as_lvalue (); | |
1103 | } | |
1104 | ||
1105 | /* Public entrypoint. See description in libgccjit.h. | |
1106 | ||
1107 | After error-checking, this calls the trivial | |
1108 | gcc::jit::recording::lvalue::as_rvalue method (a param is an rvalue), | |
1109 | in jit-recording.h. */ | |
1110 | ||
1111 | gcc_jit_rvalue * | |
1112 | gcc_jit_param_as_rvalue (gcc_jit_param *param) | |
1113 | { | |
1114 | RETURN_NULL_IF_FAIL (param, NULL, NULL, "NULL param"); | |
1115 | ||
1116 | return (gcc_jit_rvalue *)param->as_rvalue (); | |
1117 | } | |
1118 | ||
1119 | /* Public entrypoint. See description in libgccjit.h. | |
1120 | ||
1121 | After error-checking, the real work is done by the | |
1122 | gcc::jit::recording::context::new_function method, in | |
e53b6e56 | 1123 | jit-recording.cc. */ |
35485da9 DM |
1124 | |
1125 | gcc_jit_function * | |
1126 | gcc_jit_context_new_function (gcc_jit_context *ctxt, | |
1127 | gcc_jit_location *loc, | |
1128 | enum gcc_jit_function_kind kind, | |
1129 | gcc_jit_type *return_type, | |
1130 | const char *name, | |
1131 | int num_params, | |
1132 | gcc_jit_param **params, | |
1133 | int is_variadic) | |
1134 | { | |
1135 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 1136 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
1137 | /* LOC can be NULL. */ |
1138 | RETURN_NULL_IF_FAIL_PRINTF1 ( | |
1139 | ((kind >= GCC_JIT_FUNCTION_EXPORTED) | |
1140 | && (kind <= GCC_JIT_FUNCTION_ALWAYS_INLINE)), | |
1141 | ctxt, loc, | |
1142 | "unrecognized value for enum gcc_jit_function_kind: %i", | |
1143 | kind); | |
1144 | RETURN_NULL_IF_FAIL (return_type, ctxt, loc, "NULL return_type"); | |
1145 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); | |
1146 | /* The assembler can only handle certain names, so for now, enforce | |
32bd0353 | 1147 | C's rules for identifiers upon the name, using ISALPHA and ISALNUM |
35485da9 DM |
1148 | from safe-ctype.h to ignore the current locale. |
1149 | Eventually we'll need some way to interact with e.g. C++ name | |
1150 | mangling. */ | |
1151 | { | |
1152 | /* Leading char: */ | |
1153 | char ch = *name; | |
1154 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
1155 | ISALPHA (ch) || ch == '_', | |
1156 | ctxt, loc, | |
1157 | "name \"%s\" contains invalid character: '%c'", | |
1158 | name, ch); | |
1159 | /* Subsequent chars: */ | |
1160 | for (const char *ptr = name + 1; (ch = *ptr); ptr++) | |
1161 | { | |
1162 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
1163 | ISALNUM (ch) || ch == '_', | |
1164 | ctxt, loc, | |
1165 | "name \"%s\" contains invalid character: '%c'", | |
1166 | name, ch); | |
1167 | } | |
1168 | } | |
1169 | RETURN_NULL_IF_FAIL_PRINTF1 ( | |
1170 | (num_params == 0) || params, | |
1171 | ctxt, loc, | |
1172 | "NULL params creating function %s", name); | |
1173 | for (int i = 0; i < num_params; i++) | |
f6f2b019 DM |
1174 | { |
1175 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
1176 | params[i], | |
1177 | ctxt, loc, | |
1178 | "NULL parameter %i creating function %s", i, name); | |
1179 | RETURN_NULL_IF_FAIL_PRINTF5 ( | |
01512446 | 1180 | params[i]->get_scope () == NULL, |
f6f2b019 DM |
1181 | ctxt, loc, |
1182 | "parameter %i \"%s\"" | |
1183 | " (type: %s)" | |
1184 | " for function %s" | |
1185 | " was already used for function %s", | |
1186 | i, params[i]->get_debug_string (), | |
1187 | params[i]->get_type ()->get_debug_string (), | |
1188 | name, | |
1189 | params[i]->get_scope ()->get_debug_string ()); | |
1190 | } | |
35485da9 DM |
1191 | |
1192 | return (gcc_jit_function*) | |
1193 | ctxt->new_function (loc, kind, return_type, name, | |
1194 | num_params, | |
1195 | (gcc::jit::recording::param **)params, | |
1196 | is_variadic, | |
1197 | BUILT_IN_NONE); | |
1198 | } | |
1199 | ||
1200 | /* Public entrypoint. See description in libgccjit.h. | |
1201 | ||
1202 | After error-checking, the real work is done by the | |
1203 | gcc::jit::recording::context::get_builtin_function method, in | |
e53b6e56 | 1204 | jit-recording.cc. */ |
35485da9 DM |
1205 | |
1206 | gcc_jit_function * | |
1207 | gcc_jit_context_get_builtin_function (gcc_jit_context *ctxt, | |
1208 | const char *name) | |
1209 | { | |
1210 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 1211 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
1212 | RETURN_NULL_IF_FAIL (name, ctxt, NULL, "NULL name"); |
1213 | ||
1214 | return static_cast <gcc_jit_function *> (ctxt->get_builtin_function (name)); | |
1215 | } | |
1216 | ||
1217 | /* Public entrypoint. See description in libgccjit.h. | |
1218 | ||
1219 | After error-checking, this calls the trivial | |
1220 | gcc::jit::recording::memento::as_object method (a function is a | |
1221 | memento), in jit-recording.h. */ | |
1222 | ||
1223 | gcc_jit_object * | |
1224 | gcc_jit_function_as_object (gcc_jit_function *func) | |
1225 | { | |
1226 | RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function"); | |
1227 | ||
1228 | return static_cast <gcc_jit_object *> (func->as_object ()); | |
1229 | } | |
1230 | ||
1231 | /* Public entrypoint. See description in libgccjit.h. | |
1232 | ||
1233 | After error-checking, the real work is done by the | |
1234 | gcc::jit::recording::function::get_param method, in | |
1235 | jit-recording.h. */ | |
1236 | ||
1237 | gcc_jit_param * | |
1238 | gcc_jit_function_get_param (gcc_jit_function *func, int index) | |
1239 | { | |
1240 | RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function"); | |
1241 | gcc::jit::recording::context *ctxt = func->m_ctxt; | |
eb4c16eb | 1242 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
1243 | RETURN_NULL_IF_FAIL (index >= 0, ctxt, NULL, "negative index"); |
1244 | int num_params = func->get_params ().length (); | |
1245 | RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params, | |
1246 | ctxt, NULL, | |
1247 | "index of %d is too large (%s has %d params)", | |
1248 | index, | |
1249 | func->get_debug_string (), | |
1250 | num_params); | |
1251 | ||
1252 | return static_cast <gcc_jit_param *> (func->get_param (index)); | |
1253 | } | |
1254 | ||
cfe8dbd9 AB |
1255 | /* Public entrypoint. See description in libgccjit.h. |
1256 | ||
1257 | After error-checking, the real work is done by the | |
1258 | gcc::jit::recording::function::get_params method, in | |
1259 | jit-recording.h. | |
1260 | */ | |
1261 | ||
1262 | size_t | |
1263 | gcc_jit_function_get_param_count (gcc_jit_function *func) | |
1264 | { | |
1265 | RETURN_VAL_IF_FAIL (func, 0, NULL, NULL, "NULL function"); | |
1266 | gcc::jit::recording::context *ctxt = func->m_ctxt; | |
1267 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
1268 | return func->get_params ().length (); | |
1269 | } | |
1270 | ||
1271 | /* Public entrypoint. See description in libgccjit.h. | |
1272 | ||
1273 | After error-checking, the real work is done by the | |
1274 | gcc::jit::recording::function::get_return_type method, in | |
1275 | jit-recording.h. */ | |
1276 | ||
1277 | gcc_jit_type * | |
1278 | gcc_jit_function_get_return_type (gcc_jit_function *func) | |
1279 | { | |
1280 | RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function_type"); | |
1281 | return (gcc_jit_type *)func->get_return_type (); | |
1282 | } | |
1283 | ||
35485da9 DM |
1284 | /* Public entrypoint. See description in libgccjit.h. |
1285 | ||
1286 | After error-checking, the real work is done by the | |
1287 | gcc::jit::recording::function::dump_to_dot method, in | |
e53b6e56 | 1288 | jit-recording.cc. */ |
35485da9 DM |
1289 | |
1290 | void | |
1291 | gcc_jit_function_dump_to_dot (gcc_jit_function *func, | |
1292 | const char *path) | |
1293 | { | |
1294 | RETURN_IF_FAIL (func, NULL, NULL, "NULL function"); | |
1295 | gcc::jit::recording::context *ctxt = func->m_ctxt; | |
eb4c16eb | 1296 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
1297 | RETURN_IF_FAIL (path, ctxt, NULL, "NULL path"); |
1298 | ||
1299 | func->dump_to_dot (path); | |
1300 | } | |
1301 | ||
1302 | /* Public entrypoint. See description in libgccjit.h. | |
1303 | ||
1304 | After error-checking, the real work is done by the | |
1305 | gcc::jit::recording::function::new_block method, in | |
e53b6e56 | 1306 | jit-recording.cc. */ |
35485da9 DM |
1307 | |
1308 | gcc_jit_block* | |
1309 | gcc_jit_function_new_block (gcc_jit_function *func, | |
1310 | const char *name) | |
1311 | { | |
1312 | RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function"); | |
eb4c16eb | 1313 | JIT_LOG_FUNC (func->get_context ()->get_logger ()); |
35485da9 DM |
1314 | RETURN_NULL_IF_FAIL (func->get_kind () != GCC_JIT_FUNCTION_IMPORTED, |
1315 | func->get_context (), NULL, | |
1316 | "cannot add block to an imported function"); | |
1317 | /* name can be NULL. */ | |
1318 | ||
1319 | return (gcc_jit_block *)func->new_block (name); | |
1320 | } | |
1321 | ||
1322 | /* Public entrypoint. See description in libgccjit.h. | |
1323 | ||
1324 | After error-checking, this calls the trivial | |
1325 | gcc::jit::recording::memento::as_object method (a block is a | |
1326 | memento), in jit-recording.h. */ | |
1327 | ||
1328 | gcc_jit_object * | |
1329 | gcc_jit_block_as_object (gcc_jit_block *block) | |
1330 | { | |
1331 | RETURN_NULL_IF_FAIL (block, NULL, NULL, "NULL block"); | |
1332 | ||
1333 | return static_cast <gcc_jit_object *> (block->as_object ()); | |
1334 | } | |
1335 | ||
1336 | /* Public entrypoint. See description in libgccjit.h. | |
1337 | ||
1338 | After error-checking, the real work is done by the | |
1339 | gcc::jit::recording::block::get_function method, in | |
1340 | jit-recording.h. */ | |
1341 | ||
1342 | gcc_jit_function * | |
1343 | gcc_jit_block_get_function (gcc_jit_block *block) | |
1344 | { | |
1345 | RETURN_NULL_IF_FAIL (block, NULL, NULL, "NULL block"); | |
1346 | ||
1347 | return static_cast <gcc_jit_function *> (block->get_function ()); | |
1348 | } | |
1349 | ||
1350 | /* Public entrypoint. See description in libgccjit.h. | |
1351 | ||
1352 | After error-checking, the real work is done by the | |
1353 | gcc::jit::recording::context::new_global method, in | |
e53b6e56 | 1354 | jit-recording.cc. */ |
35485da9 DM |
1355 | |
1356 | gcc_jit_lvalue * | |
1357 | gcc_jit_context_new_global (gcc_jit_context *ctxt, | |
1358 | gcc_jit_location *loc, | |
791cfef8 | 1359 | enum gcc_jit_global_kind kind, |
35485da9 DM |
1360 | gcc_jit_type *type, |
1361 | const char *name) | |
1362 | { | |
1363 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 1364 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 | 1365 | /* LOC can be NULL. */ |
791cfef8 DM |
1366 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
1367 | ((kind >= GCC_JIT_GLOBAL_EXPORTED) | |
1368 | && (kind <= GCC_JIT_GLOBAL_IMPORTED)), | |
1369 | ctxt, loc, | |
1370 | "unrecognized value for enum gcc_jit_global_kind: %i", | |
1371 | kind); | |
35485da9 DM |
1372 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); |
1373 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); | |
58c5ad40 | 1374 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
3457d39e DM |
1375 | type->has_known_size (), |
1376 | ctxt, loc, | |
58c5ad40 DM |
1377 | "unknown size for global \"%s\" (type: %s)", |
1378 | name, | |
3457d39e | 1379 | type->get_debug_string ()); |
6f7585de DM |
1380 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
1381 | !type->is_void (), | |
1382 | ctxt, loc, | |
1383 | "void type for global \"%s\"", | |
1384 | name); | |
35485da9 | 1385 | |
791cfef8 | 1386 | return (gcc_jit_lvalue *)ctxt->new_global (loc, kind, type, name); |
35485da9 DM |
1387 | } |
1388 | ||
37368378 PT |
1389 | extern gcc_jit_rvalue * |
1390 | gcc_jit_context_new_struct_constructor (gcc_jit_context *ctxt, | |
1391 | gcc_jit_location *loc, | |
1392 | gcc_jit_type *type, | |
1393 | size_t num_values, | |
1394 | gcc_jit_field **fields, | |
1395 | gcc_jit_rvalue **values) | |
1396 | { | |
1397 | using namespace gcc::jit::recording; | |
1398 | ||
1399 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
1400 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
1401 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); | |
1402 | ||
1403 | RETURN_NULL_IF_FAIL_PRINTF1 (type->is_struct (), | |
1404 | ctxt, loc, | |
1405 | "constructor type is not a struct: %s", | |
1406 | type->get_debug_string ()); | |
1407 | ||
1408 | compound_type *ct = reinterpret_cast<compound_type *>(type); | |
1409 | gcc::jit::recording::fields *fields_struct = ct->get_fields (); | |
1410 | size_t n_fields = fields_struct->length (); | |
1411 | ||
1412 | RETURN_NULL_IF_FAIL_PRINTF1 (ct->has_known_size (), | |
1413 | ctxt, loc, | |
1414 | "struct can't be opaque: %s", | |
1415 | type->get_debug_string ()); | |
1416 | RETURN_NULL_IF_FAIL_PRINTF1 (n_fields, | |
1417 | ctxt, loc, | |
1418 | "no fields in struct: %s", | |
1419 | type->get_debug_string ()); | |
1420 | ||
1421 | /* If there is no array input we just short circuit to zero the struct. */ | |
1422 | if (!num_values) | |
1423 | return (gcc_jit_rvalue *)ctxt->new_ctor (loc, type, 0, NULL, NULL); | |
1424 | ||
1425 | RETURN_NULL_IF_FAIL_PRINTF3 (n_fields >= num_values, | |
1426 | ctxt, loc, | |
1427 | "more values in constructor (n=%zu) than fields" | |
1428 | " in target %s (n=%zu)", | |
1429 | num_values, | |
1430 | type->get_debug_string (), | |
1431 | n_fields); | |
1432 | ||
1433 | /* It is OK if fields are null here, indicating definiton order, | |
1434 | but there has to be a values array. */ | |
1435 | RETURN_NULL_IF_FAIL (values, | |
1436 | ctxt, loc, | |
1437 | "'values' NULL with non-zero 'num_values'"); | |
1438 | ||
1439 | size_t idx = 0; /* Runner index for fields in the type object. */ | |
1440 | ||
1441 | for (size_t i = 0; i < num_values; i++) | |
1442 | { | |
1443 | gcc::jit::recording::rvalue *rv = values[i]; | |
1444 | ||
1445 | /* rv kan be NULL, which would indicate zero init for the field. */ | |
1446 | gcc::jit::recording::type *rv_type = rv ? rv->get_type () : nullptr; | |
1447 | ||
1448 | /* If fields are specified we need to check that they are in | |
1449 | definition order. */ | |
1450 | if (fields) | |
1451 | { | |
1452 | gcc::jit::recording::field *f = fields[i]; | |
1453 | ||
1454 | RETURN_NULL_IF_FAIL_PRINTF1 ( | |
1455 | f, | |
1456 | ctxt, loc, | |
1457 | "NULL field in 'fields', at index %zu", i); | |
1458 | ||
1459 | RETURN_NULL_IF_FAIL_PRINTF3 ( | |
1460 | f->get_container () == | |
1461 | static_cast<gcc::jit::recording::type*>(type), | |
1462 | ctxt, loc, | |
1463 | "field object at index %zu (%s), was not used when creating " | |
1464 | "the %s", | |
1465 | i, | |
1466 | f->get_debug_string (), | |
1467 | type->get_debug_string ()); | |
1468 | ||
1469 | /* Fields in the constructor need to be in struct definition | |
1470 | order, but there can be gaps. */ | |
1471 | size_t j; | |
1472 | for (j = idx; j < n_fields; j++) | |
1473 | { | |
1474 | field *fs = fields_struct->get_field (j); | |
1475 | if (fs == f) | |
1476 | { | |
1477 | idx = j; /* Advance runner index for next iteration. */ | |
1478 | break; | |
1479 | } | |
1480 | } | |
1481 | ||
1482 | RETURN_NULL_IF_FAIL_PRINTF3 ( | |
1483 | j != n_fields, | |
1484 | ctxt, loc, | |
1485 | "field at index %zu in 'fields' is not in definition order " | |
1486 | "(struct: %s) (ctor field: %s)", | |
1487 | i, | |
1488 | type->get_debug_string (), | |
1489 | f->get_debug_string ()); | |
1490 | ||
1491 | /* Check that the specified field has the same type as the | |
1492 | value, unless the value is null (a zero value init). */ | |
1493 | RETURN_NULL_IF_FAIL_PRINTF5 ( | |
1494 | !rv || gcc::jit::types_kinda_same (rv_type, | |
1495 | f->get_type ()), | |
1496 | ctxt, loc, | |
1497 | "value and field not the same unqualified type, at index %zu" | |
1498 | " (%s.%s: %s)(value type: %s)", | |
1499 | i, | |
1500 | type->get_debug_string (), | |
1501 | f->get_debug_string (), | |
1502 | f->get_type ()->get_debug_string (), | |
1503 | rv_type->get_debug_string ()); | |
1504 | } | |
1505 | ||
1506 | /* If no fields are specified, check that the value has the same type | |
1507 | as the field in the definition of the struct. */ | |
1508 | if (rv && !fields) | |
1509 | { | |
1510 | RETURN_NULL_IF_FAIL_PRINTF5 ( | |
1511 | gcc::jit::types_kinda_same (rv_type, | |
1512 | fields_struct-> | |
1513 | get_field (i)->get_type ()), | |
1514 | ctxt, loc, | |
1515 | "value and field not the same unqualified type, at index %zu" | |
1516 | " (%s.%s: %s)(value type: %s)", | |
1517 | i, | |
1518 | type->get_debug_string (), | |
1519 | fields_struct->get_field (i)->get_debug_string (), | |
1520 | fields_struct->get_field (i)->get_type ()->get_debug_string (), | |
1521 | rv_type->get_debug_string ()); | |
1522 | } | |
1523 | ||
1524 | if (rv) | |
1525 | { | |
1526 | RETURN_NULL_IF_FAIL_PRINTF1 ( | |
1527 | !rv_type->is_void (), | |
1528 | ctxt, loc, | |
1529 | "can't construct the void type, at index %zu", i); | |
1530 | } | |
1531 | } | |
1532 | ||
1533 | return (gcc_jit_rvalue *)ctxt->new_ctor ( | |
1534 | loc, | |
1535 | type, | |
1536 | num_values, | |
1537 | reinterpret_cast<gcc::jit::recording::field**>(fields), | |
1538 | reinterpret_cast<gcc::jit::recording::rvalue**>(values)); | |
1539 | } | |
1540 | ||
1541 | extern gcc_jit_rvalue * | |
1542 | gcc_jit_context_new_union_constructor (gcc_jit_context *ctxt, | |
1543 | gcc_jit_location *loc, | |
1544 | gcc_jit_type *type, | |
1545 | gcc_jit_field *field, | |
1546 | gcc_jit_rvalue *value) | |
1547 | { | |
1548 | using namespace gcc::jit::recording; | |
1549 | ||
1550 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
1551 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
1552 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); | |
1553 | ||
1554 | RETURN_NULL_IF_FAIL_PRINTF1 (type->is_union (), | |
1555 | ctxt, loc, | |
1556 | "constructor type is not an union: %s", | |
1557 | type->get_debug_string ()); | |
1558 | ||
1559 | compound_type *ct = reinterpret_cast<compound_type *>(type); | |
1560 | gcc::jit::recording::fields *fields_union = ct->get_fields (); | |
1561 | size_t n_fields = fields_union->length (); | |
1562 | ||
1563 | RETURN_NULL_IF_FAIL_PRINTF1 (ct->has_known_size (), | |
1564 | ctxt, loc, | |
1565 | "union can't be opaque: %s", | |
1566 | type->get_debug_string ()); | |
1567 | RETURN_NULL_IF_FAIL_PRINTF1 (n_fields, | |
1568 | ctxt, loc, | |
1569 | "no fields in union: %s", | |
1570 | type->get_debug_string ()); | |
1571 | ||
1572 | /* If value is NULL we are just supposed to zero the whole union. */ | |
1573 | if (!value) | |
1574 | return (gcc_jit_rvalue *)ctxt->new_ctor (loc, type, 0, NULL, NULL); | |
1575 | ||
1576 | gcc::jit::recording::type *rv_type = value->get_type (); | |
1577 | ||
1578 | RETURN_NULL_IF_FAIL ( | |
1579 | !rv_type->is_void (), | |
1580 | ctxt, loc, | |
1581 | "can't construct the void type"); | |
1582 | ||
1583 | if (field) | |
1584 | { | |
1585 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
1586 | field->get_container () == | |
1587 | static_cast<gcc::jit::recording::type*>(type), | |
1588 | ctxt, loc, | |
1589 | "field object (%s) was not used when creating " | |
1590 | "the type %s", | |
1591 | field->get_debug_string (), | |
1592 | type->get_debug_string ()); | |
1593 | ||
1594 | RETURN_NULL_IF_FAIL_PRINTF4 ( | |
1595 | gcc::jit::types_kinda_same (rv_type, | |
1596 | field->get_type ()), | |
1597 | ctxt, loc, | |
1598 | "value and field are not the same unqualified type" | |
1599 | " (%s.%s: %s)(value type: %s)", | |
1600 | type->get_debug_string (), | |
1601 | field->get_debug_string (), | |
1602 | field->get_type ()->get_debug_string (), | |
1603 | rv_type->get_debug_string ()); | |
1604 | } | |
1605 | /* If no field is specified, check that the value has the same type | |
1606 | as the first field in the definition of the union. */ | |
1607 | if (!field) | |
1608 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
1609 | gcc::jit::types_kinda_same (rv_type, | |
1610 | fields_union-> | |
1611 | get_field (0)->get_type ()), | |
1612 | ctxt, loc, | |
1613 | "value and first union field not the same unqualified type" | |
1614 | " (field type: %s)(value type: %s)", | |
1615 | fields_union->get_field (0)->get_type ()->get_debug_string (), | |
1616 | rv_type->get_debug_string ()); | |
1617 | ||
1618 | ||
1619 | return (gcc_jit_rvalue *)ctxt->new_ctor ( | |
1620 | loc, | |
1621 | type, | |
1622 | 1, | |
1623 | /* A NULL fields array tells new_ctor to take fields from the type obj. */ | |
1624 | reinterpret_cast<gcc::jit::recording::field**>(field ? &field : NULL), | |
1625 | reinterpret_cast<gcc::jit::recording::rvalue**>(&value)); | |
1626 | } | |
1627 | ||
1628 | extern gcc_jit_rvalue * | |
1629 | gcc_jit_context_new_array_constructor (gcc_jit_context *ctxt, | |
1630 | gcc_jit_location *loc, | |
1631 | gcc_jit_type *type, | |
1632 | size_t num_values, | |
1633 | gcc_jit_rvalue **values) | |
1634 | { | |
1635 | using namespace gcc::jit::recording; | |
1636 | ||
1637 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
1638 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
1639 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); | |
1640 | ||
1641 | RETURN_NULL_IF_FAIL (type->is_array () != NULL, | |
1642 | ctxt, loc, | |
1643 | "constructor type not an array"); | |
1644 | ||
1645 | if (!num_values) | |
1646 | values = NULL; | |
1647 | ||
1648 | if (num_values) | |
1649 | { | |
1650 | RETURN_NULL_IF_FAIL ( | |
1651 | values, | |
1652 | ctxt, loc, | |
1653 | "'values' NULL with non-zero 'num_values'"); | |
1654 | ||
1655 | gcc::jit::recording::array_type *arr_type = | |
1656 | reinterpret_cast<gcc::jit::recording::array_type*>(type); | |
1657 | size_t n_el = arr_type->num_elements (); | |
1658 | ||
1659 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
1660 | n_el >= num_values, | |
1661 | ctxt, loc, | |
1662 | "array constructor has more values than the array type's length" | |
1663 | " (array type length: %zu, constructor length: %zu)", | |
1664 | n_el, | |
1665 | num_values); | |
1666 | ||
1667 | /* For arrays, all values need to be the same base type. */ | |
1668 | gcc::jit::recording::type *type0 = NULL; | |
1669 | size_t i = 0; | |
1670 | /* Find first non-null value. */ | |
1671 | for (;i < num_values; i++) | |
1672 | { | |
1673 | if (values[i]) | |
1674 | break; | |
1675 | } | |
1676 | ||
1677 | if (i < num_values) /* All values might be null and i == num_values. */ | |
1678 | type0 = values[i]->get_type (); | |
1679 | ||
1680 | /* If we got a type0, check that all other values have | |
1681 | the same type. */ | |
1682 | for (; i < num_values; i++) | |
1683 | { | |
1684 | if (values[i]) | |
1685 | RETURN_NULL_IF_FAIL_PRINTF3 ( | |
1686 | gcc::jit::types_kinda_same (type0, | |
1687 | values[i]->get_type ()), | |
1688 | ctxt, loc, | |
1689 | "value type at index %zu differ from first value type" | |
1690 | " (first type: %s)(different type: %s)", | |
1691 | i, | |
1692 | type0->get_debug_string (), | |
1693 | values[i]->get_type ()->get_debug_string ()); | |
1694 | } | |
1695 | ||
1696 | /* Compare type0 with the element type specified in the | |
1697 | type of the array. */ | |
1698 | if (type0) | |
1699 | { | |
1700 | gcc::jit::recording::type *el_type = | |
1701 | type->is_array (); | |
1702 | ||
1703 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
1704 | gcc::jit::types_kinda_same (type0, el_type), | |
1705 | ctxt, loc, | |
1706 | "array element value types differ from types in 'values'" | |
1707 | " (element type: %s)('values' type: %s)", | |
1708 | el_type->get_debug_string (), | |
1709 | type0->get_debug_string ()); | |
1710 | } | |
1711 | } | |
1712 | ||
1713 | return (gcc_jit_rvalue *)ctxt->new_ctor ( | |
1714 | loc, | |
1715 | type, | |
1716 | num_values, | |
1717 | NULL, | |
1718 | reinterpret_cast<gcc::jit::recording::rvalue**>(values)); | |
1719 | } | |
1720 | ||
1721 | /* Public entrypoint. See description in libgccjit.h. */ | |
1722 | ||
1723 | extern gcc_jit_lvalue * | |
1724 | gcc_jit_global_set_initializer_rvalue (gcc_jit_lvalue *global, | |
1725 | gcc_jit_rvalue *init_rvalue) | |
1726 | { | |
1727 | RETURN_NULL_IF_FAIL (global, NULL, NULL,"NULL global"); | |
1728 | ||
1729 | gcc::jit::recording::context *ctxt = global->get_context (); | |
1730 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL,"NULL context"); | |
1731 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
1732 | RETURN_NULL_IF_FAIL (init_rvalue, ctxt, NULL,"NULL init_rvalue"); | |
1733 | ||
1734 | RETURN_NULL_IF_FAIL_PRINTF1 (global->is_global (), | |
1735 | ctxt, NULL, | |
1736 | "lvalue \"%s\" not a global", | |
1737 | global->get_debug_string ()); | |
1738 | ||
1739 | gcc::jit::recording::global *gbl = | |
1740 | reinterpret_cast<gcc::jit::recording::global *> (global); | |
1741 | ||
1742 | RETURN_NULL_IF_FAIL_PRINTF1 (gbl->get_kind () != | |
1743 | GCC_JIT_GLOBAL_IMPORTED, | |
1744 | ctxt, NULL, | |
1745 | "can't initialize \"%s\", it is imported", | |
1746 | global->get_debug_string ()); | |
1747 | ||
1748 | RETURN_NULL_IF_FAIL_PRINTF4 (gcc::jit::types_kinda_same ( | |
1749 | global->get_type (), | |
1750 | init_rvalue->get_type ()), | |
1751 | ctxt, NULL, | |
1752 | "mismatching types:" | |
1753 | " initializing %s (type: %s) with %s (type: %s)", | |
1754 | global->get_debug_string (), | |
1755 | global->get_type ()->get_debug_string (), | |
1756 | init_rvalue->get_debug_string (), | |
1757 | init_rvalue->get_type ()->get_debug_string ()); | |
1758 | ||
1759 | /* Check that there are no initializers set for the global yet. */ | |
1760 | RETURN_NULL_IF_FAIL_PRINTF1 (!gbl->test_flags_anyof ( | |
1761 | gcc::jit::GLOBAL_VAR_FLAGS_WILL_BE_RVAL_INIT | | |
1762 | gcc::jit::GLOBAL_VAR_FLAGS_WILL_BE_BLOB_INIT), | |
1763 | ctxt, NULL, | |
1764 | "global variable already initialized: %s", | |
1765 | global->get_debug_string ()); | |
1766 | ||
1767 | /* The global need to know during playback that it will be | |
1768 | initialized. */ | |
1769 | gbl->set_flags (gcc::jit::GLOBAL_VAR_FLAGS_WILL_BE_RVAL_INIT); | |
1770 | ||
1771 | ctxt->new_global_init_rvalue (global, init_rvalue); | |
1772 | ||
1773 | return global; | |
1774 | } | |
1775 | ||
4ecc0061 AC |
1776 | /* Public entrypoint. See description in libgccjit.h. |
1777 | ||
1778 | After error-checking, the real work is done by the | |
1779 | gcc::jit::recording::global::set_initializer method, in | |
e53b6e56 | 1780 | jit-recording.cc. */ |
4ecc0061 AC |
1781 | |
1782 | extern gcc_jit_lvalue * | |
1783 | gcc_jit_global_set_initializer (gcc_jit_lvalue *global, | |
1784 | const void *blob, | |
1785 | size_t num_bytes) | |
1786 | { | |
1787 | RETURN_NULL_IF_FAIL (global, NULL, NULL, "NULL global"); | |
1788 | RETURN_NULL_IF_FAIL (blob, NULL, NULL, "NULL blob"); | |
1789 | RETURN_NULL_IF_FAIL_PRINTF1 (global->is_global (), NULL, NULL, | |
1790 | "lvalue \"%s\" not a global", | |
1791 | global->get_debug_string ()); | |
1792 | ||
1793 | gcc::jit::recording::type *lval_type = global->get_type (); | |
1794 | RETURN_NULL_IF_FAIL_PRINTF1 (lval_type->is_array (), NULL, NULL, | |
1795 | "global \"%s\" is not an array", | |
1796 | global->get_debug_string ()); | |
1797 | RETURN_NULL_IF_FAIL_PRINTF1 (lval_type->dereference ()->is_int (), NULL, NULL, | |
1798 | "global \"%s\" is not an array of integral type", | |
1799 | global->get_debug_string ()); | |
1800 | size_t lvalue_size = | |
1801 | lval_type->dereference ()->get_size () | |
1802 | * static_cast <gcc::jit::recording::array_type *> (lval_type)->num_elements (); | |
1803 | RETURN_NULL_IF_FAIL_PRINTF3 ( | |
1804 | lvalue_size == num_bytes, NULL, NULL, | |
1805 | "mismatching sizes:" | |
1806 | " global \"%s\" has size %zu whereas initializer has size %zu", | |
1807 | global->get_debug_string (), lvalue_size, num_bytes); | |
1808 | ||
37368378 PT |
1809 | /* Check that the rvalue initializer is not set for this global. |
1810 | Note that we do not check if this blob type initializer is | |
1811 | already set, since that check was not present when the entrypoint | |
1812 | was initially written. */ | |
1813 | gcc::jit::recording::global *gbl = | |
1814 | reinterpret_cast<gcc::jit::recording::global *> (global); | |
1815 | RETURN_NULL_IF_FAIL_PRINTF1 (!gbl->test_flags_anyof ( | |
1816 | gcc::jit::GLOBAL_VAR_FLAGS_WILL_BE_RVAL_INIT), | |
1817 | NULL, NULL, | |
1818 | "global variable already initialized: %s", | |
1819 | global->get_debug_string ()); | |
1820 | ||
1821 | gbl->set_initializer (blob, num_bytes); | |
1822 | /* The global need to know during playback that it will be | |
1823 | initialized. */ | |
1824 | gbl->set_flags (gcc::jit::GLOBAL_VAR_FLAGS_WILL_BE_BLOB_INIT); | |
4ecc0061 AC |
1825 | |
1826 | return global; | |
1827 | } | |
1828 | ||
35485da9 DM |
1829 | /* Public entrypoint. See description in libgccjit.h. |
1830 | ||
1831 | After error-checking, this calls the trivial | |
1832 | gcc::jit::recording::memento::as_object method (an lvalue is a | |
1833 | memento), in jit-recording.h. */ | |
1834 | ||
1835 | gcc_jit_object * | |
1836 | gcc_jit_lvalue_as_object (gcc_jit_lvalue *lvalue) | |
1837 | { | |
1838 | RETURN_NULL_IF_FAIL (lvalue, NULL, NULL, "NULL lvalue"); | |
1839 | ||
1840 | return static_cast <gcc_jit_object *> (lvalue->as_object ()); | |
1841 | } | |
1842 | ||
1843 | /* Public entrypoint. See description in libgccjit.h. | |
1844 | ||
1845 | After error-checking, this calls the trivial | |
1846 | gcc::jit::recording::lvalue::as_rvalue method in jit-recording.h. */ | |
1847 | ||
1848 | gcc_jit_rvalue * | |
1849 | gcc_jit_lvalue_as_rvalue (gcc_jit_lvalue *lvalue) | |
1850 | { | |
1851 | RETURN_NULL_IF_FAIL (lvalue, NULL, NULL, "NULL lvalue"); | |
1852 | ||
1853 | return (gcc_jit_rvalue *)lvalue->as_rvalue (); | |
1854 | } | |
1855 | ||
1856 | /* Public entrypoint. See description in libgccjit.h. | |
1857 | ||
1858 | After error-checking, this calls the trivial | |
1859 | gcc::jit::recording::memento::as_object method (an rvalue is a | |
1860 | memento), in jit-recording.h. */ | |
1861 | ||
1862 | gcc_jit_object * | |
1863 | gcc_jit_rvalue_as_object (gcc_jit_rvalue *rvalue) | |
1864 | { | |
1865 | RETURN_NULL_IF_FAIL (rvalue, NULL, NULL, "NULL rvalue"); | |
1866 | ||
1867 | return static_cast <gcc_jit_object *> (rvalue->as_object ()); | |
1868 | } | |
1869 | ||
1870 | /* Public entrypoint. See description in libgccjit.h. | |
1871 | ||
1872 | After error-checking, the real work is done by the | |
1873 | gcc::jit::recording::rvalue::get_type method, in | |
1874 | jit-recording.h. */ | |
1875 | ||
1876 | gcc_jit_type * | |
1877 | gcc_jit_rvalue_get_type (gcc_jit_rvalue *rvalue) | |
1878 | { | |
1879 | RETURN_NULL_IF_FAIL (rvalue, NULL, NULL, "NULL rvalue"); | |
1880 | ||
1881 | return static_cast <gcc_jit_type *> (rvalue->get_type ()); | |
1882 | } | |
1883 | ||
1884 | /* Verify that NUMERIC_TYPE is non-NULL, and that it is a "numeric" | |
1885 | type i.e. it satisfies gcc::jit::type::is_numeric (), such as the | |
1886 | result of gcc_jit_context_get_type (GCC_JIT_TYPE_INT). */ | |
1887 | ||
1888 | #define RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE(CTXT, NUMERIC_TYPE) \ | |
120e92fc | 1889 | JIT_BEGIN_STMT \ |
35485da9 DM |
1890 | RETURN_NULL_IF_FAIL (NUMERIC_TYPE, CTXT, NULL, "NULL type"); \ |
1891 | RETURN_NULL_IF_FAIL_PRINTF1 ( \ | |
1892 | NUMERIC_TYPE->is_numeric (), ctxt, NULL, \ | |
1893 | "not a numeric type: %s", \ | |
120e92fc TV |
1894 | NUMERIC_TYPE->get_debug_string ()); \ |
1895 | JIT_END_STMT | |
35485da9 DM |
1896 | |
1897 | /* Public entrypoint. See description in libgccjit.h. | |
1898 | ||
1899 | After error-checking, the real work is done by the | |
fc34d04b | 1900 | gcc::jit::recording::context::new_rvalue_from_const <int> method in |
e53b6e56 | 1901 | jit-recording.cc. */ |
35485da9 DM |
1902 | |
1903 | gcc_jit_rvalue * | |
1904 | gcc_jit_context_new_rvalue_from_int (gcc_jit_context *ctxt, | |
1905 | gcc_jit_type *numeric_type, | |
1906 | int value) | |
1907 | { | |
1908 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 1909 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
1910 | RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type); |
1911 | ||
ccce3b2a DM |
1912 | return ((gcc_jit_rvalue *)ctxt |
1913 | ->new_rvalue_from_const <int> (numeric_type, value)); | |
1914 | } | |
1915 | ||
fc34d04b AC |
1916 | /* Public entrypoint. See description in libgccjit.h. |
1917 | ||
1918 | After error-checking, the real work is done by the | |
1919 | gcc::jit::recording::context::new_rvalue_from_const <long> method | |
e53b6e56 | 1920 | in jit-recording.cc. */ |
ccce3b2a DM |
1921 | |
1922 | gcc_jit_rvalue * | |
1923 | gcc_jit_context_new_rvalue_from_long (gcc_jit_context *ctxt, | |
1924 | gcc_jit_type *numeric_type, | |
1925 | long value) | |
1926 | { | |
1927 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
1928 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
1929 | RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type); | |
1930 | ||
1931 | return ((gcc_jit_rvalue *)ctxt | |
1932 | ->new_rvalue_from_const <long> (numeric_type, value)); | |
35485da9 DM |
1933 | } |
1934 | ||
1935 | /* Public entrypoint. See description in libgccjit.h. | |
1936 | ||
1937 | This is essentially equivalent to: | |
1938 | gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 0); | |
1939 | albeit with slightly different error messages if an error occurs. */ | |
1940 | ||
1941 | gcc_jit_rvalue * | |
1942 | gcc_jit_context_zero (gcc_jit_context *ctxt, | |
1943 | gcc_jit_type *numeric_type) | |
1944 | { | |
1945 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 1946 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
1947 | RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type); |
1948 | ||
1949 | return gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 0); | |
1950 | } | |
1951 | ||
1952 | /* Public entrypoint. See description in libgccjit.h. | |
1953 | ||
1954 | This is essentially equivalent to: | |
1955 | gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 1); | |
1956 | albeit with slightly different error messages if an error occurs. */ | |
1957 | ||
1958 | gcc_jit_rvalue * | |
1959 | gcc_jit_context_one (gcc_jit_context *ctxt, | |
1960 | gcc_jit_type *numeric_type) | |
1961 | { | |
1962 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 1963 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
1964 | RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type); |
1965 | ||
1966 | return gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 1); | |
1967 | } | |
1968 | ||
1969 | /* Public entrypoint. See description in libgccjit.h. | |
1970 | ||
1971 | After error-checking, the real work is done by the | |
fc34d04b | 1972 | gcc::jit::recording::context::new_rvalue_from_const <double> method in |
e53b6e56 | 1973 | jit-recording.cc. */ |
35485da9 DM |
1974 | |
1975 | gcc_jit_rvalue * | |
1976 | gcc_jit_context_new_rvalue_from_double (gcc_jit_context *ctxt, | |
1977 | gcc_jit_type *numeric_type, | |
1978 | double value) | |
1979 | { | |
1980 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 1981 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
1982 | RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type); |
1983 | ||
ccce3b2a DM |
1984 | return ((gcc_jit_rvalue *)ctxt |
1985 | ->new_rvalue_from_const <double> (numeric_type, value)); | |
35485da9 DM |
1986 | } |
1987 | ||
1988 | /* Public entrypoint. See description in libgccjit.h. | |
1989 | ||
1990 | After error-checking, the real work is done by the | |
fc34d04b | 1991 | gcc::jit::recording::context::new_rvalue_from_const <void *> method |
e53b6e56 | 1992 | in jit-recording.cc. */ |
35485da9 DM |
1993 | |
1994 | gcc_jit_rvalue * | |
1995 | gcc_jit_context_new_rvalue_from_ptr (gcc_jit_context *ctxt, | |
1996 | gcc_jit_type *pointer_type, | |
1997 | void *value) | |
1998 | { | |
1999 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 2000 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
2001 | RETURN_NULL_IF_FAIL (pointer_type, ctxt, NULL, "NULL type"); |
2002 | RETURN_NULL_IF_FAIL_PRINTF1 ( | |
2003 | pointer_type->is_pointer (), | |
2004 | ctxt, NULL, | |
2005 | "not a pointer type (type: %s)", | |
2006 | pointer_type->get_debug_string ()); | |
2007 | ||
ccce3b2a DM |
2008 | return ((gcc_jit_rvalue *)ctxt |
2009 | ->new_rvalue_from_const <void *> (pointer_type, value)); | |
35485da9 DM |
2010 | } |
2011 | ||
2012 | /* Public entrypoint. See description in libgccjit.h. | |
2013 | ||
2014 | This is essentially equivalent to: | |
2015 | gcc_jit_context_new_rvalue_from_ptr (ctxt, pointer_type, NULL); | |
2016 | albeit with slightly different error messages if an error occurs. */ | |
2017 | ||
2018 | gcc_jit_rvalue * | |
2019 | gcc_jit_context_null (gcc_jit_context *ctxt, | |
2020 | gcc_jit_type *pointer_type) | |
2021 | { | |
2022 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 2023 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
2024 | RETURN_NULL_IF_FAIL (pointer_type, ctxt, NULL, "NULL type"); |
2025 | RETURN_NULL_IF_FAIL_PRINTF1 ( | |
2026 | pointer_type->is_pointer (), | |
2027 | ctxt, NULL, | |
2028 | "not a pointer type (type: %s)", | |
2029 | pointer_type->get_debug_string ()); | |
2030 | ||
2031 | return gcc_jit_context_new_rvalue_from_ptr (ctxt, pointer_type, NULL); | |
2032 | } | |
2033 | ||
2034 | /* Public entrypoint. See description in libgccjit.h. | |
2035 | ||
2036 | After error-checking, the real work is done by the | |
2037 | gcc::jit::recording::context::new_string_literal method in | |
e53b6e56 | 2038 | jit-recording.cc. */ |
35485da9 DM |
2039 | |
2040 | gcc_jit_rvalue * | |
2041 | gcc_jit_context_new_string_literal (gcc_jit_context *ctxt, | |
2042 | const char *value) | |
2043 | { | |
2044 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 2045 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
2046 | RETURN_NULL_IF_FAIL (value, ctxt, NULL, "NULL value"); |
2047 | ||
2048 | return (gcc_jit_rvalue *)ctxt->new_string_literal (value); | |
2049 | } | |
2050 | ||
2051 | /* Public entrypoint. See description in libgccjit.h. | |
2052 | ||
2053 | After error-checking, the real work is done by the | |
2054 | gcc::jit::recording::context::new_unary_op method in | |
e53b6e56 | 2055 | jit-recording.cc. */ |
35485da9 DM |
2056 | |
2057 | gcc_jit_rvalue * | |
2058 | gcc_jit_context_new_unary_op (gcc_jit_context *ctxt, | |
2059 | gcc_jit_location *loc, | |
2060 | enum gcc_jit_unary_op op, | |
2061 | gcc_jit_type *result_type, | |
2062 | gcc_jit_rvalue *rvalue) | |
2063 | { | |
2064 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 2065 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
2066 | /* LOC can be NULL. */ |
2067 | RETURN_NULL_IF_FAIL_PRINTF1 ( | |
2068 | (op >= GCC_JIT_UNARY_OP_MINUS | |
18146f45 | 2069 | && op <= GCC_JIT_UNARY_OP_ABS), |
35485da9 DM |
2070 | ctxt, loc, |
2071 | "unrecognized value for enum gcc_jit_unary_op: %i", | |
2072 | op); | |
2073 | RETURN_NULL_IF_FAIL (result_type, ctxt, loc, "NULL result_type"); | |
9afb91b2 AC |
2074 | RETURN_NULL_IF_FAIL_PRINTF3 ( |
2075 | result_type->is_numeric (), ctxt, loc, | |
2076 | "gcc_jit_unary_op %s with operand %s " | |
2077 | "has non-numeric result_type: %s", | |
2078 | gcc::jit::unary_op_reproducer_strings[op], | |
2079 | rvalue->get_debug_string (), | |
2080 | result_type->get_debug_string ()); | |
35485da9 DM |
2081 | RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); |
2082 | ||
2083 | return (gcc_jit_rvalue *)ctxt->new_unary_op (loc, op, result_type, rvalue); | |
2084 | } | |
2085 | ||
2086 | /* Determine if OP is a valid value for enum gcc_jit_binary_op. | |
2087 | For use by both gcc_jit_context_new_binary_op and | |
2088 | gcc_jit_block_add_assignment_op. */ | |
2089 | ||
2090 | static bool | |
2091 | valid_binary_op_p (enum gcc_jit_binary_op op) | |
2092 | { | |
2093 | return (op >= GCC_JIT_BINARY_OP_PLUS | |
2094 | && op <= GCC_JIT_BINARY_OP_RSHIFT); | |
2095 | } | |
2096 | ||
2097 | /* Public entrypoint. See description in libgccjit.h. | |
2098 | ||
2099 | After error-checking, the real work is done by the | |
2100 | gcc::jit::recording::context::new_binary_op method in | |
e53b6e56 | 2101 | jit-recording.cc. */ |
35485da9 DM |
2102 | |
2103 | gcc_jit_rvalue * | |
2104 | gcc_jit_context_new_binary_op (gcc_jit_context *ctxt, | |
2105 | gcc_jit_location *loc, | |
2106 | enum gcc_jit_binary_op op, | |
2107 | gcc_jit_type *result_type, | |
2108 | gcc_jit_rvalue *a, gcc_jit_rvalue *b) | |
2109 | { | |
2110 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 2111 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
2112 | /* LOC can be NULL. */ |
2113 | RETURN_NULL_IF_FAIL_PRINTF1 ( | |
2114 | valid_binary_op_p (op), | |
2115 | ctxt, loc, | |
2116 | "unrecognized value for enum gcc_jit_binary_op: %i", | |
2117 | op); | |
2118 | RETURN_NULL_IF_FAIL (result_type, ctxt, loc, "NULL result_type"); | |
2119 | RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a"); | |
2120 | RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b"); | |
2121 | RETURN_NULL_IF_FAIL_PRINTF4 ( | |
6069fe72 | 2122 | a->get_type ()->unqualified () == b->get_type ()->unqualified (), |
35485da9 DM |
2123 | ctxt, loc, |
2124 | "mismatching types for binary op:" | |
2125 | " a: %s (type: %s) b: %s (type: %s)", | |
2126 | a->get_debug_string (), | |
2127 | a->get_type ()->get_debug_string (), | |
2128 | b->get_debug_string (), | |
2129 | b->get_type ()->get_debug_string ()); | |
2b442504 AC |
2130 | RETURN_NULL_IF_FAIL_PRINTF4 ( |
2131 | result_type->is_numeric (), ctxt, loc, | |
9afb91b2 AC |
2132 | "gcc_jit_binary_op %s with operands a: %s b: %s " |
2133 | "has non-numeric result_type: %s", | |
2134 | gcc::jit::binary_op_reproducer_strings[op], | |
2135 | a->get_debug_string (), b->get_debug_string (), | |
2b442504 | 2136 | result_type->get_debug_string ()); |
35485da9 DM |
2137 | |
2138 | return (gcc_jit_rvalue *)ctxt->new_binary_op (loc, op, result_type, a, b); | |
2139 | } | |
2140 | ||
2141 | /* Public entrypoint. See description in libgccjit.h. | |
2142 | ||
2143 | After error-checking, the real work is done by the | |
2144 | gcc::jit::recording::context::new_comparison method in | |
e53b6e56 | 2145 | jit-recording.cc. */ |
35485da9 DM |
2146 | |
2147 | gcc_jit_rvalue * | |
2148 | gcc_jit_context_new_comparison (gcc_jit_context *ctxt, | |
2149 | gcc_jit_location *loc, | |
2150 | enum gcc_jit_comparison op, | |
2151 | gcc_jit_rvalue *a, gcc_jit_rvalue *b) | |
2152 | { | |
2153 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 2154 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
2155 | /* LOC can be NULL. */ |
2156 | RETURN_NULL_IF_FAIL_PRINTF1 ( | |
2157 | (op >= GCC_JIT_COMPARISON_EQ | |
2158 | && op <= GCC_JIT_COMPARISON_GE), | |
2159 | ctxt, loc, | |
2160 | "unrecognized value for enum gcc_jit_comparison: %i", | |
2161 | op); | |
2162 | RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a"); | |
2163 | RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b"); | |
2164 | RETURN_NULL_IF_FAIL_PRINTF4 ( | |
2165 | a->get_type ()->unqualified () == b->get_type ()->unqualified (), | |
2166 | ctxt, loc, | |
2167 | "mismatching types for comparison:" | |
2168 | " a: %s (type: %s) b: %s (type: %s)", | |
2169 | a->get_debug_string (), | |
2170 | a->get_type ()->get_debug_string (), | |
2171 | b->get_debug_string (), | |
2172 | b->get_type ()->get_debug_string ()); | |
2173 | ||
2174 | return (gcc_jit_rvalue *)ctxt->new_comparison (loc, op, a, b); | |
2175 | } | |
2176 | ||
2177 | /* Public entrypoint. See description in libgccjit.h. | |
2178 | ||
2179 | After error-checking, the real work is done by the | |
2180 | gcc::jit::recording::context::new_call method in | |
e53b6e56 | 2181 | jit-recording.cc. */ |
35485da9 DM |
2182 | |
2183 | gcc_jit_rvalue * | |
2184 | gcc_jit_context_new_call (gcc_jit_context *ctxt, | |
2185 | gcc_jit_location *loc, | |
2186 | gcc_jit_function *func, | |
2187 | int numargs , gcc_jit_rvalue **args) | |
2188 | { | |
2189 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 2190 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
2191 | /* LOC can be NULL. */ |
2192 | RETURN_NULL_IF_FAIL (func, ctxt, loc, "NULL function"); | |
2193 | if (numargs) | |
2194 | RETURN_NULL_IF_FAIL (args, ctxt, loc, "NULL args"); | |
2195 | ||
2196 | int min_num_params = func->get_params ().length (); | |
2197 | bool is_variadic = func->is_variadic (); | |
2198 | ||
2199 | RETURN_NULL_IF_FAIL_PRINTF3 ( | |
2200 | numargs >= min_num_params, | |
2201 | ctxt, loc, | |
2202 | "not enough arguments to function \"%s\"" | |
2203 | " (got %i args, expected %i)", | |
2204 | func->get_name ()->c_str (), | |
2205 | numargs, min_num_params); | |
2206 | ||
2207 | RETURN_NULL_IF_FAIL_PRINTF3 ( | |
2208 | (numargs == min_num_params || is_variadic), | |
2209 | ctxt, loc, | |
2210 | "too many arguments to function \"%s\"" | |
2211 | " (got %i args, expected %i)", | |
2212 | func->get_name ()->c_str (), | |
2213 | numargs, min_num_params); | |
2214 | ||
2215 | for (int i = 0; i < min_num_params; i++) | |
2216 | { | |
2217 | gcc::jit::recording::param *param = func->get_param (i); | |
2218 | gcc_jit_rvalue *arg = args[i]; | |
2219 | ||
2220 | RETURN_NULL_IF_FAIL_PRINTF4 ( | |
2221 | arg, | |
2222 | ctxt, loc, | |
2223 | "NULL argument %i to function \"%s\":" | |
2224 | " param %s (type: %s)", | |
2225 | i + 1, | |
2226 | func->get_name ()->c_str (), | |
2227 | param->get_debug_string (), | |
2228 | param->get_type ()->get_debug_string ()); | |
2229 | ||
2230 | RETURN_NULL_IF_FAIL_PRINTF6 ( | |
2231 | compatible_types (param->get_type (), | |
2232 | arg->get_type ()), | |
2233 | ctxt, loc, | |
2234 | "mismatching types for argument %d of function \"%s\":" | |
2235 | " assignment to param %s (type: %s) from %s (type: %s)", | |
2236 | i + 1, | |
2237 | func->get_name ()->c_str (), | |
2238 | param->get_debug_string (), | |
2239 | param->get_type ()->get_debug_string (), | |
2240 | arg->get_debug_string (), | |
2241 | arg->get_type ()->get_debug_string ()); | |
2242 | } | |
2243 | ||
2244 | return (gcc_jit_rvalue *)ctxt->new_call (loc, | |
2245 | func, | |
2246 | numargs, | |
2247 | (gcc::jit::recording::rvalue **)args); | |
2248 | } | |
2249 | ||
2250 | /* Public entrypoint. See description in libgccjit.h. | |
2251 | ||
2252 | After error-checking, the real work is done by the | |
2253 | gcc::jit::recording::context::new_call_through_ptr method in | |
e53b6e56 | 2254 | jit-recording.cc. */ |
35485da9 DM |
2255 | |
2256 | gcc_jit_rvalue * | |
2257 | gcc_jit_context_new_call_through_ptr (gcc_jit_context *ctxt, | |
2258 | gcc_jit_location *loc, | |
2259 | gcc_jit_rvalue *fn_ptr, | |
2260 | int numargs, gcc_jit_rvalue **args) | |
2261 | { | |
2262 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 2263 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
2264 | /* LOC can be NULL. */ |
2265 | RETURN_NULL_IF_FAIL (fn_ptr, ctxt, loc, "NULL fn_ptr"); | |
2266 | if (numargs) | |
2267 | RETURN_NULL_IF_FAIL (args, ctxt, loc, "NULL args"); | |
2268 | ||
2269 | gcc::jit::recording::type *ptr_type = fn_ptr->get_type ()->dereference (); | |
2270 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
2271 | ptr_type, ctxt, loc, | |
2272 | "fn_ptr is not a ptr: %s" | |
2273 | " type: %s", | |
2274 | fn_ptr->get_debug_string (), | |
2275 | fn_ptr->get_type ()->get_debug_string ()); | |
2276 | ||
2277 | gcc::jit::recording::function_type *fn_type = | |
2278 | ptr_type->dyn_cast_function_type(); | |
2279 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
2280 | fn_type, ctxt, loc, | |
2281 | "fn_ptr is not a function ptr: %s" | |
2282 | " type: %s", | |
2283 | fn_ptr->get_debug_string (), | |
2284 | fn_ptr->get_type ()->get_debug_string ()); | |
2285 | ||
2286 | int min_num_params = fn_type->get_param_types ().length (); | |
2287 | bool is_variadic = fn_type->is_variadic (); | |
2288 | ||
2289 | RETURN_NULL_IF_FAIL_PRINTF3 ( | |
2290 | numargs >= min_num_params, | |
2291 | ctxt, loc, | |
2292 | "not enough arguments to fn_ptr: %s" | |
2293 | " (got %i args, expected %i)", | |
2294 | fn_ptr->get_debug_string (), | |
2295 | numargs, min_num_params); | |
2296 | ||
2297 | RETURN_NULL_IF_FAIL_PRINTF3 ( | |
2298 | (numargs == min_num_params || is_variadic), | |
2299 | ctxt, loc, | |
2300 | "too many arguments to fn_ptr: %s" | |
2301 | " (got %i args, expected %i)", | |
2302 | fn_ptr->get_debug_string (), | |
2303 | numargs, min_num_params); | |
2304 | ||
2305 | for (int i = 0; i < min_num_params; i++) | |
2306 | { | |
2307 | gcc::jit::recording::type *param_type = fn_type->get_param_types ()[i]; | |
2308 | gcc_jit_rvalue *arg = args[i]; | |
2309 | ||
2310 | RETURN_NULL_IF_FAIL_PRINTF3 ( | |
2311 | arg, | |
2312 | ctxt, loc, | |
2313 | "NULL argument %i to fn_ptr: %s" | |
2314 | " (type: %s)", | |
2315 | i + 1, | |
2316 | fn_ptr->get_debug_string (), | |
2317 | param_type->get_debug_string ()); | |
2318 | ||
2319 | RETURN_NULL_IF_FAIL_PRINTF6 ( | |
2320 | compatible_types (param_type, | |
2321 | arg->get_type ()), | |
2322 | ctxt, loc, | |
2323 | "mismatching types for argument %d of fn_ptr: %s:" | |
2324 | " assignment to param %d (type: %s) from %s (type: %s)", | |
2325 | i + 1, | |
2326 | fn_ptr->get_debug_string (), | |
2327 | i + 1, | |
2328 | param_type->get_debug_string (), | |
2329 | arg->get_debug_string (), | |
2330 | arg->get_type ()->get_debug_string ()); | |
2331 | } | |
2332 | ||
2333 | return (gcc_jit_rvalue *)( | |
2334 | ctxt->new_call_through_ptr (loc, | |
2335 | fn_ptr, | |
2336 | numargs, | |
2337 | (gcc::jit::recording::rvalue **)args)); | |
2338 | } | |
2339 | ||
2340 | /* Helper function for determining if we can cast an rvalue from SRC_TYPE | |
2341 | to DST_TYPE, for use by gcc_jit_context_new_cast. | |
2342 | ||
2343 | We only permit these kinds of cast: | |
2344 | ||
2345 | int <-> float | |
2346 | int <-> bool | |
2347 | P* <-> Q* for pointer types P and Q. */ | |
2348 | ||
2349 | static bool | |
2350 | is_valid_cast (gcc::jit::recording::type *src_type, | |
2351 | gcc_jit_type *dst_type) | |
2352 | { | |
2353 | bool src_is_int = src_type->is_int (); | |
2354 | bool dst_is_int = dst_type->is_int (); | |
2355 | bool src_is_float = src_type->is_float (); | |
2356 | bool dst_is_float = dst_type->is_float (); | |
2357 | bool src_is_bool = src_type->is_bool (); | |
2358 | bool dst_is_bool = dst_type->is_bool (); | |
2359 | ||
2360 | if (src_is_int) | |
2361 | if (dst_is_int || dst_is_float || dst_is_bool) | |
2362 | return true; | |
2363 | ||
2364 | if (src_is_float) | |
2365 | if (dst_is_int || dst_is_float) | |
2366 | return true; | |
2367 | ||
2368 | if (src_is_bool) | |
2369 | if (dst_is_int || dst_is_bool) | |
2370 | return true; | |
2371 | ||
2372 | /* Permit casts between pointer types. */ | |
2373 | gcc::jit::recording::type *deref_src_type = src_type->is_pointer (); | |
2374 | gcc::jit::recording::type *deref_dst_type = dst_type->is_pointer (); | |
2375 | if (deref_src_type && deref_dst_type) | |
2376 | return true; | |
2377 | ||
2378 | return false; | |
2379 | } | |
2380 | ||
2381 | /* Public entrypoint. See description in libgccjit.h. | |
2382 | ||
2383 | After error-checking, the real work is done by the | |
e53b6e56 | 2384 | gcc::jit::recording::context::new_cast method in jit-recording.cc. */ |
35485da9 DM |
2385 | |
2386 | gcc_jit_rvalue * | |
2387 | gcc_jit_context_new_cast (gcc_jit_context *ctxt, | |
2388 | gcc_jit_location *loc, | |
2389 | gcc_jit_rvalue *rvalue, | |
2390 | gcc_jit_type *type) | |
2391 | { | |
2392 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 2393 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
2394 | /* LOC can be NULL. */ |
2395 | RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); | |
2396 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); | |
2397 | RETURN_NULL_IF_FAIL_PRINTF3 ( | |
2398 | is_valid_cast (rvalue->get_type (), type), | |
2399 | ctxt, loc, | |
2400 | "cannot cast %s from type: %s to type: %s", | |
2401 | rvalue->get_debug_string (), | |
2402 | rvalue->get_type ()->get_debug_string (), | |
2403 | type->get_debug_string ()); | |
2404 | ||
2405 | return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc, rvalue, type)); | |
2406 | } | |
2407 | ||
2408 | /* Public entrypoint. See description in libgccjit.h. | |
2409 | ||
2410 | After error-checking, the real work is done by the | |
2411 | gcc::jit::recording::context::new_array_access method in | |
e53b6e56 | 2412 | jit-recording.cc. */ |
35485da9 DM |
2413 | |
2414 | extern gcc_jit_lvalue * | |
2415 | gcc_jit_context_new_array_access (gcc_jit_context *ctxt, | |
2416 | gcc_jit_location *loc, | |
2417 | gcc_jit_rvalue *ptr, | |
2418 | gcc_jit_rvalue *index) | |
2419 | { | |
2420 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); | |
eb4c16eb | 2421 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
2422 | /* LOC can be NULL. */ |
2423 | RETURN_NULL_IF_FAIL (ptr, ctxt, loc, "NULL ptr"); | |
2424 | RETURN_NULL_IF_FAIL (index, ctxt, loc, "NULL index"); | |
2425 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
2426 | ptr->get_type ()->dereference (), | |
2427 | ctxt, loc, | |
2428 | "ptr: %s (type: %s) is not a pointer or array", | |
2429 | ptr->get_debug_string (), | |
2430 | ptr->get_type ()->get_debug_string ()); | |
2431 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
2432 | index->get_type ()->is_numeric (), | |
2433 | ctxt, loc, | |
2434 | "index: %s (type: %s) is not of numeric type", | |
2435 | index->get_debug_string (), | |
2436 | index->get_type ()->get_debug_string ()); | |
2437 | ||
2438 | return (gcc_jit_lvalue *)ctxt->new_array_access (loc, ptr, index); | |
2439 | } | |
2440 | ||
2441 | /* Public entrypoint. See description in libgccjit.h. | |
2442 | ||
2443 | After error-checking, the real work is done by the | |
2444 | gcc::jit::recording::memento::get_context method in | |
2445 | jit-recording.h. */ | |
2446 | ||
2447 | gcc_jit_context * | |
2448 | gcc_jit_object_get_context (gcc_jit_object *obj) | |
2449 | { | |
2450 | RETURN_NULL_IF_FAIL (obj, NULL, NULL, "NULL object"); | |
2451 | ||
2452 | return static_cast <gcc_jit_context *> (obj->get_context ()); | |
2453 | } | |
2454 | ||
2455 | /* Public entrypoint. See description in libgccjit.h. | |
2456 | ||
2457 | After error-checking, the real work is done by the | |
2458 | gcc::jit::recording::memento::get_debug_string method in | |
e53b6e56 | 2459 | jit-recording.cc. */ |
35485da9 DM |
2460 | |
2461 | const char * | |
2462 | gcc_jit_object_get_debug_string (gcc_jit_object *obj) | |
2463 | { | |
2464 | RETURN_NULL_IF_FAIL (obj, NULL, NULL, "NULL object"); | |
2465 | ||
2466 | return obj->get_debug_string (); | |
2467 | } | |
2468 | ||
2469 | /* Public entrypoint. See description in libgccjit.h. | |
2470 | ||
2471 | After error-checking, the real work is done by the | |
2472 | gcc::jit::recording::lvalue::access_field method in | |
e53b6e56 | 2473 | jit-recording.cc. */ |
35485da9 DM |
2474 | |
2475 | gcc_jit_lvalue * | |
2476 | gcc_jit_lvalue_access_field (gcc_jit_lvalue *struct_, | |
2477 | gcc_jit_location *loc, | |
2478 | gcc_jit_field *field) | |
2479 | { | |
2480 | RETURN_NULL_IF_FAIL (struct_, NULL, loc, "NULL struct"); | |
35485da9 | 2481 | gcc::jit::recording::context *ctxt = struct_->m_ctxt; |
eb4c16eb DM |
2482 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2483 | /* LOC can be NULL. */ | |
35485da9 DM |
2484 | RETURN_NULL_IF_FAIL (field, ctxt, loc, "NULL field"); |
2485 | RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt, loc, | |
2486 | "field %s has not been placed in a struct", | |
2487 | field->get_debug_string ()); | |
41571b55 DM |
2488 | gcc::jit::recording::type *underlying_type = |
2489 | struct_->get_type (); | |
2490 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
2491 | (field->get_container ()->unqualified () | |
2492 | == underlying_type->unqualified ()), | |
2493 | struct_->m_ctxt, loc, | |
2494 | "%s is not a field of %s", | |
2495 | field->get_debug_string (), | |
2496 | underlying_type->get_debug_string ()); | |
35485da9 DM |
2497 | |
2498 | return (gcc_jit_lvalue *)struct_->access_field (loc, field); | |
2499 | } | |
2500 | ||
2501 | /* Public entrypoint. See description in libgccjit.h. | |
2502 | ||
2503 | After error-checking, the real work is done by the | |
2504 | gcc::jit::recording::rvalue::access_field method in | |
e53b6e56 | 2505 | jit-recording.cc. */ |
35485da9 DM |
2506 | |
2507 | gcc_jit_rvalue * | |
2508 | gcc_jit_rvalue_access_field (gcc_jit_rvalue *struct_, | |
2509 | gcc_jit_location *loc, | |
2510 | gcc_jit_field *field) | |
2511 | { | |
2512 | RETURN_NULL_IF_FAIL (struct_, NULL, loc, "NULL struct"); | |
35485da9 | 2513 | gcc::jit::recording::context *ctxt = struct_->m_ctxt; |
eb4c16eb DM |
2514 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2515 | /* LOC can be NULL. */ | |
35485da9 DM |
2516 | RETURN_NULL_IF_FAIL (field, ctxt, loc, "NULL field"); |
2517 | RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt, loc, | |
2518 | "field %s has not been placed in a struct", | |
2519 | field->get_debug_string ()); | |
41571b55 DM |
2520 | gcc::jit::recording::type *underlying_type = |
2521 | struct_->get_type (); | |
2522 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
2523 | (field->get_container ()->unqualified () | |
2524 | == underlying_type->unqualified ()), | |
2525 | struct_->m_ctxt, loc, | |
2526 | "%s is not a field of %s", | |
2527 | field->get_debug_string (), | |
2528 | underlying_type->get_debug_string ()); | |
35485da9 DM |
2529 | |
2530 | return (gcc_jit_rvalue *)struct_->access_field (loc, field); | |
2531 | } | |
2532 | ||
2533 | /* Public entrypoint. See description in libgccjit.h. | |
2534 | ||
2535 | After error-checking, the real work is done by the | |
2536 | gcc::jit::recording::rvalue::deference_field method in | |
e53b6e56 | 2537 | jit-recording.cc. */ |
35485da9 DM |
2538 | |
2539 | gcc_jit_lvalue * | |
2540 | gcc_jit_rvalue_dereference_field (gcc_jit_rvalue *ptr, | |
2541 | gcc_jit_location *loc, | |
2542 | gcc_jit_field *field) | |
2543 | { | |
2544 | RETURN_NULL_IF_FAIL (ptr, NULL, loc, "NULL ptr"); | |
eb4c16eb | 2545 | JIT_LOG_FUNC (ptr->get_context ()->get_logger ()); |
35485da9 DM |
2546 | /* LOC can be NULL. */ |
2547 | RETURN_NULL_IF_FAIL (field, NULL, loc, "NULL field"); | |
2548 | gcc::jit::recording::type *underlying_type = | |
2549 | ptr->get_type ()->is_pointer (); | |
2550 | RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt, loc, | |
2551 | "field %s has not been placed in a struct", | |
2552 | field->get_debug_string ()); | |
2553 | RETURN_NULL_IF_FAIL_PRINTF3 ( | |
2554 | underlying_type, | |
2555 | ptr->m_ctxt, loc, | |
2556 | "dereference of non-pointer %s (type: %s) when accessing ->%s", | |
2557 | ptr->get_debug_string (), | |
2558 | ptr->get_type ()->get_debug_string (), | |
2559 | field->get_debug_string ()); | |
2560 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
2561 | (field->get_container ()->unqualified () | |
2562 | == underlying_type->unqualified ()), | |
2563 | ptr->m_ctxt, loc, | |
2564 | "%s is not a field of %s", | |
2565 | field->get_debug_string (), | |
2566 | underlying_type->get_debug_string ()); | |
2567 | ||
2568 | return (gcc_jit_lvalue *)ptr->dereference_field (loc, field); | |
2569 | } | |
2570 | ||
2571 | /* Public entrypoint. See description in libgccjit.h. | |
2572 | ||
2573 | After error-checking, the real work is done by the | |
2574 | gcc::jit::recording::rvalue::deference method in | |
e53b6e56 | 2575 | jit-recording.cc. */ |
35485da9 DM |
2576 | |
2577 | gcc_jit_lvalue * | |
2578 | gcc_jit_rvalue_dereference (gcc_jit_rvalue *rvalue, | |
2579 | gcc_jit_location *loc) | |
2580 | { | |
2581 | RETURN_NULL_IF_FAIL (rvalue, NULL, loc, "NULL rvalue"); | |
eb4c16eb | 2582 | JIT_LOG_FUNC (rvalue->get_context ()->get_logger ()); |
35485da9 DM |
2583 | /* LOC can be NULL. */ |
2584 | ||
2585 | gcc::jit::recording::type *underlying_type = | |
2586 | rvalue->get_type ()->is_pointer (); | |
2587 | ||
2588 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
2589 | underlying_type, | |
2590 | rvalue->m_ctxt, loc, | |
2591 | "dereference of non-pointer %s (type: %s)", | |
2592 | rvalue->get_debug_string (), | |
2593 | rvalue->get_type ()->get_debug_string ()); | |
2594 | ||
c211cd23 DM |
2595 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
2596 | !underlying_type->is_void (), | |
2597 | rvalue->m_ctxt, loc, | |
2598 | "dereference of void pointer %s (type: %s)", | |
2599 | rvalue->get_debug_string (), | |
2600 | rvalue->get_type ()->get_debug_string ()); | |
2601 | ||
35485da9 DM |
2602 | return (gcc_jit_lvalue *)rvalue->dereference (loc); |
2603 | } | |
2604 | ||
2605 | /* Public entrypoint. See description in libgccjit.h. | |
2606 | ||
2607 | After error-checking, the real work is done by the | |
e53b6e56 | 2608 | gcc::jit::recording::lvalue::get_address method in jit-recording.cc. */ |
35485da9 DM |
2609 | |
2610 | gcc_jit_rvalue * | |
2611 | gcc_jit_lvalue_get_address (gcc_jit_lvalue *lvalue, | |
2612 | gcc_jit_location *loc) | |
2613 | { | |
2614 | RETURN_NULL_IF_FAIL (lvalue, NULL, loc, "NULL lvalue"); | |
eb4c16eb | 2615 | JIT_LOG_FUNC (lvalue->get_context ()->get_logger ()); |
35485da9 DM |
2616 | /* LOC can be NULL. */ |
2617 | ||
2618 | return (gcc_jit_rvalue *)lvalue->get_address (loc); | |
2619 | } | |
2620 | ||
c6b7f68b AB |
2621 | /* Public entrypoint. See description in libgccjit.h. |
2622 | ||
2623 | After error-checking, the real work is done by the | |
e53b6e56 | 2624 | gcc::jit::recording::lvalue::set_tls_model method in jit-recording.cc. */ |
c6b7f68b AB |
2625 | |
2626 | void | |
2627 | gcc_jit_lvalue_set_tls_model (gcc_jit_lvalue *lvalue, | |
2628 | enum gcc_jit_tls_model model) | |
2629 | { | |
2630 | RETURN_IF_FAIL (lvalue, NULL, NULL, "NULL lvalue"); | |
2631 | JIT_LOG_FUNC (lvalue->get_context ()->get_logger ()); | |
2632 | RETURN_IF_FAIL_PRINTF1 (lvalue->is_global (), lvalue->get_context (), NULL, | |
2633 | "lvalue \"%s\" not a global", | |
2634 | lvalue->get_debug_string ()); | |
2635 | ||
2636 | lvalue->set_tls_model (model); | |
2637 | } | |
2638 | ||
0b52083e AB |
2639 | /* Public entrypoint. See description in libgccjit.h. |
2640 | ||
2641 | After error-checking, the real work is done by the | |
e53b6e56 | 2642 | gcc::jit::recording::lvalue::set_link_section method in jit-recording.cc. */ |
0b52083e AB |
2643 | |
2644 | void | |
2645 | gcc_jit_lvalue_set_link_section (gcc_jit_lvalue *lvalue, | |
2646 | const char *section_name) | |
2647 | { | |
2648 | RETURN_IF_FAIL (section_name, NULL, NULL, "NULL section_name"); | |
2649 | lvalue->set_link_section (section_name); | |
2650 | } | |
2651 | ||
35485da9 DM |
2652 | /* Public entrypoint. See description in libgccjit.h. |
2653 | ||
2654 | After error-checking, the real work is done by the | |
e53b6e56 | 2655 | gcc::jit::recording::function::new_local method in jit-recording.cc. */ |
35485da9 DM |
2656 | |
2657 | gcc_jit_lvalue * | |
2658 | gcc_jit_function_new_local (gcc_jit_function *func, | |
2659 | gcc_jit_location *loc, | |
2660 | gcc_jit_type *type, | |
2661 | const char *name) | |
2662 | { | |
2663 | RETURN_NULL_IF_FAIL (func, NULL, loc, "NULL function"); | |
35485da9 | 2664 | gcc::jit::recording::context *ctxt = func->m_ctxt; |
eb4c16eb DM |
2665 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2666 | /* LOC can be NULL. */ | |
35485da9 DM |
2667 | RETURN_NULL_IF_FAIL (func->get_kind () != GCC_JIT_FUNCTION_IMPORTED, |
2668 | ctxt, loc, | |
2669 | "Cannot add locals to an imported function"); | |
2670 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); | |
2671 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); | |
58c5ad40 | 2672 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
3457d39e DM |
2673 | type->has_known_size (), |
2674 | ctxt, loc, | |
58c5ad40 DM |
2675 | "unknown size for local \"%s\" (type: %s)", |
2676 | name, | |
3457d39e | 2677 | type->get_debug_string ()); |
6f7585de DM |
2678 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
2679 | !type->is_void (), | |
2680 | ctxt, loc, | |
2681 | "void type for local \"%s\"", | |
2682 | name); | |
35485da9 DM |
2683 | |
2684 | return (gcc_jit_lvalue *)func->new_local (loc, type, name); | |
2685 | } | |
2686 | ||
2687 | /* Public entrypoint. See description in libgccjit.h. | |
2688 | ||
2689 | After error-checking, the real work is done by the | |
e53b6e56 | 2690 | gcc::jit::recording::block::add_eval method in jit-recording.cc. */ |
35485da9 DM |
2691 | |
2692 | void | |
2693 | gcc_jit_block_add_eval (gcc_jit_block *block, | |
2694 | gcc_jit_location *loc, | |
2695 | gcc_jit_rvalue *rvalue) | |
2696 | { | |
2697 | RETURN_IF_NOT_VALID_BLOCK (block, loc); | |
35485da9 | 2698 | gcc::jit::recording::context *ctxt = block->get_context (); |
eb4c16eb DM |
2699 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2700 | /* LOC can be NULL. */ | |
35485da9 DM |
2701 | RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); |
2702 | ||
f6f2b019 DM |
2703 | gcc::jit::recording::statement *stmt = block->add_eval (loc, rvalue); |
2704 | ||
2705 | /* "stmt" should be good enough to be usable in error-messages, | |
2706 | but might still not be compilable; perform some more | |
2707 | error-checking here. We do this here so that the error messages | |
2708 | can contain a stringified version of "stmt", whilst appearing | |
2709 | as close as possible to the point of failure. */ | |
2710 | rvalue->verify_valid_within_stmt (__func__, stmt); | |
35485da9 DM |
2711 | } |
2712 | ||
2713 | /* Public entrypoint. See description in libgccjit.h. | |
2714 | ||
2715 | After error-checking, the real work is done by the | |
2716 | gcc::jit::recording::block::add_assignment method in | |
e53b6e56 | 2717 | jit-recording.cc. */ |
35485da9 DM |
2718 | |
2719 | void | |
2720 | gcc_jit_block_add_assignment (gcc_jit_block *block, | |
2721 | gcc_jit_location *loc, | |
2722 | gcc_jit_lvalue *lvalue, | |
2723 | gcc_jit_rvalue *rvalue) | |
2724 | { | |
2725 | RETURN_IF_NOT_VALID_BLOCK (block, loc); | |
35485da9 | 2726 | gcc::jit::recording::context *ctxt = block->get_context (); |
eb4c16eb DM |
2727 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2728 | /* LOC can be NULL. */ | |
35485da9 DM |
2729 | RETURN_IF_FAIL (lvalue, ctxt, loc, "NULL lvalue"); |
2730 | RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); | |
2731 | RETURN_IF_FAIL_PRINTF4 ( | |
2732 | compatible_types (lvalue->get_type (), | |
2733 | rvalue->get_type ()), | |
2734 | ctxt, loc, | |
2735 | "mismatching types:" | |
2736 | " assignment to %s (type: %s) from %s (type: %s)", | |
2737 | lvalue->get_debug_string (), | |
2738 | lvalue->get_type ()->get_debug_string (), | |
2739 | rvalue->get_debug_string (), | |
2740 | rvalue->get_type ()->get_debug_string ()); | |
2741 | ||
f6f2b019 DM |
2742 | gcc::jit::recording::statement *stmt = block->add_assignment (loc, lvalue, rvalue); |
2743 | ||
2744 | /* "stmt" should be good enough to be usable in error-messages, | |
2745 | but might still not be compilable; perform some more | |
2746 | error-checking here. We do this here so that the error messages | |
2747 | can contain a stringified version of "stmt", whilst appearing | |
2748 | as close as possible to the point of failure. */ | |
2749 | lvalue->verify_valid_within_stmt (__func__, stmt); | |
2750 | rvalue->verify_valid_within_stmt (__func__, stmt); | |
35485da9 DM |
2751 | } |
2752 | ||
2753 | /* Public entrypoint. See description in libgccjit.h. | |
2754 | ||
2755 | After error-checking, the real work is done by the | |
2756 | gcc::jit::recording::block::add_assignment_op method in | |
e53b6e56 | 2757 | jit-recording.cc. */ |
35485da9 DM |
2758 | |
2759 | void | |
2760 | gcc_jit_block_add_assignment_op (gcc_jit_block *block, | |
2761 | gcc_jit_location *loc, | |
2762 | gcc_jit_lvalue *lvalue, | |
2763 | enum gcc_jit_binary_op op, | |
2764 | gcc_jit_rvalue *rvalue) | |
2765 | { | |
2766 | RETURN_IF_NOT_VALID_BLOCK (block, loc); | |
35485da9 | 2767 | gcc::jit::recording::context *ctxt = block->get_context (); |
eb4c16eb DM |
2768 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2769 | /* LOC can be NULL. */ | |
35485da9 DM |
2770 | RETURN_IF_FAIL (lvalue, ctxt, loc, "NULL lvalue"); |
2771 | RETURN_IF_FAIL_PRINTF1 ( | |
2772 | valid_binary_op_p (op), | |
2773 | ctxt, loc, | |
2774 | "unrecognized value for enum gcc_jit_binary_op: %i", | |
2775 | op); | |
2776 | RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); | |
96a87981 DM |
2777 | RETURN_IF_FAIL_PRINTF4 ( |
2778 | compatible_types (lvalue->get_type (), | |
2779 | rvalue->get_type ()), | |
2780 | ctxt, loc, | |
2781 | "mismatching types:" | |
2782 | " assignment to %s (type: %s) involving %s (type: %s)", | |
2783 | lvalue->get_debug_string (), | |
2784 | lvalue->get_type ()->get_debug_string (), | |
2785 | rvalue->get_debug_string (), | |
2786 | rvalue->get_type ()->get_debug_string ()); | |
35485da9 | 2787 | |
f6f2b019 DM |
2788 | gcc::jit::recording::statement *stmt = block->add_assignment_op (loc, lvalue, op, rvalue); |
2789 | ||
2790 | /* "stmt" should be good enough to be usable in error-messages, | |
2791 | but might still not be compilable; perform some more | |
2792 | error-checking here. We do this here so that the error messages | |
2793 | can contain a stringified version of "stmt", whilst appearing | |
2794 | as close as possible to the point of failure. */ | |
2795 | lvalue->verify_valid_within_stmt (__func__, stmt); | |
2796 | rvalue->verify_valid_within_stmt (__func__, stmt); | |
35485da9 DM |
2797 | } |
2798 | ||
2799 | /* Internal helper function for determining if rvalue BOOLVAL is of | |
2800 | boolean type. For use by gcc_jit_block_end_with_conditional. */ | |
2801 | ||
2802 | static bool | |
2803 | is_bool (gcc_jit_rvalue *boolval) | |
2804 | { | |
2805 | gcc::jit::recording::type *actual_type = boolval->get_type (); | |
2806 | gcc::jit::recording::type *bool_type = | |
2807 | boolval->m_ctxt->get_type (GCC_JIT_TYPE_BOOL); | |
2808 | return actual_type == bool_type; | |
2809 | } | |
2810 | ||
2811 | /* Public entrypoint. See description in libgccjit.h. | |
2812 | ||
2813 | After error-checking, the real work is done by the | |
2814 | gcc::jit::recording::block::end_with_conditional method in | |
e53b6e56 | 2815 | jit-recording.cc. */ |
35485da9 DM |
2816 | |
2817 | void | |
2818 | gcc_jit_block_end_with_conditional (gcc_jit_block *block, | |
2819 | gcc_jit_location *loc, | |
2820 | gcc_jit_rvalue *boolval, | |
2821 | gcc_jit_block *on_true, | |
2822 | gcc_jit_block *on_false) | |
2823 | { | |
2824 | RETURN_IF_NOT_VALID_BLOCK (block, loc); | |
35485da9 | 2825 | gcc::jit::recording::context *ctxt = block->get_context (); |
eb4c16eb DM |
2826 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2827 | /* LOC can be NULL. */ | |
35485da9 DM |
2828 | RETURN_IF_FAIL (boolval, ctxt, loc, "NULL boolval"); |
2829 | RETURN_IF_FAIL_PRINTF2 ( | |
2830 | is_bool (boolval), ctxt, loc, | |
2831 | "%s (type: %s) is not of boolean type ", | |
2832 | boolval->get_debug_string (), | |
2833 | boolval->get_type ()->get_debug_string ()); | |
2834 | RETURN_IF_FAIL (on_true, ctxt, loc, "NULL on_true"); | |
2835 | RETURN_IF_FAIL (on_true, ctxt, loc, "NULL on_false"); | |
2836 | RETURN_IF_FAIL_PRINTF4 ( | |
2837 | block->get_function () == on_true->get_function (), | |
2838 | ctxt, loc, | |
2839 | "\"on_true\" block is not in same function:" | |
2840 | " source block %s is in function %s" | |
2841 | " whereas target block %s is in function %s", | |
2842 | block->get_debug_string (), | |
2843 | block->get_function ()->get_debug_string (), | |
2844 | on_true->get_debug_string (), | |
2845 | on_true->get_function ()->get_debug_string ()); | |
2846 | RETURN_IF_FAIL_PRINTF4 ( | |
2847 | block->get_function () == on_false->get_function (), | |
2848 | ctxt, loc, | |
2849 | "\"on_false\" block is not in same function:" | |
2850 | " source block %s is in function %s" | |
2851 | " whereas target block %s is in function %s", | |
2852 | block->get_debug_string (), | |
2853 | block->get_function ()->get_debug_string (), | |
2854 | on_false->get_debug_string (), | |
2855 | on_false->get_function ()->get_debug_string ()); | |
2856 | ||
f6f2b019 DM |
2857 | gcc::jit::recording::statement *stmt = block->end_with_conditional (loc, boolval, on_true, on_false); |
2858 | ||
2859 | /* "stmt" should be good enough to be usable in error-messages, | |
2860 | but might still not be compilable; perform some more | |
2861 | error-checking here. We do this here so that the error messages | |
2862 | can contain a stringified version of "stmt", whilst appearing | |
2863 | as close as possible to the point of failure. */ | |
2864 | boolval->verify_valid_within_stmt (__func__, stmt); | |
35485da9 DM |
2865 | } |
2866 | ||
2867 | /* Public entrypoint. See description in libgccjit.h. | |
2868 | ||
2869 | After error-checking, the real work is done by the | |
2870 | gcc::jit::recording::block::add_comment method in | |
e53b6e56 | 2871 | jit-recording.cc. */ |
35485da9 DM |
2872 | |
2873 | void | |
2874 | gcc_jit_block_add_comment (gcc_jit_block *block, | |
2875 | gcc_jit_location *loc, | |
2876 | const char *text) | |
2877 | { | |
2878 | RETURN_IF_NOT_VALID_BLOCK (block, loc); | |
35485da9 | 2879 | gcc::jit::recording::context *ctxt = block->get_context (); |
eb4c16eb DM |
2880 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2881 | /* LOC can be NULL. */ | |
35485da9 DM |
2882 | RETURN_IF_FAIL (text, ctxt, loc, "NULL text"); |
2883 | ||
2884 | block->add_comment (loc, text); | |
2885 | } | |
2886 | ||
2887 | /* Public entrypoint. See description in libgccjit.h. | |
2888 | ||
2889 | After error-checking, the real work is done by the | |
2890 | gcc::jit::recording::block::end_with_jump method in | |
e53b6e56 | 2891 | jit-recording.cc. */ |
35485da9 DM |
2892 | |
2893 | void | |
2894 | gcc_jit_block_end_with_jump (gcc_jit_block *block, | |
2895 | gcc_jit_location *loc, | |
2896 | gcc_jit_block *target) | |
2897 | { | |
2898 | RETURN_IF_NOT_VALID_BLOCK (block, loc); | |
35485da9 | 2899 | gcc::jit::recording::context *ctxt = block->get_context (); |
eb4c16eb DM |
2900 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2901 | /* LOC can be NULL. */ | |
35485da9 DM |
2902 | RETURN_IF_FAIL (target, ctxt, loc, "NULL target"); |
2903 | RETURN_IF_FAIL_PRINTF4 ( | |
2904 | block->get_function () == target->get_function (), | |
2905 | ctxt, loc, | |
2906 | "target block is not in same function:" | |
2907 | " source block %s is in function %s" | |
2908 | " whereas target block %s is in function %s", | |
2909 | block->get_debug_string (), | |
2910 | block->get_function ()->get_debug_string (), | |
2911 | target->get_debug_string (), | |
2912 | target->get_function ()->get_debug_string ()); | |
2913 | ||
2914 | block->end_with_jump (loc, target); | |
2915 | } | |
2916 | ||
2917 | /* Public entrypoint. See description in libgccjit.h. | |
2918 | ||
2919 | After error-checking, the real work is done by the | |
2920 | gcc::jit::recording::block::end_with_return method in | |
e53b6e56 | 2921 | jit-recording.cc. */ |
35485da9 DM |
2922 | |
2923 | void | |
2924 | gcc_jit_block_end_with_return (gcc_jit_block *block, | |
2925 | gcc_jit_location *loc, | |
2926 | gcc_jit_rvalue *rvalue) | |
2927 | { | |
2928 | RETURN_IF_NOT_VALID_BLOCK (block, loc); | |
35485da9 | 2929 | gcc::jit::recording::context *ctxt = block->get_context (); |
eb4c16eb DM |
2930 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2931 | /* LOC can be NULL. */ | |
35485da9 DM |
2932 | gcc::jit::recording::function *func = block->get_function (); |
2933 | RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); | |
2934 | RETURN_IF_FAIL_PRINTF4 ( | |
2935 | compatible_types ( | |
2936 | func->get_return_type (), | |
2937 | rvalue->get_type ()), | |
2938 | ctxt, loc, | |
2939 | "mismatching types:" | |
2940 | " return of %s (type: %s) in function %s (return type: %s)", | |
2941 | rvalue->get_debug_string (), | |
2942 | rvalue->get_type ()->get_debug_string (), | |
2943 | func->get_debug_string (), | |
2944 | func->get_return_type ()->get_debug_string ()); | |
2945 | ||
f6f2b019 DM |
2946 | gcc::jit::recording::statement *stmt = block->end_with_return (loc, rvalue); |
2947 | ||
2948 | /* "stmt" should be good enough to be usable in error-messages, | |
2949 | but might still not be compilable; perform some more | |
2950 | error-checking here. We do this here so that the error messages | |
2951 | can contain a stringified version of "stmt", whilst appearing | |
2952 | as close as possible to the point of failure. */ | |
2953 | rvalue->verify_valid_within_stmt (__func__, stmt); | |
35485da9 DM |
2954 | } |
2955 | ||
2956 | /* Public entrypoint. See description in libgccjit.h. | |
2957 | ||
2958 | After error-checking, the real work is done by the | |
2959 | gcc::jit::recording::block::end_with_return method in | |
e53b6e56 | 2960 | jit-recording.cc. */ |
35485da9 DM |
2961 | |
2962 | void | |
2963 | gcc_jit_block_end_with_void_return (gcc_jit_block *block, | |
2964 | gcc_jit_location *loc) | |
2965 | { | |
2966 | RETURN_IF_NOT_VALID_BLOCK (block, loc); | |
35485da9 | 2967 | gcc::jit::recording::context *ctxt = block->get_context (); |
eb4c16eb DM |
2968 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2969 | /* LOC can be NULL. */ | |
35485da9 DM |
2970 | gcc::jit::recording::function *func = block->get_function (); |
2971 | RETURN_IF_FAIL_PRINTF2 ( | |
2972 | func->get_return_type () == ctxt->get_type (GCC_JIT_TYPE_VOID), | |
2973 | ctxt, loc, | |
2974 | "mismatching types:" | |
2975 | " void return in function %s (return type: %s)", | |
2976 | func->get_debug_string (), | |
2977 | func->get_return_type ()->get_debug_string ()); | |
2978 | ||
f6f2b019 | 2979 | block->end_with_return (loc, NULL); |
35485da9 DM |
2980 | } |
2981 | ||
ec5d0088 DM |
2982 | /* Public entrypoint. See description in libgccjit.h. |
2983 | ||
2984 | After error-checking, the real work is done by the | |
2985 | gcc::jit::recording::context::new_case method in | |
e53b6e56 | 2986 | jit-recording.cc. */ |
ec5d0088 DM |
2987 | |
2988 | gcc_jit_case * | |
2989 | gcc_jit_context_new_case (gcc_jit_context *ctxt, | |
2990 | gcc_jit_rvalue *min_value, | |
2991 | gcc_jit_rvalue *max_value, | |
2992 | gcc_jit_block *block) | |
2993 | { | |
2994 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
2995 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
2996 | RETURN_NULL_IF_FAIL (min_value, ctxt, NULL, "NULL min_value"); | |
2997 | RETURN_NULL_IF_FAIL (max_value, ctxt, NULL, "NULL max_value"); | |
2998 | RETURN_NULL_IF_FAIL (block, ctxt, NULL, "NULL block"); | |
2999 | ||
3000 | RETURN_NULL_IF_FAIL_PRINTF1 (min_value->is_constant (), ctxt, NULL, | |
3001 | "min_value is not a constant: %s", | |
3002 | min_value->get_debug_string ()); | |
3003 | RETURN_NULL_IF_FAIL_PRINTF1 (max_value->is_constant (), ctxt, NULL, | |
3004 | "max_value is not a constant: %s", | |
3005 | max_value->get_debug_string ()); | |
3006 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
3007 | min_value->get_type ()->is_int (), | |
3008 | ctxt, NULL, | |
3009 | "min_value: %s (type: %s) is not of integer type", | |
3010 | min_value->get_debug_string (), | |
3011 | min_value->get_type ()->get_debug_string ()); | |
3012 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
3013 | max_value->get_type ()->is_int (), | |
3014 | ctxt, NULL, | |
3015 | "max_value: %s (type: %s) is not of integer type", | |
3016 | max_value->get_debug_string (), | |
3017 | max_value->get_type ()->get_debug_string ()); | |
3018 | ||
3019 | wide_int wi_min, wi_max; | |
3020 | if (!min_value->get_wide_int (&wi_min)) | |
3021 | gcc_unreachable (); | |
3022 | if (!max_value->get_wide_int (&wi_max)) | |
3023 | gcc_unreachable (); | |
3024 | RETURN_NULL_IF_FAIL_PRINTF2 ( | |
3025 | wi::les_p (wi_min, wi_max), | |
3026 | ctxt, NULL, | |
3027 | "min_value: %s > max_value: %s", | |
3028 | min_value->get_debug_string (), | |
3029 | max_value->get_debug_string ()); | |
3030 | return (gcc_jit_case *)ctxt->new_case (min_value, | |
3031 | max_value, | |
3032 | block); | |
3033 | } | |
3034 | ||
3035 | /* Public entrypoint. See description in libgccjit.h. | |
3036 | ||
3037 | After error-checking, this calls the trivial | |
3038 | gcc::jit::recording::memento::as_object method (a case is a | |
3039 | memento), in jit-recording.h. */ | |
3040 | ||
3041 | gcc_jit_object * | |
3042 | gcc_jit_case_as_object (gcc_jit_case *case_) | |
3043 | { | |
3044 | RETURN_NULL_IF_FAIL (case_, NULL, NULL, "NULL case"); | |
3045 | ||
3046 | return static_cast <gcc_jit_object *> (case_->as_object ()); | |
3047 | } | |
3048 | ||
3049 | /* Helper function for gcc_jit_block_end_with_switch and | |
3050 | valid_case_for_switch. */ | |
3051 | ||
3052 | static bool | |
3053 | valid_dest_for_switch (gcc::jit::recording::context *ctxt, | |
3054 | gcc_jit_location *loc, | |
3055 | const char *api_funcname, | |
3056 | gcc::jit::recording::block *switch_block, | |
3057 | gcc::jit::recording::block *dest_block, | |
3058 | const char *dest_block_desc) | |
3059 | { | |
3060 | if (!dest_block) | |
3061 | { | |
3062 | jit_error (ctxt, loc, "%s: NULL %s", api_funcname, dest_block_desc); | |
3063 | return false; | |
3064 | } | |
3065 | gcc::jit::recording::function *switch_fn = switch_block->get_function (); | |
3066 | gcc::jit::recording::function *dest_fn = dest_block->get_function (); | |
3067 | if (switch_fn != dest_fn) | |
3068 | { | |
3069 | jit_error (ctxt, loc, | |
3070 | "%s: %s is not in same function:" | |
3071 | " switch block %s is in function %s" | |
3072 | " whereas %s %s is in function %s", | |
3073 | api_funcname, | |
3074 | dest_block_desc, | |
3075 | switch_block->get_debug_string (), | |
3076 | switch_fn->get_debug_string (), | |
3077 | dest_block_desc, | |
3078 | dest_block->get_debug_string (), | |
3079 | dest_fn->get_debug_string ()); | |
3080 | return false; | |
3081 | } | |
3082 | return true; | |
3083 | } | |
3084 | ||
3085 | /* Helper function for gcc_jit_block_end_with_switch. */ | |
3086 | ||
3087 | static bool | |
3088 | valid_case_for_switch (gcc::jit::recording::context *ctxt, | |
3089 | gcc_jit_location *loc, | |
3090 | const char *api_funcname, | |
3091 | gcc_jit_block *switch_block, | |
3092 | gcc_jit_rvalue *expr, | |
3093 | gcc_jit_case *case_, | |
3094 | const char *case_desc, | |
3095 | int case_idx) | |
3096 | { | |
3097 | if (!case_) | |
3098 | { | |
3099 | jit_error (ctxt, loc, | |
3100 | "%s:" | |
3101 | " NULL case %i", | |
3102 | api_funcname, | |
3103 | case_idx); | |
3104 | return false; | |
3105 | } | |
3106 | if (!valid_dest_for_switch (ctxt, loc, | |
3107 | api_funcname, | |
3108 | switch_block, | |
3109 | case_->get_dest_block (), | |
3110 | case_desc)) | |
3111 | return false; | |
3112 | gcc::jit::recording::type *expr_type = expr->get_type (); | |
3113 | if (expr_type != case_->get_min_value ()->get_type ()) | |
3114 | { | |
3115 | jit_error (ctxt, loc, | |
3116 | "%s:" | |
3117 | " mismatching types between case and expression:" | |
3118 | " cases[%i]->min_value: %s (type: %s)" | |
3119 | " expr: %s (type: %s)", | |
3120 | api_funcname, | |
3121 | case_idx, | |
3122 | case_->get_min_value ()->get_debug_string (), | |
3123 | case_->get_min_value ()->get_type ()->get_debug_string (), | |
3124 | expr->get_debug_string (), | |
3125 | expr_type->get_debug_string ()); | |
3126 | return false; | |
3127 | } | |
3128 | if (expr_type != case_->get_max_value ()->get_type ()) | |
3129 | { | |
3130 | jit_error (ctxt, loc, | |
3131 | "%s:" | |
3132 | " mismatching types between case and expression:" | |
3133 | " cases[%i]->max_value: %s (type: %s)" | |
3134 | " expr: %s (type: %s)", | |
3135 | api_funcname, | |
3136 | case_idx, | |
3137 | case_->get_max_value ()->get_debug_string (), | |
3138 | case_->get_max_value ()->get_type ()->get_debug_string (), | |
3139 | expr->get_debug_string (), | |
3140 | expr_type->get_debug_string ()); | |
3141 | return false; | |
3142 | } | |
3143 | return true; | |
3144 | } | |
3145 | ||
3146 | /* A class for holding the data we need to perform error-checking | |
3147 | on a libgccjit API call. */ | |
3148 | ||
3149 | class api_call_validator | |
3150 | { | |
3151 | public: | |
3152 | api_call_validator (gcc::jit::recording::context *ctxt, | |
3153 | gcc_jit_location *loc, | |
3154 | const char *funcname) | |
3155 | : m_ctxt (ctxt), | |
3156 | m_loc (loc), | |
3157 | m_funcname (funcname) | |
3158 | {} | |
3159 | ||
3160 | protected: | |
3161 | gcc::jit::recording::context *m_ctxt; | |
3162 | gcc_jit_location *m_loc; | |
3163 | const char *m_funcname; | |
3164 | }; | |
3165 | ||
3166 | /* A class for verifying that the ranges of cases within | |
3167 | gcc_jit_block_end_with_switch don't overlap. */ | |
3168 | ||
3169 | class case_range_validator : public api_call_validator | |
3170 | { | |
3171 | public: | |
3172 | case_range_validator (gcc::jit::recording::context *ctxt, | |
3173 | gcc_jit_location *loc, | |
3174 | const char *funcname); | |
3175 | ||
3176 | bool | |
3177 | validate (gcc_jit_case *case_, int idx); | |
3178 | ||
3179 | private: | |
3180 | static int | |
3181 | case_compare (gcc::jit::recording::rvalue *k1, | |
3182 | gcc::jit::recording::rvalue *k2); | |
3183 | ||
3184 | static wide_int | |
3185 | get_wide_int (gcc::jit::recording::rvalue *k); | |
3186 | ||
3187 | private: | |
3188 | typed_splay_tree <gcc::jit::recording::rvalue *, gcc_jit_case *> m_cases; | |
3189 | }; | |
3190 | ||
3191 | /* case_range_validator's ctor. */ | |
3192 | ||
3193 | case_range_validator::case_range_validator (gcc::jit::recording::context *ctxt, | |
3194 | gcc_jit_location *loc, | |
3195 | const char *funcname) | |
3196 | : api_call_validator (ctxt, loc, funcname), | |
3197 | m_cases (case_compare, NULL, NULL) | |
3198 | { | |
3199 | } | |
3200 | ||
3201 | /* Ensure that the range of CASE_ does not overlap with any of the | |
3202 | ranges of cases we've already seen. | |
3203 | Return true if everything is OK. | |
3204 | Return false and emit an error if there is an overlap. | |
e53b6e56 | 3205 | Compare with c-family/c-common.cc:c_add_case_label. */ |
ec5d0088 DM |
3206 | |
3207 | bool | |
3208 | case_range_validator::validate (gcc_jit_case *case_, | |
3209 | int case_idx) | |
3210 | { | |
3211 | /* Look up the LOW_VALUE in the table of case labels we already | |
3212 | have. */ | |
3213 | gcc_jit_case *other = m_cases.lookup (case_->get_min_value ()); | |
3214 | ||
3215 | /* If there was not an exact match, check for overlapping ranges. */ | |
3216 | if (!other) | |
3217 | { | |
3218 | gcc_jit_case *pred; | |
3219 | gcc_jit_case *succ; | |
3220 | ||
3221 | /* Even though there wasn't an exact match, there might be an | |
3222 | overlap between this case range and another case range. | |
3223 | Since we've (inductively) not allowed any overlapping case | |
3224 | ranges, we simply need to find the greatest low case label | |
3225 | that is smaller that CASE_MIN_VALUE, and the smallest low case | |
3226 | label that is greater than CASE_MAX_VALUE. If there is an overlap | |
3227 | it will occur in one of these two ranges. */ | |
3228 | pred = m_cases.predecessor (case_->get_min_value ()); | |
3229 | succ = m_cases.successor (case_->get_max_value ()); | |
3230 | ||
3231 | /* Check to see if the PRED overlaps. It is smaller than | |
3232 | the LOW_VALUE, so we only need to check its max value. */ | |
3233 | if (pred) | |
3234 | { | |
3235 | wide_int wi_case_min = get_wide_int (case_->get_min_value ()); | |
3236 | wide_int wi_pred_max = get_wide_int (pred->get_max_value ()); | |
3237 | if (wi::ges_p (wi_pred_max, wi_case_min)) | |
3238 | other = pred; | |
3239 | } | |
3240 | ||
3241 | if (!other && succ) | |
3242 | { | |
3243 | /* Check to see if the SUCC overlaps. The low end of that | |
3244 | range is bigger than the low end of the current range. */ | |
3245 | wide_int wi_case_max = get_wide_int (case_->get_max_value ()); | |
3246 | wide_int wi_succ_min = get_wide_int (succ->get_min_value ()); | |
3247 | if (wi::les_p (wi_succ_min, wi_case_max)) | |
3248 | other = succ; | |
3249 | } | |
3250 | } | |
3251 | ||
3252 | /* If there was an overlap, issue an error. */ | |
3253 | if (other) | |
3254 | { | |
3255 | jit_error (m_ctxt, m_loc, | |
3256 | "%s: duplicate (or overlapping) cases values:" | |
3257 | " case %i: %s overlaps %s", | |
3258 | m_funcname, | |
3259 | case_idx, | |
3260 | case_->get_debug_string (), | |
3261 | other->get_debug_string ()); | |
3262 | return false; | |
3263 | } | |
3264 | ||
3265 | /* Register this case label in the splay tree. */ | |
3266 | m_cases.insert (case_->get_min_value (), | |
3267 | case_); | |
3268 | return true; | |
3269 | } | |
3270 | ||
e53b6e56 | 3271 | /* Compare with c-family/c-common.cc:case_compare, which acts on tree |
ec5d0088 DM |
3272 | nodes, rather than rvalue *. |
3273 | ||
3274 | Comparator for case label values. K1 and K2 must be constant integer | |
3275 | values (anything else should have been rejected by | |
3276 | gcc_jit_context_new_case. | |
3277 | ||
3278 | Returns -1 if K1 is ordered before K2, -1 if K1 is ordered after | |
3279 | K2, and 0 if K1 and K2 are equal. */ | |
3280 | ||
3281 | int | |
3282 | case_range_validator::case_compare (gcc::jit::recording::rvalue * k1, | |
3283 | gcc::jit::recording::rvalue * k2) | |
3284 | { | |
3285 | wide_int wi1 = get_wide_int (k1); | |
3286 | wide_int wi2 = get_wide_int (k2); | |
3287 | return wi::cmps(wi1, wi2); | |
3288 | } | |
3289 | ||
3290 | /* Given a const int rvalue K, get the underlying value as a wide_int. */ | |
3291 | ||
3292 | wide_int | |
3293 | case_range_validator::get_wide_int (gcc::jit::recording::rvalue *k) | |
3294 | { | |
3295 | wide_int wi; | |
3296 | bool got_wi = k->get_wide_int (&wi); | |
3297 | gcc_assert (got_wi); | |
3298 | return wi; | |
3299 | } | |
3300 | ||
3301 | /* Public entrypoint. See description in libgccjit.h. | |
3302 | ||
3303 | After error-checking, the real work is done by the | |
3304 | gcc::jit::recording::block::end_with_switch method in | |
e53b6e56 | 3305 | jit-recording.cc. */ |
ec5d0088 DM |
3306 | |
3307 | void | |
3308 | gcc_jit_block_end_with_switch (gcc_jit_block *block, | |
3309 | gcc_jit_location *loc, | |
3310 | gcc_jit_rvalue *expr, | |
3311 | gcc_jit_block *default_block, | |
3312 | int num_cases, | |
3313 | gcc_jit_case **cases) | |
3314 | { | |
3315 | RETURN_IF_NOT_VALID_BLOCK (block, loc); | |
3316 | gcc::jit::recording::context *ctxt = block->get_context (); | |
3317 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
3318 | /* LOC can be NULL. */ | |
3319 | RETURN_IF_FAIL (expr, ctxt, loc, | |
3320 | "NULL expr"); | |
3321 | gcc::jit::recording::type *expr_type = expr->get_type (); | |
3322 | RETURN_IF_FAIL_PRINTF2 ( | |
3323 | expr_type->is_int (), | |
3324 | ctxt, loc, | |
3325 | "expr: %s (type: %s) is not of integer type", | |
3326 | expr->get_debug_string (), | |
3327 | expr_type->get_debug_string ()); | |
3328 | if (!valid_dest_for_switch (ctxt, loc, | |
3329 | __func__, | |
3330 | block, | |
3331 | default_block, | |
3332 | "default_block")) | |
3333 | return; | |
3334 | RETURN_IF_FAIL (num_cases >= 0, ctxt, loc, "num_cases < 0"); | |
3335 | case_range_validator crv (ctxt, loc, __func__); | |
3336 | for (int i = 0; i < num_cases; i++) | |
3337 | { | |
3338 | char case_desc[32]; | |
3339 | snprintf (case_desc, sizeof (case_desc), | |
3340 | "cases[%i]", i); | |
3341 | if (!valid_case_for_switch (ctxt, loc, | |
3342 | __func__, | |
3343 | block, | |
3344 | expr, | |
3345 | cases[i], | |
3346 | case_desc, | |
3347 | i)) | |
3348 | return; | |
3349 | if (!crv.validate (cases[i], i)) | |
3350 | return; | |
3351 | } | |
3352 | ||
3353 | block->end_with_switch (loc, expr, default_block, | |
3354 | num_cases, | |
3355 | (gcc::jit::recording::case_ **)cases); | |
3356 | } | |
3357 | ||
35485da9 DM |
3358 | /********************************************************************** |
3359 | Option-management | |
3360 | **********************************************************************/ | |
3361 | ||
3362 | /* Public entrypoint. See description in libgccjit.h. | |
3363 | ||
3364 | After error-checking, the real work is done by the | |
3365 | gcc::jit::recording::context::set_str_option method in | |
e53b6e56 | 3366 | jit-recording.cc. */ |
35485da9 DM |
3367 | |
3368 | void | |
3369 | gcc_jit_context_set_str_option (gcc_jit_context *ctxt, | |
3370 | enum gcc_jit_str_option opt, | |
3371 | const char *value) | |
3372 | { | |
3373 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 3374 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
3375 | /* opt is checked by the inner function. |
3376 | value can be NULL. */ | |
3377 | ||
3378 | ctxt->set_str_option (opt, value); | |
3379 | } | |
3380 | ||
3381 | /* Public entrypoint. See description in libgccjit.h. | |
3382 | ||
3383 | After error-checking, the real work is done by the | |
3384 | gcc::jit::recording::context::set_int_option method in | |
e53b6e56 | 3385 | jit-recording.cc. */ |
35485da9 DM |
3386 | |
3387 | void | |
3388 | gcc_jit_context_set_int_option (gcc_jit_context *ctxt, | |
3389 | enum gcc_jit_int_option opt, | |
3390 | int value) | |
3391 | { | |
3392 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 3393 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
3394 | /* opt is checked by the inner function. */ |
3395 | ||
3396 | ctxt->set_int_option (opt, value); | |
3397 | } | |
3398 | ||
3399 | /* Public entrypoint. See description in libgccjit.h. | |
3400 | ||
3401 | After error-checking, the real work is done by the | |
3402 | gcc::jit::recording::context::set_bool_option method in | |
e53b6e56 | 3403 | jit-recording.cc. */ |
35485da9 DM |
3404 | |
3405 | void | |
3406 | gcc_jit_context_set_bool_option (gcc_jit_context *ctxt, | |
3407 | enum gcc_jit_bool_option opt, | |
3408 | int value) | |
3409 | { | |
3410 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 3411 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
3412 | /* opt is checked by the inner function. */ |
3413 | ||
3414 | ctxt->set_bool_option (opt, value); | |
3415 | } | |
3416 | ||
6a3603e3 DM |
3417 | /* Public entrypoint. See description in libgccjit.h. |
3418 | ||
3419 | After error-checking, the real work is done by the | |
3420 | gcc::jit::recording::context::set_inner_bool_option method in | |
e53b6e56 | 3421 | jit-recording.cc. */ |
6a3603e3 DM |
3422 | |
3423 | void | |
3424 | gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context *ctxt, | |
3425 | int bool_value) | |
3426 | { | |
3427 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
3428 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
3429 | ctxt->set_inner_bool_option ( | |
3430 | gcc::jit::INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS, | |
3431 | bool_value); | |
3432 | } | |
3433 | ||
9376dd63 DM |
3434 | /* Public entrypoint. See description in libgccjit.h. |
3435 | ||
3436 | After error-checking, the real work is done by the | |
3437 | gcc::jit::recording::context::set_inner_bool_option method in | |
e53b6e56 | 3438 | jit-recording.cc. */ |
9376dd63 DM |
3439 | |
3440 | extern void | |
3441 | gcc_jit_context_set_bool_use_external_driver (gcc_jit_context *ctxt, | |
3442 | int bool_value) | |
3443 | { | |
3444 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
3445 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
3446 | ctxt->set_inner_bool_option ( | |
3447 | gcc::jit::INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER, | |
3448 | bool_value); | |
3449 | } | |
3450 | ||
fa22c20d DM |
3451 | /* Public entrypoint. See description in libgccjit.h. |
3452 | ||
3453 | After error-checking, the real work is done by the | |
3454 | gcc::jit::recording::context::add_command_line_option method in | |
e53b6e56 | 3455 | jit-recording.cc. */ |
fa22c20d DM |
3456 | |
3457 | void | |
3458 | gcc_jit_context_add_command_line_option (gcc_jit_context *ctxt, | |
3459 | const char *optname) | |
3460 | { | |
3461 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
3462 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
3463 | RETURN_IF_FAIL (optname, ctxt, NULL, "NULL optname"); | |
3464 | if (ctxt->get_logger ()) | |
3465 | ctxt->get_logger ()->log ("optname: %s", optname); | |
3466 | ||
3467 | ctxt->add_command_line_option (optname); | |
3468 | } | |
3469 | ||
216090cc AC |
3470 | /* Public entrypoint. See description in libgccjit.h. |
3471 | ||
3472 | The real work is done by the | |
3473 | gcc::jit::recording::context::add_driver_option method in | |
e53b6e56 | 3474 | jit-recording.cc. */ |
216090cc AC |
3475 | |
3476 | void | |
3477 | gcc_jit_context_add_driver_option (gcc_jit_context *ctxt, | |
3478 | const char *optname) | |
3479 | { | |
3480 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
3481 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
3482 | RETURN_IF_FAIL (optname, ctxt, NULL, "NULL optname"); | |
3483 | if (ctxt->get_logger ()) | |
3484 | ctxt->get_logger ()->log ("optname: %s", optname); | |
3485 | ||
3486 | ctxt->add_driver_option (optname); | |
3487 | } | |
3488 | ||
463366a0 DM |
3489 | /* Public entrypoint. See description in libgccjit.h. |
3490 | ||
3491 | After error-checking, the real work is done by the | |
3492 | gcc::jit::recording::context::enable_dump method in | |
e53b6e56 | 3493 | jit-recording.cc. */ |
463366a0 DM |
3494 | |
3495 | void | |
3496 | gcc_jit_context_enable_dump (gcc_jit_context *ctxt, | |
3497 | const char *dumpname, | |
3498 | char **out_ptr) | |
3499 | { | |
3500 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 3501 | JIT_LOG_FUNC (ctxt->get_logger ()); |
463366a0 DM |
3502 | RETURN_IF_FAIL (dumpname, ctxt, NULL, "NULL dumpname"); |
3503 | RETURN_IF_FAIL (out_ptr, ctxt, NULL, "NULL out_ptr"); | |
3504 | ||
3505 | ctxt->enable_dump (dumpname, out_ptr); | |
3506 | } | |
3507 | ||
35485da9 DM |
3508 | /* Public entrypoint. See description in libgccjit.h. |
3509 | ||
3510 | After error-checking, the real work is done by the | |
3511 | gcc::jit::recording::context::compile method in | |
e53b6e56 | 3512 | jit-recording.cc. */ |
35485da9 DM |
3513 | |
3514 | gcc_jit_result * | |
3515 | gcc_jit_context_compile (gcc_jit_context *ctxt) | |
3516 | { | |
3517 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
3518 | ||
eb4c16eb DM |
3519 | JIT_LOG_FUNC (ctxt->get_logger ()); |
3520 | ||
fdce7209 | 3521 | ctxt->log ("in-memory compile of ctxt: %p", (void *)ctxt); |
eb4c16eb DM |
3522 | |
3523 | gcc_jit_result *result = (gcc_jit_result *)ctxt->compile (); | |
3524 | ||
3525 | ctxt->log ("%s: returning (gcc_jit_result *)%p", | |
3526 | __func__, (void *)result); | |
3527 | ||
3528 | return result; | |
35485da9 DM |
3529 | } |
3530 | ||
fdce7209 DM |
3531 | /* Public entrypoint. See description in libgccjit.h. |
3532 | ||
3533 | After error-checking, the real work is done by the | |
3534 | gcc::jit::recording::context::compile_to_file method in | |
e53b6e56 | 3535 | jit-recording.cc. */ |
fdce7209 DM |
3536 | |
3537 | void | |
3538 | gcc_jit_context_compile_to_file (gcc_jit_context *ctxt, | |
3539 | enum gcc_jit_output_kind output_kind, | |
3540 | const char *output_path) | |
3541 | { | |
3542 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
3543 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
3544 | RETURN_IF_FAIL_PRINTF1 ( | |
3545 | ((output_kind >= GCC_JIT_OUTPUT_KIND_ASSEMBLER) | |
3546 | && (output_kind <= GCC_JIT_OUTPUT_KIND_EXECUTABLE)), | |
3547 | ctxt, NULL, | |
3548 | "unrecognized output_kind: %i", | |
3549 | output_kind); | |
3550 | RETURN_IF_FAIL (output_path, ctxt, NULL, "NULL output_path"); | |
3551 | ||
3552 | ctxt->log ("compile_to_file of ctxt: %p", (void *)ctxt); | |
3553 | ctxt->log ("output_kind: %i", output_kind); | |
3554 | ctxt->log ("output_path: %s", output_path); | |
3555 | ||
3556 | ctxt->compile_to_file (output_kind, output_path); | |
3557 | } | |
3558 | ||
3559 | ||
35485da9 DM |
3560 | /* Public entrypoint. See description in libgccjit.h. |
3561 | ||
3562 | After error-checking, the real work is done by the | |
3563 | gcc::jit::recording::context::dump_to_file method in | |
e53b6e56 | 3564 | jit-recording.cc. */ |
35485da9 DM |
3565 | |
3566 | void | |
3567 | gcc_jit_context_dump_to_file (gcc_jit_context *ctxt, | |
3568 | const char *path, | |
3569 | int update_locations) | |
3570 | { | |
3571 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 3572 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
3573 | RETURN_IF_FAIL (path, ctxt, NULL, "NULL path"); |
3574 | ctxt->dump_to_file (path, update_locations); | |
3575 | } | |
3576 | ||
eb4c16eb DM |
3577 | /* Public entrypoint. See description in libgccjit.h. */ |
3578 | ||
3579 | void | |
3580 | gcc_jit_context_set_logfile (gcc_jit_context *ctxt, | |
3581 | FILE *logfile, | |
3582 | int flags, | |
3583 | int verbosity) | |
3584 | { | |
3585 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
3586 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
3587 | RETURN_IF_FAIL ((flags == 0), ctxt, NULL, "flags must be 0 for now"); | |
3588 | RETURN_IF_FAIL ((verbosity == 0), ctxt, NULL, "verbosity must be 0 for now"); | |
3589 | ||
3590 | gcc::jit::logger *logger; | |
3591 | if (logfile) | |
3592 | logger = new gcc::jit::logger (logfile, flags, verbosity); | |
3593 | else | |
3594 | logger = NULL; | |
3595 | ctxt->set_logger (logger); | |
3596 | } | |
3597 | ||
86d0ac88 DM |
3598 | /* Public entrypoint. See description in libgccjit.h. |
3599 | ||
3600 | After error-checking, the real work is done by the | |
3601 | gcc::jit::recording::context::dump_reproducer_to_file method in | |
e53b6e56 | 3602 | jit-recording.cc. */ |
86d0ac88 DM |
3603 | |
3604 | void | |
3605 | gcc_jit_context_dump_reproducer_to_file (gcc_jit_context *ctxt, | |
3606 | const char *path) | |
3607 | { | |
3608 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
3609 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
3610 | RETURN_IF_FAIL (path, ctxt, NULL, "NULL path"); | |
3611 | ctxt->dump_reproducer_to_file (path); | |
3612 | } | |
3613 | ||
35485da9 DM |
3614 | /* Public entrypoint. See description in libgccjit.h. |
3615 | ||
3616 | After error-checking, the real work is done by the | |
3617 | gcc::jit::recording::context::get_first_error method in | |
e53b6e56 | 3618 | jit-recording.cc. */ |
35485da9 DM |
3619 | |
3620 | const char * | |
3621 | gcc_jit_context_get_first_error (gcc_jit_context *ctxt) | |
3622 | { | |
3623 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
eb4c16eb | 3624 | JIT_LOG_FUNC (ctxt->get_logger ()); |
35485da9 DM |
3625 | |
3626 | return ctxt->get_first_error (); | |
3627 | } | |
3628 | ||
303e1d56 DM |
3629 | /* Public entrypoint. See description in libgccjit.h. |
3630 | ||
3631 | After error-checking, the real work is done by the | |
3632 | gcc::jit::recording::context::get_last_error method in | |
e53b6e56 | 3633 | jit-recording.cc. */ |
303e1d56 DM |
3634 | |
3635 | const char * | |
3636 | gcc_jit_context_get_last_error (gcc_jit_context *ctxt) | |
3637 | { | |
3638 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); | |
3639 | ||
3640 | return ctxt->get_last_error (); | |
3641 | } | |
3642 | ||
35485da9 DM |
3643 | /* Public entrypoint. See description in libgccjit.h. |
3644 | ||
3645 | After error-checking, the real work is done by the | |
e53b6e56 | 3646 | gcc::jit::result::get_code method in jit-result.cc. */ |
35485da9 DM |
3647 | |
3648 | void * | |
3649 | gcc_jit_result_get_code (gcc_jit_result *result, | |
3650 | const char *fnname) | |
3651 | { | |
3652 | RETURN_NULL_IF_FAIL (result, NULL, NULL, "NULL result"); | |
eb4c16eb | 3653 | JIT_LOG_FUNC (result->get_logger ()); |
35485da9 DM |
3654 | RETURN_NULL_IF_FAIL (fnname, NULL, NULL, "NULL fnname"); |
3655 | ||
eb4c16eb DM |
3656 | result->log ("locating fnname: %s", fnname); |
3657 | void *code = result->get_code (fnname); | |
3658 | result->log ("%s: returning (void *)%p", __func__, code); | |
3659 | ||
3660 | return code; | |
35485da9 DM |
3661 | } |
3662 | ||
791cfef8 DM |
3663 | /* Public entrypoint. See description in libgccjit.h. |
3664 | ||
3665 | After error-checking, the real work is done by the | |
e53b6e56 | 3666 | gcc::jit::result::get_global method in jit-result.cc. */ |
791cfef8 DM |
3667 | |
3668 | void * | |
3669 | gcc_jit_result_get_global (gcc_jit_result *result, | |
3670 | const char *name) | |
3671 | { | |
3672 | RETURN_NULL_IF_FAIL (result, NULL, NULL, "NULL result"); | |
3673 | JIT_LOG_FUNC (result->get_logger ()); | |
3674 | RETURN_NULL_IF_FAIL (name, NULL, NULL, "NULL name"); | |
3675 | ||
3676 | void *global = result->get_global (name); | |
3677 | result->log ("%s: returning (void *)%p", __func__, global); | |
3678 | ||
3679 | return global; | |
3680 | } | |
3681 | ||
35485da9 DM |
3682 | /* Public entrypoint. See description in libgccjit.h. |
3683 | ||
3684 | After error-checking, this is essentially a wrapper around the | |
e53b6e56 | 3685 | destructor for gcc::jit::result in jit-result.cc. */ |
35485da9 DM |
3686 | |
3687 | void | |
3688 | gcc_jit_result_release (gcc_jit_result *result) | |
3689 | { | |
3690 | RETURN_IF_FAIL (result, NULL, NULL, "NULL result"); | |
eb4c16eb DM |
3691 | JIT_LOG_FUNC (result->get_logger ()); |
3692 | result->log ("deleting result: %p", (void *)result); | |
35485da9 DM |
3693 | delete result; |
3694 | } | |
afed3459 DM |
3695 | |
3696 | /********************************************************************** | |
3697 | Timing support. | |
3698 | **********************************************************************/ | |
3699 | ||
3700 | /* Create a gcc_jit_timer instance, and start timing. */ | |
3701 | ||
3702 | gcc_jit_timer * | |
3703 | gcc_jit_timer_new (void) | |
3704 | { | |
3705 | gcc_jit_timer *timer = new gcc_jit_timer (); | |
3706 | timer->start (TV_TOTAL); | |
3707 | timer->push (TV_JIT_CLIENT_CODE); | |
3708 | return timer; | |
3709 | } | |
3710 | ||
3711 | /* Release a gcc_jit_timer instance. */ | |
3712 | ||
3713 | void | |
3714 | gcc_jit_timer_release (gcc_jit_timer *timer) | |
3715 | { | |
3716 | RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer"); | |
3717 | ||
3718 | delete timer; | |
3719 | } | |
3720 | ||
3721 | /* Associate a gcc_jit_timer instance with a context. */ | |
3722 | ||
3723 | void | |
3724 | gcc_jit_context_set_timer (gcc_jit_context *ctxt, | |
3725 | gcc_jit_timer *timer) | |
3726 | { | |
3727 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL ctxt"); | |
3728 | RETURN_IF_FAIL (timer, ctxt, NULL, "NULL timer"); | |
3729 | ||
3730 | ctxt->set_timer (timer); | |
3731 | } | |
3732 | ||
3733 | /* Get the timer associated with a context (if any). */ | |
3734 | ||
3735 | gcc_jit_timer * | |
3736 | gcc_jit_context_get_timer (gcc_jit_context *ctxt) | |
3737 | { | |
3738 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL ctxt"); | |
3739 | ||
3740 | return (gcc_jit_timer *)ctxt->get_timer (); | |
3741 | } | |
3742 | ||
3743 | /* Push the given item onto the timing stack. */ | |
3744 | ||
3745 | void | |
3746 | gcc_jit_timer_push (gcc_jit_timer *timer, | |
3747 | const char *item_name) | |
3748 | { | |
3749 | RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer"); | |
3750 | RETURN_IF_FAIL (item_name, NULL, NULL, "NULL item_name"); | |
3751 | timer->push_client_item (item_name); | |
3752 | } | |
3753 | ||
3754 | /* Pop the top item from the timing stack. */ | |
3755 | ||
3756 | void | |
3757 | gcc_jit_timer_pop (gcc_jit_timer *timer, | |
3758 | const char *item_name) | |
3759 | { | |
3760 | RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer"); | |
3761 | ||
3762 | if (item_name) | |
3763 | { | |
3764 | const char *top_item_name = timer->get_topmost_item_name (); | |
3765 | ||
3766 | RETURN_IF_FAIL_PRINTF1 | |
3767 | (top_item_name, NULL, NULL, | |
3768 | "pop of empty timing stack (attempting to pop: \"%s\")", | |
3769 | item_name); | |
3770 | ||
3771 | RETURN_IF_FAIL_PRINTF2 | |
01512446 | 3772 | (strcmp (item_name, top_item_name) == 0, NULL, NULL, |
afed3459 DM |
3773 | "mismatching item_name:" |
3774 | " top of timing stack: \"%s\"," | |
3775 | " attempting to pop: \"%s\"", | |
3776 | top_item_name, | |
3777 | item_name); | |
3778 | } | |
3779 | ||
3780 | timer->pop_client_item (); | |
3781 | } | |
3782 | ||
3783 | /* Print timing information to the given stream about activity since | |
3784 | the timer was started. */ | |
3785 | ||
3786 | void | |
3787 | gcc_jit_timer_print (gcc_jit_timer *timer, | |
3788 | FILE *f_out) | |
3789 | { | |
3790 | RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer"); | |
3791 | RETURN_IF_FAIL (f_out, NULL, NULL, "NULL f_out"); | |
3792 | ||
3793 | timer->pop (TV_JIT_CLIENT_CODE); | |
3794 | timer->stop (TV_TOTAL); | |
3795 | timer->print (f_out); | |
3796 | timer->start (TV_TOTAL); | |
3797 | timer->push (TV_JIT_CLIENT_CODE); | |
3798 | } | |
15c671a7 DM |
3799 | |
3800 | /* Public entrypoint. See description in libgccjit.h. | |
3801 | ||
3802 | After error-checking, the real work is effectively done by the | |
3803 | gcc::jit::base_call::set_require_tail_call setter in jit-recording.h. */ | |
3804 | ||
3805 | void | |
3806 | gcc_jit_rvalue_set_bool_require_tail_call (gcc_jit_rvalue *rvalue, | |
3807 | int require_tail_call) | |
3808 | { | |
3809 | RETURN_IF_FAIL (rvalue, NULL, NULL, "NULL call"); | |
3810 | JIT_LOG_FUNC (rvalue->get_context ()->get_logger ()); | |
3811 | ||
3812 | /* Verify that it's a call. */ | |
3813 | gcc::jit::recording::base_call *call = rvalue->dyn_cast_base_call (); | |
3814 | RETURN_IF_FAIL_PRINTF1 (call, NULL, NULL, "not a call: %s", | |
3815 | rvalue->get_debug_string ()); | |
3816 | ||
3817 | call->set_require_tail_call (require_tail_call); | |
3818 | } | |
0ebd1f00 DM |
3819 | |
3820 | /* Public entrypoint. See description in libgccjit.h. | |
3821 | ||
3822 | After error-checking, the real work is done by the | |
3823 | gcc::jit::recording::type::get_aligned method, in | |
e53b6e56 | 3824 | jit-recording.cc. */ |
0ebd1f00 DM |
3825 | |
3826 | gcc_jit_type * | |
3827 | gcc_jit_type_get_aligned (gcc_jit_type *type, | |
3828 | size_t alignment_in_bytes) | |
3829 | { | |
3830 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); | |
3831 | ||
3832 | gcc::jit::recording::context *ctxt = type->m_ctxt; | |
3833 | ||
3834 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
3835 | ||
3836 | RETURN_NULL_IF_FAIL_PRINTF1 | |
3837 | (pow2_or_zerop (alignment_in_bytes), ctxt, NULL, | |
3838 | "alignment not a power of two: %zi", | |
3839 | alignment_in_bytes); | |
6f7585de | 3840 | RETURN_NULL_IF_FAIL (!type->is_void (), ctxt, NULL, "void type"); |
0ebd1f00 DM |
3841 | |
3842 | return (gcc_jit_type *)type->get_aligned (alignment_in_bytes); | |
3843 | } | |
47ee1b7c DM |
3844 | |
3845 | /* Public entrypoint. See description in libgccjit.h. | |
3846 | ||
3847 | After error-checking, the real work is done by the | |
3848 | gcc::jit::recording::type::get_vector method, in | |
e53b6e56 | 3849 | jit-recording.cc. */ |
47ee1b7c DM |
3850 | |
3851 | gcc_jit_type * | |
3852 | gcc_jit_type_get_vector (gcc_jit_type *type, size_t num_units) | |
3853 | { | |
3854 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); | |
3855 | ||
3856 | gcc::jit::recording::context *ctxt = type->m_ctxt; | |
3857 | ||
3858 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
3859 | ||
3860 | RETURN_NULL_IF_FAIL_PRINTF1 | |
3861 | (type->is_int () || type->is_float (), ctxt, NULL, | |
3862 | "type is not integral or floating point: %s", | |
3863 | type->get_debug_string ()); | |
3864 | ||
3865 | RETURN_NULL_IF_FAIL_PRINTF1 | |
3866 | (pow2_or_zerop (num_units), ctxt, NULL, | |
3867 | "num_units not a power of two: %zi", | |
3868 | num_units); | |
3869 | ||
3870 | return (gcc_jit_type *)type->get_vector (num_units); | |
3871 | } | |
15a65e63 DM |
3872 | |
3873 | /* Public entrypoint. See description in libgccjit.h. | |
3874 | ||
3875 | After error-checking, the real work is done by the | |
3876 | gcc::jit::recording::function::get_address method, in | |
e53b6e56 | 3877 | jit-recording.cc. */ |
15a65e63 DM |
3878 | |
3879 | gcc_jit_rvalue * | |
3880 | gcc_jit_function_get_address (gcc_jit_function *fn, | |
3881 | gcc_jit_location *loc) | |
3882 | { | |
3883 | RETURN_NULL_IF_FAIL (fn, NULL, NULL, "NULL function"); | |
3884 | ||
3885 | gcc::jit::recording::context *ctxt = fn->m_ctxt; | |
3886 | ||
3887 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
3888 | /* LOC can be NULL. */ | |
3889 | ||
3890 | return (gcc_jit_rvalue *)fn->get_address (loc); | |
3891 | } | |
6069fe72 DM |
3892 | |
3893 | /* Public entrypoint. See description in libgccjit.h. | |
3894 | ||
3895 | After error-checking, the real work is done by the | |
3896 | gcc::jit::recording::context::new_rvalue_from_vector method, in | |
e53b6e56 | 3897 | jit-recording.cc. */ |
6069fe72 DM |
3898 | |
3899 | extern gcc_jit_rvalue * | |
3900 | gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt, | |
3901 | gcc_jit_location *loc, | |
3902 | gcc_jit_type *vec_type, | |
3903 | size_t num_elements, | |
3904 | gcc_jit_rvalue **elements) | |
3905 | { | |
3906 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL ctxt"); | |
3907 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
3908 | ||
3909 | /* LOC can be NULL. */ | |
3910 | RETURN_NULL_IF_FAIL (vec_type, ctxt, loc, "NULL vec_type"); | |
3911 | ||
3912 | /* "vec_type" must be a vector type. */ | |
3913 | gcc::jit::recording::vector_type *as_vec_type | |
3914 | = vec_type->dyn_cast_vector_type (); | |
3915 | RETURN_NULL_IF_FAIL_PRINTF1 (as_vec_type, ctxt, loc, | |
3916 | "%s is not a vector type", | |
3917 | vec_type->get_debug_string ()); | |
3918 | ||
3919 | /* "num_elements" must match. */ | |
3920 | RETURN_NULL_IF_FAIL_PRINTF1 ( | |
3921 | num_elements == as_vec_type->get_num_units (), ctxt, loc, | |
3922 | "num_elements != %zi", as_vec_type->get_num_units ()); | |
3923 | ||
3924 | /* "elements must be non-NULL. */ | |
3925 | RETURN_NULL_IF_FAIL (elements, ctxt, loc, "NULL elements"); | |
3926 | ||
3927 | /* Each of "elements" must be non-NULL and of the correct type. */ | |
3928 | gcc::jit::recording::type *element_type | |
3929 | = as_vec_type->get_element_type (); | |
3930 | for (size_t i = 0; i < num_elements; i++) | |
3931 | { | |
3932 | RETURN_NULL_IF_FAIL_PRINTF1 ( | |
3933 | elements[i], ctxt, loc, "NULL elements[%zi]", i); | |
3934 | RETURN_NULL_IF_FAIL_PRINTF4 ( | |
3935 | compatible_types (element_type, | |
3936 | elements[i]->get_type ()), | |
3937 | ctxt, loc, | |
3938 | "mismatching type for element[%zi] (expected type: %s): %s (type: %s)", | |
3939 | i, | |
3940 | element_type->get_debug_string (), | |
3941 | elements[i]->get_debug_string (), | |
3942 | elements[i]->get_type ()->get_debug_string ()); | |
3943 | } | |
3944 | ||
3945 | return (gcc_jit_rvalue *)ctxt->new_rvalue_from_vector | |
3946 | (loc, | |
3947 | as_vec_type, | |
3948 | (gcc::jit::recording::rvalue **)elements); | |
3949 | } | |
63b2923d A |
3950 | |
3951 | /* A mutex around the cached state in parse_basever. | |
3952 | Ideally this would be within parse_basever, but the mutex is only needed | |
3953 | by libgccjit. */ | |
3954 | ||
3955 | static pthread_mutex_t version_mutex = PTHREAD_MUTEX_INITIALIZER; | |
3956 | ||
7424323b | 3957 | struct jit_version_info |
63b2923d A |
3958 | { |
3959 | /* Default constructor. Populate via parse_basever, | |
3960 | guarded by version_mutex. */ | |
7424323b | 3961 | jit_version_info () |
63b2923d A |
3962 | { |
3963 | pthread_mutex_lock (&version_mutex); | |
3964 | parse_basever (&major, &minor, &patchlevel); | |
3965 | pthread_mutex_unlock (&version_mutex); | |
3966 | } | |
3967 | ||
3968 | int major; | |
3969 | int minor; | |
3970 | int patchlevel; | |
3971 | }; | |
3972 | ||
3973 | ||
3974 | extern int | |
3975 | gcc_jit_version_major (void) | |
3976 | { | |
7424323b | 3977 | jit_version_info vi; |
63b2923d A |
3978 | return vi.major; |
3979 | } | |
3980 | ||
3981 | extern int | |
3982 | gcc_jit_version_minor (void) | |
3983 | { | |
7424323b | 3984 | jit_version_info vi; |
63b2923d A |
3985 | return vi.minor; |
3986 | } | |
3987 | ||
3988 | extern int | |
3989 | gcc_jit_version_patchlevel (void) | |
3990 | { | |
7424323b | 3991 | jit_version_info vi; |
63b2923d A |
3992 | return vi.patchlevel; |
3993 | } | |
421d0d0f DM |
3994 | |
3995 | /********************************************************************** | |
3996 | Asm support. | |
3997 | **********************************************************************/ | |
3998 | ||
3999 | /* Public entrypoint. See description in libgccjit.h. | |
4000 | ||
4001 | After error-checking, the real work is done by the | |
4002 | gcc::jit::recording::block::add_extended_asm, in | |
e53b6e56 | 4003 | jit-recording.cc. */ |
421d0d0f DM |
4004 | |
4005 | gcc_jit_extended_asm * | |
4006 | gcc_jit_block_add_extended_asm (gcc_jit_block *block, | |
4007 | gcc_jit_location *loc, | |
4008 | const char *asm_template) | |
4009 | { | |
4010 | RETURN_NULL_IF_NOT_VALID_BLOCK (block, loc); | |
4011 | gcc::jit::recording::context *ctxt = block->get_context (); | |
4012 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
4013 | /* LOC can be NULL. */ | |
4014 | RETURN_NULL_IF_FAIL (asm_template, ctxt, loc, "NULL asm_template"); | |
4015 | ||
4016 | return (gcc_jit_extended_asm *)block->add_extended_asm (loc, asm_template); | |
4017 | } | |
4018 | ||
4019 | /* Public entrypoint. See description in libgccjit.h. | |
4020 | ||
4021 | After error-checking, the real work is done by the | |
4022 | gcc::jit::recording::block::end_with_extended_asm_goto, in | |
e53b6e56 | 4023 | jit-recording.cc. */ |
421d0d0f DM |
4024 | |
4025 | gcc_jit_extended_asm * | |
4026 | gcc_jit_block_end_with_extended_asm_goto (gcc_jit_block *block, | |
4027 | gcc_jit_location *loc, | |
4028 | const char *asm_template, | |
4029 | int num_goto_blocks, | |
4030 | gcc_jit_block **goto_blocks, | |
4031 | gcc_jit_block *fallthrough_block) | |
4032 | { | |
4033 | RETURN_NULL_IF_NOT_VALID_BLOCK (block, loc); | |
4034 | gcc::jit::recording::context *ctxt = block->get_context (); | |
4035 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
4036 | /* LOC can be NULL. */ | |
4037 | RETURN_NULL_IF_FAIL (asm_template, ctxt, loc, "NULL asm_template"); | |
4038 | RETURN_NULL_IF_FAIL (num_goto_blocks >= 0, ctxt, loc, "num_goto_blocks < 0"); | |
4039 | for (int i = 0; i < num_goto_blocks; i++) | |
4040 | RETURN_NULL_IF_FAIL_PRINTF1 (goto_blocks[i], | |
4041 | ctxt, loc, | |
4042 | "NULL goto_blocks[%i]", i); | |
4043 | /* fallthrough_block can be NULL. */ | |
4044 | return (gcc_jit_extended_asm *)block->end_with_extended_asm_goto | |
4045 | (loc, asm_template, | |
4046 | num_goto_blocks, (gcc::jit::recording::block **)goto_blocks, | |
4047 | fallthrough_block); | |
4048 | } | |
4049 | ||
4050 | /* Public entrypoint. See description in libgccjit.h. | |
4051 | ||
4052 | After error-checking, this calls the trivial | |
4053 | gcc::jit::recording::memento::as_object method (an extended_asm is a | |
4054 | memento), in jit-recording.h. */ | |
4055 | ||
4056 | gcc_jit_object * | |
4057 | gcc_jit_extended_asm_as_object (gcc_jit_extended_asm *ext_asm) | |
4058 | { | |
4059 | RETURN_NULL_IF_FAIL (ext_asm, NULL, NULL, "NULL ext_asm"); | |
4060 | ||
4061 | return static_cast <gcc_jit_object *> (ext_asm->as_object ()); | |
4062 | } | |
4063 | ||
4064 | /* Public entrypoint. See description in libgccjit.h. | |
4065 | ||
4066 | After error-checking, the real work is done by the | |
4067 | gcc::jit::recording::extended_asm::set_volatile_flag, in | |
e53b6e56 | 4068 | jit-recording.cc. */ |
421d0d0f DM |
4069 | |
4070 | void | |
4071 | gcc_jit_extended_asm_set_volatile_flag (gcc_jit_extended_asm *ext_asm, | |
4072 | int flag) | |
4073 | { | |
4074 | RETURN_IF_FAIL (ext_asm, NULL, NULL, "NULL ext_asm"); | |
4075 | ext_asm->set_volatile_flag (flag); | |
4076 | } | |
4077 | ||
4078 | /* Public entrypoint. See description in libgccjit.h. | |
4079 | ||
4080 | After error-checking, the real work is done by the | |
4081 | gcc::jit::recording::extended_asm::set_inline_flag, in | |
e53b6e56 | 4082 | jit-recording.cc. */ |
421d0d0f DM |
4083 | |
4084 | void | |
4085 | gcc_jit_extended_asm_set_inline_flag (gcc_jit_extended_asm *ext_asm, | |
4086 | int flag) | |
4087 | { | |
4088 | RETURN_IF_FAIL (ext_asm, NULL, NULL, "NULL ext_asm"); | |
4089 | ext_asm->set_inline_flag (flag); | |
4090 | } | |
4091 | ||
4092 | /* Public entrypoint. See description in libgccjit.h. | |
4093 | ||
4094 | After error-checking, the real work is done by the | |
4095 | gcc::jit::recording::extended_asm::add_output_operand, in | |
e53b6e56 | 4096 | jit-recording.cc. */ |
421d0d0f DM |
4097 | |
4098 | void | |
4099 | gcc_jit_extended_asm_add_output_operand (gcc_jit_extended_asm *ext_asm, | |
4100 | const char *asm_symbolic_name, | |
4101 | const char *constraint, | |
4102 | gcc_jit_lvalue *dest) | |
4103 | { | |
4104 | RETURN_IF_FAIL (ext_asm, NULL, NULL, "NULL ext_asm"); | |
4105 | gcc::jit::recording::context *ctxt = ext_asm->get_context (); | |
4106 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
4107 | gcc::jit::recording::location *loc = ext_asm->get_loc (); | |
4108 | /* asm_symbolic_name can be NULL. */ | |
4109 | RETURN_IF_FAIL (constraint, ctxt, loc, "NULL constraint"); | |
4110 | RETURN_IF_FAIL (dest, ctxt, loc, "NULL dest"); | |
4111 | RETURN_IF_FAIL (!ext_asm->is_goto (), ctxt, loc, | |
4112 | "cannot add output operand to asm goto"); | |
4113 | ext_asm->add_output_operand (asm_symbolic_name, constraint, dest); | |
4114 | } | |
4115 | ||
4116 | /* Public entrypoint. See description in libgccjit.h. | |
4117 | ||
4118 | After error-checking, the real work is done by the | |
4119 | gcc::jit::recording::extended_asm::add_input_operand, in | |
e53b6e56 | 4120 | jit-recording.cc. */ |
421d0d0f DM |
4121 | |
4122 | extern void | |
4123 | gcc_jit_extended_asm_add_input_operand (gcc_jit_extended_asm *ext_asm, | |
4124 | const char *asm_symbolic_name, | |
4125 | const char *constraint, | |
4126 | gcc_jit_rvalue *src) | |
4127 | { | |
4128 | RETURN_IF_FAIL (ext_asm, NULL, NULL, "NULL ext_asm"); | |
4129 | gcc::jit::recording::context *ctxt = ext_asm->get_context (); | |
4130 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
4131 | gcc::jit::recording::location *loc = ext_asm->get_loc (); | |
4132 | /* asm_symbolic_name can be NULL. */ | |
4133 | RETURN_IF_FAIL (constraint, ctxt, loc, "NULL constraint"); | |
4134 | RETURN_IF_FAIL (src, ctxt, loc, "NULL src"); | |
4135 | ext_asm->add_input_operand (asm_symbolic_name, constraint, src); | |
4136 | } | |
4137 | ||
4138 | /* Public entrypoint. See description in libgccjit.h. | |
4139 | ||
4140 | After error-checking, the real work is done by the | |
4141 | gcc::jit::recording::extended_asm::add_clobber, in | |
e53b6e56 | 4142 | jit-recording.cc. */ |
421d0d0f DM |
4143 | |
4144 | void | |
4145 | gcc_jit_extended_asm_add_clobber (gcc_jit_extended_asm *ext_asm, | |
4146 | const char *victim) | |
4147 | { | |
4148 | RETURN_IF_FAIL (ext_asm, NULL, NULL, "NULL ext_asm"); | |
4149 | gcc::jit::recording::context *ctxt = ext_asm->get_context (); | |
4150 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
4151 | gcc::jit::recording::location *loc = ext_asm->get_loc (); | |
4152 | RETURN_IF_FAIL (victim, ctxt, loc, "NULL victim"); | |
4153 | ext_asm->add_clobber (victim); | |
4154 | } | |
4155 | ||
4156 | /* Public entrypoint. See description in libgccjit.h. | |
4157 | ||
4158 | After error-checking, the real work is done by the | |
4159 | gcc::jit::recording::context::add_top_level_asm, in | |
e53b6e56 | 4160 | jit-recording.cc. */ |
421d0d0f DM |
4161 | |
4162 | void | |
4163 | gcc_jit_context_add_top_level_asm (gcc_jit_context *ctxt, | |
4164 | gcc_jit_location *loc, | |
4165 | const char *asm_stmts) | |
4166 | { | |
4167 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL ctxt"); | |
4168 | JIT_LOG_FUNC (ctxt->get_logger ()); | |
4169 | /* LOC can be NULL. */ | |
4170 | RETURN_IF_FAIL (asm_stmts, ctxt, NULL, "NULL asm_stmts"); | |
4171 | ctxt->add_top_level_asm (loc, asm_stmts); | |
4172 | } |