Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /* Implementation of the C API; all wrappers into the internal C++ API |
---|---|
2 | Copyright (C) 2013-2017 Free Software Foundation, Inc. |
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" |
24 | #include "timevar.h" |
25 | #include "typed-splay-tree.h" |
26 | |
27 | #include "libgccjit.h" |
28 | #include "jit-recording.h" |
29 | #include "jit-result.h" |
30 | |
31 | /* The opaque types used by the public API are actually subclasses |
32 | of the gcc::jit::recording classes. */ |
33 | |
34 | struct gcc_jit_context : public gcc::jit::recording::context |
35 | { |
36 | gcc_jit_context (gcc_jit_context *parent_ctxt) : |
37 | context (parent_ctxt) |
38 | {} |
39 | }; |
40 | |
41 | struct gcc_jit_result : public gcc::jit::result |
42 | { |
43 | }; |
44 | |
45 | struct gcc_jit_object : public gcc::jit::recording::memento |
46 | { |
47 | }; |
48 | |
49 | struct gcc_jit_location : public gcc::jit::recording::location |
50 | { |
51 | }; |
52 | |
53 | struct gcc_jit_type : public gcc::jit::recording::type |
54 | { |
55 | }; |
56 | |
57 | struct gcc_jit_struct : public gcc::jit::recording::struct_ |
58 | { |
59 | }; |
60 | |
61 | struct gcc_jit_field : public gcc::jit::recording::field |
62 | { |
63 | }; |
64 | |
65 | struct gcc_jit_function : public gcc::jit::recording::function |
66 | { |
67 | }; |
68 | |
69 | struct gcc_jit_block : public gcc::jit::recording::block |
70 | { |
71 | }; |
72 | |
73 | struct gcc_jit_rvalue : public gcc::jit::recording::rvalue |
74 | { |
75 | }; |
76 | |
77 | struct gcc_jit_lvalue : public gcc::jit::recording::lvalue |
78 | { |
79 | }; |
80 | |
81 | struct gcc_jit_param : public gcc::jit::recording::param |
82 | { |
83 | }; |
84 | |
85 | struct gcc_jit_case : public gcc::jit::recording::case_ |
86 | { |
87 | }; |
88 | |
89 | struct gcc_jit_timer : public timer |
90 | { |
91 | }; |
92 | |
93 | /********************************************************************** |
94 | Error-handling. |
95 | |
96 | We try to gracefully handle API usage errors by being defensive |
97 | at the API boundary. |
98 | **********************************************************************/ |
99 | |
100 | #define JIT_BEGIN_STMT do { |
101 | #define JIT_END_STMT } while(0) |
102 | |
103 | /* Each of these error-handling macros determines if TEST_EXPR holds. |
104 | |
105 | If TEXT_EXPR fails to hold we return from the enclosing function and |
106 | print an error, either via adding an error on the given context CTXT |
107 | if CTXT is non-NULL, falling back to simply printing to stderr if CTXT |
108 | is NULL. |
109 | |
110 | They have to be macros since they inject their "return" into the |
111 | function they are placed in. |
112 | |
113 | The variant macros express: |
114 | |
115 | (A) whether or not we need to return a value: |
116 | RETURN_VAL_IF_FAIL* vs |
117 | RETURN_IF_FAIL*, |
118 | with the former returning RETURN_EXPR, and |
119 | RETURN_NULL_IF_FAIL* |
120 | for the common case where a NULL value is to be returned on |
121 | error, and |
122 | |
123 | (B) whether the error message is to be directly printed: |
124 | RETURN_*IF_FAIL |
125 | or is a format string with some number of arguments: |
126 | RETURN_*IF_FAIL_PRINTF* |
127 | |
128 | They all use JIT_BEGIN_STMT/JIT_END_STMT so they can be written with |
129 | trailing semicolons. |
130 | */ |
131 | |
132 | #define RETURN_VAL_IF_FAIL(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_MSG) \ |
133 | JIT_BEGIN_STMT \ |
134 | if (!(TEST_EXPR)) \ |
135 | { \ |
136 | jit_error ((CTXT), (LOC), "%s: %s", __func__, (ERR_MSG)); \ |
137 | return (RETURN_EXPR); \ |
138 | } \ |
139 | JIT_END_STMT |
140 | |
141 | #define RETURN_VAL_IF_FAIL_PRINTF1(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0) \ |
142 | JIT_BEGIN_STMT \ |
143 | if (!(TEST_EXPR)) \ |
144 | { \ |
145 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ |
146 | __func__, (A0)); \ |
147 | return (RETURN_EXPR); \ |
148 | } \ |
149 | JIT_END_STMT |
150 | |
151 | #define RETURN_VAL_IF_FAIL_PRINTF2(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0, A1) \ |
152 | JIT_BEGIN_STMT \ |
153 | if (!(TEST_EXPR)) \ |
154 | { \ |
155 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ |
156 | __func__, (A0), (A1)); \ |
157 | return (RETURN_EXPR); \ |
158 | } \ |
159 | JIT_END_STMT |
160 | |
161 | #define RETURN_VAL_IF_FAIL_PRINTF3(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2) \ |
162 | JIT_BEGIN_STMT \ |
163 | if (!(TEST_EXPR)) \ |
164 | { \ |
165 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ |
166 | __func__, (A0), (A1), (A2)); \ |
167 | return (RETURN_EXPR); \ |
168 | } \ |
169 | JIT_END_STMT |
170 | |
171 | #define RETURN_VAL_IF_FAIL_PRINTF4(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3) \ |
172 | JIT_BEGIN_STMT \ |
173 | if (!(TEST_EXPR)) \ |
174 | { \ |
175 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ |
176 | __func__, (A0), (A1), (A2), (A3)); \ |
177 | return (RETURN_EXPR); \ |
178 | } \ |
179 | JIT_END_STMT |
180 | |
181 | #define RETURN_VAL_IF_FAIL_PRINTF5(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4) \ |
182 | JIT_BEGIN_STMT \ |
183 | if (!(TEST_EXPR)) \ |
184 | { \ |
185 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ |
186 | __func__, (A0), (A1), (A2), (A3), (A4)); \ |
187 | return (RETURN_EXPR); \ |
188 | } \ |
189 | JIT_END_STMT |
190 | |
191 | #define RETURN_VAL_IF_FAIL_PRINTF6(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4, A5) \ |
192 | JIT_BEGIN_STMT \ |
193 | if (!(TEST_EXPR)) \ |
194 | { \ |
195 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ |
196 | __func__, (A0), (A1), (A2), (A3), (A4), (A5)); \ |
197 | return (RETURN_EXPR); \ |
198 | } \ |
199 | JIT_END_STMT |
200 | |
201 | #define RETURN_NULL_IF_FAIL(TEST_EXPR, CTXT, LOC, ERR_MSG) \ |
202 | RETURN_VAL_IF_FAIL ((TEST_EXPR), NULL, (CTXT), (LOC), (ERR_MSG)) |
203 | |
204 | #define RETURN_NULL_IF_FAIL_PRINTF1(TEST_EXPR, CTXT, LOC, ERR_FMT, A0) \ |
205 | RETURN_VAL_IF_FAIL_PRINTF1 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0) |
206 | |
207 | #define RETURN_NULL_IF_FAIL_PRINTF2(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1) \ |
208 | RETURN_VAL_IF_FAIL_PRINTF2 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1) |
209 | |
210 | #define RETURN_NULL_IF_FAIL_PRINTF3(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2) \ |
211 | RETURN_VAL_IF_FAIL_PRINTF3 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2) |
212 | |
213 | #define RETURN_NULL_IF_FAIL_PRINTF4(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3) \ |
214 | RETURN_VAL_IF_FAIL_PRINTF4 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2, A3) |
215 | |
216 | #define RETURN_NULL_IF_FAIL_PRINTF5(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4) \ |
217 | RETURN_VAL_IF_FAIL_PRINTF5 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4) |
218 | |
219 | #define RETURN_NULL_IF_FAIL_PRINTF6(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4, A5) \ |
220 | RETURN_VAL_IF_FAIL_PRINTF6 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4, A5) |
221 | |
222 | #define RETURN_IF_FAIL(TEST_EXPR, CTXT, LOC, ERR_MSG) \ |
223 | JIT_BEGIN_STMT \ |
224 | if (!(TEST_EXPR)) \ |
225 | { \ |
226 | jit_error ((CTXT), (LOC), "%s: %s", __func__, (ERR_MSG)); \ |
227 | return; \ |
228 | } \ |
229 | JIT_END_STMT |
230 | |
231 | #define RETURN_IF_FAIL_PRINTF1(TEST_EXPR, CTXT, LOC, ERR_FMT, A0) \ |
232 | JIT_BEGIN_STMT \ |
233 | if (!(TEST_EXPR)) \ |
234 | { \ |
235 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ |
236 | __func__, (A0)); \ |
237 | return; \ |
238 | } \ |
239 | JIT_END_STMT |
240 | |
241 | #define RETURN_IF_FAIL_PRINTF2(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1) \ |
242 | JIT_BEGIN_STMT \ |
243 | if (!(TEST_EXPR)) \ |
244 | { \ |
245 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ |
246 | __func__, (A0), (A1)); \ |
247 | return; \ |
248 | } \ |
249 | JIT_END_STMT |
250 | |
251 | #define RETURN_IF_FAIL_PRINTF4(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3) \ |
252 | JIT_BEGIN_STMT \ |
253 | if (!(TEST_EXPR)) \ |
254 | { \ |
255 | jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ |
256 | __func__, (A0), (A1), (A2), (A3)); \ |
257 | return; \ |
258 | } \ |
259 | JIT_END_STMT |
260 | |
261 | /* Check that BLOCK is non-NULL, and that it's OK to add statements to |
262 | it. This will fail if BLOCK has already been terminated by some |
263 | kind of jump or a return. */ |
264 | #define RETURN_IF_NOT_VALID_BLOCK(BLOCK, LOC) \ |
265 | JIT_BEGIN_STMT \ |
266 | RETURN_IF_FAIL ((BLOCK), NULL, (LOC), "NULL block"); \ |
267 | RETURN_IF_FAIL_PRINTF2 ( \ |
268 | !(BLOCK)->has_been_terminated (), \ |
269 | (BLOCK)->get_context (), \ |
270 | (LOC), \ |
271 | "adding to terminated block: %s (already terminated by: %s)", \ |
272 | (BLOCK)->get_debug_string (), \ |
273 | (BLOCK)->get_last_statement ()->get_debug_string ()); \ |
274 | JIT_END_STMT |
275 | |
276 | /* As RETURN_IF_NOT_VALID_BLOCK, but injecting a "return NULL;" if it |
277 | fails. */ |
278 | #define RETURN_NULL_IF_NOT_VALID_BLOCK(BLOCK, LOC) \ |
279 | JIT_BEGIN_STMT \ |
280 | RETURN_NULL_IF_FAIL ((BLOCK), NULL, (LOC), "NULL block"); \ |
281 | RETURN_NULL_IF_FAIL_PRINTF2 ( \ |
282 | !(BLOCK)->has_been_terminated (), \ |
283 | (BLOCK)->get_context (), \ |
284 | (LOC), \ |
285 | "adding to terminated block: %s (already terminated by: %s)", \ |
286 | (BLOCK)->get_debug_string (), \ |
287 | (BLOCK)->get_last_statement ()->get_debug_string ()); \ |
288 | JIT_END_STMT |
289 | |
290 | /* Format the given string, and report it as an error, either on CTXT |
291 | if non-NULL, or by printing to stderr if we have a NULL context. |
292 | LOC gives the source location where the error occcurred, and can be |
293 | NULL. */ |
294 | |
295 | static void |
296 | jit_error (gcc::jit::recording::context *ctxt, |
297 | gcc_jit_location *loc, |
298 | const char *fmt, ...) |
299 | GNU_PRINTF(3, 4); |
300 | |
301 | static void |
302 | jit_error (gcc::jit::recording::context *ctxt, |
303 | gcc_jit_location *loc, |
304 | const char *fmt, ...) |
305 | { |
306 | va_list ap; |
307 | va_start (ap, fmt); |
308 | |
309 | if (ctxt) |
310 | ctxt->add_error_va (loc, fmt, ap); |
311 | else |
312 | { |
313 | /* No context? Send to stderr. */ |
314 | vfprintf (stderr, fmt, ap); |
315 | fprintf (stderr, "\n"); |
316 | } |
317 | |
318 | va_end (ap); |
319 | } |
320 | |
321 | /* Determine whether or not we can write to lvalues of type LTYPE from |
322 | rvalues of type RTYPE, detecting type errors such as attempting to |
323 | write to an int with a string literal (without an explicit cast). |
324 | |
325 | This is implemented by calling the |
326 | gcc::jit::recording::type::accepts_writes_from virtual function on |
327 | LTYPE. */ |
328 | |
329 | static bool |
330 | compatible_types (gcc::jit::recording::type *ltype, |
331 | gcc::jit::recording::type *rtype) |
332 | { |
333 | return ltype->accepts_writes_from (rtype); |
334 | } |
335 | |
336 | /* Public entrypoint for acquiring a gcc_jit_context. |
337 | Note that this creates a new top-level context; contrast with |
338 | gcc_jit_context_new_child_context below. |
339 | |
340 | The real work is done in the constructor for |
341 | gcc::jit::recording::context in jit-recording.c. */ |
342 | |
343 | gcc_jit_context * |
344 | gcc_jit_context_acquire (void) |
345 | { |
346 | gcc_jit_context *ctxt = new gcc_jit_context (NULL); |
347 | ctxt->log ("new top-level ctxt: %p", (void *)ctxt); |
348 | return ctxt; |
349 | } |
350 | |
351 | /* Public entrypoint for releasing a gcc_jit_context. |
352 | The real work is done in the destructor for |
353 | gcc::jit::recording::context in jit-recording.c. */ |
354 | |
355 | void |
356 | gcc_jit_context_release (gcc_jit_context *ctxt) |
357 | { |
358 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL ctxt"); |
359 | JIT_LOG_FUNC (ctxt->get_logger ()); |
360 | ctxt->log ("deleting ctxt: %p", (void *)ctxt); |
361 | delete ctxt; |
362 | } |
363 | |
364 | /* Public entrypoint for creating a child context within |
365 | PARENT_CTXT. See description in libgccjit.h. |
366 | |
367 | The real work is done in the constructor for |
368 | gcc::jit::recording::context in jit-recording.c. */ |
369 | |
370 | gcc_jit_context * |
371 | gcc_jit_context_new_child_context (gcc_jit_context *parent_ctxt) |
372 | { |
373 | RETURN_NULL_IF_FAIL (parent_ctxt, NULL, NULL, "NULL parent ctxt"); |
374 | JIT_LOG_FUNC (parent_ctxt->get_logger ()); |
375 | parent_ctxt->log ("parent_ctxt: %p", (void *)parent_ctxt); |
376 | gcc_jit_context *child_ctxt = new gcc_jit_context (parent_ctxt); |
377 | child_ctxt->log ("new child_ctxt: %p", (void *)child_ctxt); |
378 | return child_ctxt; |
379 | } |
380 | |
381 | /* Public entrypoint. See description in libgccjit.h. |
382 | |
383 | After error-checking, the real work is done by the |
384 | gcc::jit::recording::context::new_location |
385 | method in jit-recording.c. */ |
386 | |
387 | gcc_jit_location * |
388 | gcc_jit_context_new_location (gcc_jit_context *ctxt, |
389 | const char *filename, |
390 | int line, |
391 | int column) |
392 | { |
393 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
394 | JIT_LOG_FUNC (ctxt->get_logger ()); |
395 | return (gcc_jit_location *)ctxt->new_location (filename, line, column, true); |
396 | } |
397 | |
398 | /* Public entrypoint. See description in libgccjit.h. |
399 | |
400 | After error-checking, this calls the trivial |
401 | gcc::jit::recording::memento::as_object method (a location is a |
402 | memento), in jit-recording.h. */ |
403 | |
404 | gcc_jit_object * |
405 | gcc_jit_location_as_object (gcc_jit_location *loc) |
406 | { |
407 | RETURN_NULL_IF_FAIL (loc, NULL, NULL, "NULL location"); |
408 | |
409 | return static_cast <gcc_jit_object *> (loc->as_object ()); |
410 | } |
411 | |
412 | /* Public entrypoint. See description in libgccjit.h. |
413 | |
414 | After error-checking, this calls the trivial |
415 | gcc::jit::recording::memento::as_object method (a type is a |
416 | memento), in jit-recording.h. */ |
417 | |
418 | gcc_jit_object * |
419 | gcc_jit_type_as_object (gcc_jit_type *type) |
420 | { |
421 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); |
422 | |
423 | return static_cast <gcc_jit_object *> (type->as_object ()); |
424 | } |
425 | |
426 | /* Public entrypoint for getting a specific type from a context. |
427 | |
428 | After error-checking, the real work is done by the |
429 | gcc::jit::recording::context::get_type method, in |
430 | jit-recording.c */ |
431 | |
432 | gcc_jit_type * |
433 | gcc_jit_context_get_type (gcc_jit_context *ctxt, |
434 | enum gcc_jit_types type) |
435 | { |
436 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
437 | JIT_LOG_FUNC (ctxt->get_logger ()); |
438 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
439 | (type >= GCC_JIT_TYPE_VOID |
440 | && type <= GCC_JIT_TYPE_FILE_PTR), |
441 | ctxt, NULL, |
442 | "unrecognized value for enum gcc_jit_types: %i", type); |
443 | |
444 | return (gcc_jit_type *)ctxt->get_type (type); |
445 | } |
446 | |
447 | /* Public entrypoint for getting the integer type of the given size and |
448 | signedness. |
449 | |
450 | After error-checking, the real work is done by the |
451 | gcc::jit::recording::context::get_int_type method, |
452 | in jit-recording.c. */ |
453 | |
454 | gcc_jit_type * |
455 | gcc_jit_context_get_int_type (gcc_jit_context *ctxt, |
456 | int num_bytes, int is_signed) |
457 | { |
458 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
459 | JIT_LOG_FUNC (ctxt->get_logger ()); |
460 | RETURN_NULL_IF_FAIL (num_bytes >= 0, ctxt, NULL, "negative size"); |
461 | |
462 | return (gcc_jit_type *)ctxt->get_int_type (num_bytes, is_signed); |
463 | } |
464 | |
465 | /* Public entrypoint. See description in libgccjit.h. |
466 | |
467 | After error-checking, the real work is done by the |
468 | gcc::jit::recording::type::get_pointer method, in |
469 | jit-recording.c */ |
470 | |
471 | gcc_jit_type * |
472 | gcc_jit_type_get_pointer (gcc_jit_type *type) |
473 | { |
474 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); |
475 | |
476 | return (gcc_jit_type *)type->get_pointer (); |
477 | } |
478 | |
479 | /* Public entrypoint. See description in libgccjit.h. |
480 | |
481 | After error-checking, the real work is done by the |
482 | gcc::jit::recording::type::get_const method, in |
483 | jit-recording.c. */ |
484 | |
485 | gcc_jit_type * |
486 | gcc_jit_type_get_const (gcc_jit_type *type) |
487 | { |
488 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); |
489 | |
490 | return (gcc_jit_type *)type->get_const (); |
491 | } |
492 | |
493 | /* Public entrypoint. See description in libgccjit.h. |
494 | |
495 | After error-checking, the real work is done by the |
496 | gcc::jit::recording::type::get_volatile method, in |
497 | jit-recording.c. */ |
498 | |
499 | gcc_jit_type * |
500 | gcc_jit_type_get_volatile (gcc_jit_type *type) |
501 | { |
502 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); |
503 | |
504 | return (gcc_jit_type *)type->get_volatile (); |
505 | } |
506 | |
507 | /* Public entrypoint. See description in libgccjit.h. |
508 | |
509 | After error-checking, the real work is done by the |
510 | gcc::jit::recording::context::new_array_type method, in |
511 | jit-recording.c. */ |
512 | |
513 | gcc_jit_type * |
514 | gcc_jit_context_new_array_type (gcc_jit_context *ctxt, |
515 | gcc_jit_location *loc, |
516 | gcc_jit_type *element_type, |
517 | int num_elements) |
518 | { |
519 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
520 | JIT_LOG_FUNC (ctxt->get_logger ()); |
521 | /* LOC can be NULL. */ |
522 | RETURN_NULL_IF_FAIL (element_type, ctxt, loc, "NULL type"); |
523 | RETURN_NULL_IF_FAIL (num_elements >= 0, ctxt, NULL, "negative size"); |
524 | |
525 | return (gcc_jit_type *)ctxt->new_array_type (loc, |
526 | element_type, |
527 | num_elements); |
528 | } |
529 | |
530 | /* Public entrypoint. See description in libgccjit.h. |
531 | |
532 | After error-checking, the real work is done by the |
533 | gcc::jit::recording::context::new_field method, in |
534 | jit-recording.c. */ |
535 | |
536 | gcc_jit_field * |
537 | gcc_jit_context_new_field (gcc_jit_context *ctxt, |
538 | gcc_jit_location *loc, |
539 | gcc_jit_type *type, |
540 | const char *name) |
541 | { |
542 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
543 | JIT_LOG_FUNC (ctxt->get_logger ()); |
544 | /* LOC can be NULL. */ |
545 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); |
546 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); |
547 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
548 | type->has_known_size (), |
549 | ctxt, loc, |
550 | "unknown size for field \"%s\" (type: %s)", |
551 | name, |
552 | type->get_debug_string ()); |
553 | |
554 | return (gcc_jit_field *)ctxt->new_field (loc, type, name); |
555 | } |
556 | |
557 | /* Public entrypoint. See description in libgccjit.h. |
558 | |
559 | After error-checking, this calls the trivial |
560 | gcc::jit::recording::memento::as_object method (a field is a |
561 | memento), in jit-recording.h. */ |
562 | |
563 | gcc_jit_object * |
564 | gcc_jit_field_as_object (gcc_jit_field *field) |
565 | { |
566 | RETURN_NULL_IF_FAIL (field, NULL, NULL, "NULL field"); |
567 | |
568 | return static_cast <gcc_jit_object *> (field->as_object ()); |
569 | } |
570 | |
571 | /* Public entrypoint. See description in libgccjit.h. |
572 | |
573 | After error-checking, the real work is done by the |
574 | gcc::jit::recording::context::new_struct_type method, |
575 | immediately followed by a "set_fields" call on the resulting |
576 | gcc::jit::recording::compound_type *, both in jit-recording.c */ |
577 | |
578 | gcc_jit_struct * |
579 | gcc_jit_context_new_struct_type (gcc_jit_context *ctxt, |
580 | gcc_jit_location *loc, |
581 | const char *name, |
582 | int num_fields, |
583 | gcc_jit_field **fields) |
584 | { |
585 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
586 | JIT_LOG_FUNC (ctxt->get_logger ()); |
587 | /* LOC can be NULL. */ |
588 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); |
589 | if (num_fields) |
590 | RETURN_NULL_IF_FAIL (fields, ctxt, loc, "NULL fields ptr"); |
591 | for (int i = 0; i < num_fields; i++) |
592 | { |
593 | RETURN_NULL_IF_FAIL (fields[i], ctxt, loc, "NULL field ptr"); |
594 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
595 | NULL == fields[i]->get_container (), |
596 | ctxt, loc, |
597 | "%s is already a field of %s", |
598 | fields[i]->get_debug_string (), |
599 | fields[i]->get_container ()->get_debug_string ()); |
600 | } |
601 | |
602 | gcc::jit::recording::struct_ *result = |
603 | ctxt->new_struct_type (loc, name); |
604 | result->set_fields (loc, |
605 | num_fields, |
606 | (gcc::jit::recording::field **)fields); |
607 | return static_cast<gcc_jit_struct *> (result); |
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::context::new_struct_type method in |
614 | jit-recording.c. */ |
615 | |
616 | gcc_jit_struct * |
617 | gcc_jit_context_new_opaque_struct (gcc_jit_context *ctxt, |
618 | gcc_jit_location *loc, |
619 | const char *name) |
620 | { |
621 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
622 | JIT_LOG_FUNC (ctxt->get_logger ()); |
623 | /* LOC can be NULL. */ |
624 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); |
625 | |
626 | return (gcc_jit_struct *)ctxt->new_struct_type (loc, name); |
627 | } |
628 | |
629 | /* Public entrypoint. See description in libgccjit.h. |
630 | |
631 | After error-checking, this calls the trivial |
632 | gcc::jit::recording::struct_::as_object method in |
633 | jit-recording.h. */ |
634 | |
635 | gcc_jit_type * |
636 | gcc_jit_struct_as_type (gcc_jit_struct *struct_type) |
637 | { |
638 | RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct_type"); |
639 | |
640 | return static_cast <gcc_jit_type *> (struct_type->as_type ()); |
641 | } |
642 | |
643 | /* Public entrypoint. See description in libgccjit.h. |
644 | |
645 | After error-checking, the real work is done by the |
646 | gcc::jit::recording::compound_type::set_fields method in |
647 | jit-recording.c. */ |
648 | |
649 | void |
650 | gcc_jit_struct_set_fields (gcc_jit_struct *struct_type, |
651 | gcc_jit_location *loc, |
652 | int num_fields, |
653 | gcc_jit_field **fields) |
654 | { |
655 | RETURN_IF_FAIL (struct_type, NULL, loc, "NULL struct_type"); |
656 | gcc::jit::recording::context *ctxt = struct_type->m_ctxt; |
657 | JIT_LOG_FUNC (ctxt->get_logger ()); |
658 | /* LOC can be NULL. */ |
659 | RETURN_IF_FAIL_PRINTF1 ( |
660 | NULL == struct_type->get_fields (), ctxt, loc, |
661 | "%s already has had fields set", |
662 | struct_type->get_debug_string ()); |
663 | if (num_fields) |
664 | RETURN_IF_FAIL (fields, ctxt, loc, "NULL fields ptr"); |
665 | for (int i = 0; i < num_fields; i++) |
666 | { |
667 | RETURN_IF_FAIL_PRINTF2 ( |
668 | fields[i], |
669 | ctxt, loc, |
670 | "%s: NULL field ptr at index %i", |
671 | struct_type->get_debug_string (), |
672 | i); |
673 | RETURN_IF_FAIL_PRINTF2 ( |
674 | NULL == fields[i]->get_container (), |
675 | ctxt, loc, |
676 | "%s is already a field of %s", |
677 | fields[i]->get_debug_string (), |
678 | fields[i]->get_container ()->get_debug_string ()); |
679 | } |
680 | |
681 | struct_type->set_fields (loc, num_fields, |
682 | (gcc::jit::recording::field **)fields); |
683 | } |
684 | |
685 | /* Public entrypoint. See description in libgccjit.h. |
686 | |
687 | After error-checking, the real work is done by the |
688 | gcc::jit::recording::context::new_union_type method, |
689 | immediately followed by a "set_fields" call on the resulting |
690 | gcc::jit::recording::compound_type *, both in jit-recording.c */ |
691 | |
692 | gcc_jit_type * |
693 | gcc_jit_context_new_union_type (gcc_jit_context *ctxt, |
694 | gcc_jit_location *loc, |
695 | const char *name, |
696 | int num_fields, |
697 | gcc_jit_field **fields) |
698 | { |
699 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
700 | JIT_LOG_FUNC (ctxt->get_logger ()); |
701 | /* LOC can be NULL. */ |
702 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); |
703 | if (num_fields) |
704 | RETURN_NULL_IF_FAIL (fields, ctxt, loc, "NULL fields ptr"); |
705 | for (int i = 0; i < num_fields; i++) |
706 | { |
707 | RETURN_NULL_IF_FAIL (fields[i], ctxt, loc, "NULL field ptr"); |
708 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
709 | NULL == fields[i]->get_container (), |
710 | ctxt, loc, |
711 | "%s is already a field of %s", |
712 | fields[i]->get_debug_string (), |
713 | fields[i]->get_container ()->get_debug_string ()); |
714 | } |
715 | |
716 | gcc::jit::recording::union_ *result = |
717 | ctxt->new_union_type (loc, name); |
718 | result->set_fields (loc, |
719 | num_fields, |
720 | (gcc::jit::recording::field **)fields); |
721 | return (gcc_jit_type *) (result); |
722 | } |
723 | |
724 | /* Public entrypoint. See description in libgccjit.h. |
725 | |
726 | After error-checking, the real work is done by the |
727 | gcc::jit::recording::context::new_function_ptr_type method, |
728 | in jit-recording.c */ |
729 | |
730 | gcc_jit_type * |
731 | gcc_jit_context_new_function_ptr_type (gcc_jit_context *ctxt, |
732 | gcc_jit_location *loc, |
733 | gcc_jit_type *return_type, |
734 | int num_params, |
735 | gcc_jit_type **param_types, |
736 | int is_variadic) |
737 | { |
738 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
739 | JIT_LOG_FUNC (ctxt->get_logger ()); |
740 | /* LOC can be NULL. */ |
741 | RETURN_NULL_IF_FAIL (return_type, ctxt, loc, "NULL return_type"); |
742 | RETURN_NULL_IF_FAIL ( |
743 | (num_params == 0) || param_types, |
744 | ctxt, loc, |
745 | "NULL param_types creating function pointer type"); |
746 | for (int i = 0; i < num_params; i++) |
747 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
748 | param_types[i], |
749 | ctxt, loc, |
750 | "NULL parameter type %i creating function pointer type", i); |
751 | |
752 | return (gcc_jit_type*) |
753 | ctxt->new_function_ptr_type (loc, return_type, |
754 | num_params, |
755 | (gcc::jit::recording::type **)param_types, |
756 | is_variadic); |
757 | } |
758 | |
759 | /* Constructing functions. */ |
760 | |
761 | /* Public entrypoint. See description in libgccjit.h. |
762 | |
763 | After error-checking, the real work is done by the |
764 | gcc::jit::recording::context::new_param method, in jit-recording.c */ |
765 | |
766 | gcc_jit_param * |
767 | gcc_jit_context_new_param (gcc_jit_context *ctxt, |
768 | gcc_jit_location *loc, |
769 | gcc_jit_type *type, |
770 | const char *name) |
771 | { |
772 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
773 | JIT_LOG_FUNC (ctxt->get_logger ()); |
774 | /* LOC can be NULL. */ |
775 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); |
776 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); |
777 | |
778 | return (gcc_jit_param *)ctxt->new_param (loc, type, name); |
779 | } |
780 | |
781 | /* Public entrypoint. See description in libgccjit.h. |
782 | |
783 | After error-checking, this calls the trivial |
784 | gcc::jit::recording::memento::as_object method (a param is a memento), |
785 | in jit-recording.h. */ |
786 | |
787 | gcc_jit_object * |
788 | gcc_jit_param_as_object (gcc_jit_param *param) |
789 | { |
790 | RETURN_NULL_IF_FAIL (param, NULL, NULL, "NULL param"); |
791 | |
792 | return static_cast <gcc_jit_object *> (param->as_object ()); |
793 | } |
794 | |
795 | /* Public entrypoint. See description in libgccjit.h. |
796 | |
797 | After error-checking, this calls the trivial |
798 | gcc::jit::recording::param::as_lvalue method in jit-recording.h. */ |
799 | |
800 | gcc_jit_lvalue * |
801 | gcc_jit_param_as_lvalue (gcc_jit_param *param) |
802 | { |
803 | RETURN_NULL_IF_FAIL (param, NULL, NULL, "NULL param"); |
804 | |
805 | return (gcc_jit_lvalue *)param->as_lvalue (); |
806 | } |
807 | |
808 | /* Public entrypoint. See description in libgccjit.h. |
809 | |
810 | After error-checking, this calls the trivial |
811 | gcc::jit::recording::lvalue::as_rvalue method (a param is an rvalue), |
812 | in jit-recording.h. */ |
813 | |
814 | gcc_jit_rvalue * |
815 | gcc_jit_param_as_rvalue (gcc_jit_param *param) |
816 | { |
817 | RETURN_NULL_IF_FAIL (param, NULL, NULL, "NULL param"); |
818 | |
819 | return (gcc_jit_rvalue *)param->as_rvalue (); |
820 | } |
821 | |
822 | /* Public entrypoint. See description in libgccjit.h. |
823 | |
824 | After error-checking, the real work is done by the |
825 | gcc::jit::recording::context::new_function method, in |
826 | jit-recording.c. */ |
827 | |
828 | gcc_jit_function * |
829 | gcc_jit_context_new_function (gcc_jit_context *ctxt, |
830 | gcc_jit_location *loc, |
831 | enum gcc_jit_function_kind kind, |
832 | gcc_jit_type *return_type, |
833 | const char *name, |
834 | int num_params, |
835 | gcc_jit_param **params, |
836 | int is_variadic) |
837 | { |
838 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
839 | JIT_LOG_FUNC (ctxt->get_logger ()); |
840 | /* LOC can be NULL. */ |
841 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
842 | ((kind >= GCC_JIT_FUNCTION_EXPORTED) |
843 | && (kind <= GCC_JIT_FUNCTION_ALWAYS_INLINE)), |
844 | ctxt, loc, |
845 | "unrecognized value for enum gcc_jit_function_kind: %i", |
846 | kind); |
847 | RETURN_NULL_IF_FAIL (return_type, ctxt, loc, "NULL return_type"); |
848 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); |
849 | /* The assembler can only handle certain names, so for now, enforce |
850 | C's rules for identiers upon the name, using ISALPHA and ISALNUM |
851 | from safe-ctype.h to ignore the current locale. |
852 | Eventually we'll need some way to interact with e.g. C++ name |
853 | mangling. */ |
854 | { |
855 | /* Leading char: */ |
856 | char ch = *name; |
857 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
858 | ISALPHA (ch) || ch == '_', |
859 | ctxt, loc, |
860 | "name \"%s\" contains invalid character: '%c'", |
861 | name, ch); |
862 | /* Subsequent chars: */ |
863 | for (const char *ptr = name + 1; (ch = *ptr); ptr++) |
864 | { |
865 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
866 | ISALNUM (ch) || ch == '_', |
867 | ctxt, loc, |
868 | "name \"%s\" contains invalid character: '%c'", |
869 | name, ch); |
870 | } |
871 | } |
872 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
873 | (num_params == 0) || params, |
874 | ctxt, loc, |
875 | "NULL params creating function %s", name); |
876 | for (int i = 0; i < num_params; i++) |
877 | { |
878 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
879 | params[i], |
880 | ctxt, loc, |
881 | "NULL parameter %i creating function %s", i, name); |
882 | RETURN_NULL_IF_FAIL_PRINTF5 ( |
883 | (NULL == params[i]->get_scope ()), |
884 | ctxt, loc, |
885 | "parameter %i \"%s\"" |
886 | " (type: %s)" |
887 | " for function %s" |
888 | " was already used for function %s", |
889 | i, params[i]->get_debug_string (), |
890 | params[i]->get_type ()->get_debug_string (), |
891 | name, |
892 | params[i]->get_scope ()->get_debug_string ()); |
893 | } |
894 | |
895 | return (gcc_jit_function*) |
896 | ctxt->new_function (loc, kind, return_type, name, |
897 | num_params, |
898 | (gcc::jit::recording::param **)params, |
899 | is_variadic, |
900 | BUILT_IN_NONE); |
901 | } |
902 | |
903 | /* Public entrypoint. See description in libgccjit.h. |
904 | |
905 | After error-checking, the real work is done by the |
906 | gcc::jit::recording::context::get_builtin_function method, in |
907 | jit-recording.c. */ |
908 | |
909 | gcc_jit_function * |
910 | gcc_jit_context_get_builtin_function (gcc_jit_context *ctxt, |
911 | const char *name) |
912 | { |
913 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
914 | JIT_LOG_FUNC (ctxt->get_logger ()); |
915 | RETURN_NULL_IF_FAIL (name, ctxt, NULL, "NULL name"); |
916 | |
917 | return static_cast <gcc_jit_function *> (ctxt->get_builtin_function (name)); |
918 | } |
919 | |
920 | /* Public entrypoint. See description in libgccjit.h. |
921 | |
922 | After error-checking, this calls the trivial |
923 | gcc::jit::recording::memento::as_object method (a function is a |
924 | memento), in jit-recording.h. */ |
925 | |
926 | gcc_jit_object * |
927 | gcc_jit_function_as_object (gcc_jit_function *func) |
928 | { |
929 | RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function"); |
930 | |
931 | return static_cast <gcc_jit_object *> (func->as_object ()); |
932 | } |
933 | |
934 | /* Public entrypoint. See description in libgccjit.h. |
935 | |
936 | After error-checking, the real work is done by the |
937 | gcc::jit::recording::function::get_param method, in |
938 | jit-recording.h. */ |
939 | |
940 | gcc_jit_param * |
941 | gcc_jit_function_get_param (gcc_jit_function *func, int index) |
942 | { |
943 | RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function"); |
944 | gcc::jit::recording::context *ctxt = func->m_ctxt; |
945 | JIT_LOG_FUNC (ctxt->get_logger ()); |
946 | RETURN_NULL_IF_FAIL (index >= 0, ctxt, NULL, "negative index"); |
947 | int num_params = func->get_params ().length (); |
948 | RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params, |
949 | ctxt, NULL, |
950 | "index of %d is too large (%s has %d params)", |
951 | index, |
952 | func->get_debug_string (), |
953 | num_params); |
954 | |
955 | return static_cast <gcc_jit_param *> (func->get_param (index)); |
956 | } |
957 | |
958 | /* Public entrypoint. See description in libgccjit.h. |
959 | |
960 | After error-checking, the real work is done by the |
961 | gcc::jit::recording::function::dump_to_dot method, in |
962 | jit-recording.c. */ |
963 | |
964 | void |
965 | gcc_jit_function_dump_to_dot (gcc_jit_function *func, |
966 | const char *path) |
967 | { |
968 | RETURN_IF_FAIL (func, NULL, NULL, "NULL function"); |
969 | gcc::jit::recording::context *ctxt = func->m_ctxt; |
970 | JIT_LOG_FUNC (ctxt->get_logger ()); |
971 | RETURN_IF_FAIL (path, ctxt, NULL, "NULL path"); |
972 | |
973 | func->dump_to_dot (path); |
974 | } |
975 | |
976 | /* Public entrypoint. See description in libgccjit.h. |
977 | |
978 | After error-checking, the real work is done by the |
979 | gcc::jit::recording::function::new_block method, in |
980 | jit-recording.c. */ |
981 | |
982 | gcc_jit_block* |
983 | gcc_jit_function_new_block (gcc_jit_function *func, |
984 | const char *name) |
985 | { |
986 | RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function"); |
987 | JIT_LOG_FUNC (func->get_context ()->get_logger ()); |
988 | RETURN_NULL_IF_FAIL (func->get_kind () != GCC_JIT_FUNCTION_IMPORTED, |
989 | func->get_context (), NULL, |
990 | "cannot add block to an imported function"); |
991 | /* name can be NULL. */ |
992 | |
993 | return (gcc_jit_block *)func->new_block (name); |
994 | } |
995 | |
996 | /* Public entrypoint. See description in libgccjit.h. |
997 | |
998 | After error-checking, this calls the trivial |
999 | gcc::jit::recording::memento::as_object method (a block is a |
1000 | memento), in jit-recording.h. */ |
1001 | |
1002 | gcc_jit_object * |
1003 | gcc_jit_block_as_object (gcc_jit_block *block) |
1004 | { |
1005 | RETURN_NULL_IF_FAIL (block, NULL, NULL, "NULL block"); |
1006 | |
1007 | return static_cast <gcc_jit_object *> (block->as_object ()); |
1008 | } |
1009 | |
1010 | /* Public entrypoint. See description in libgccjit.h. |
1011 | |
1012 | After error-checking, the real work is done by the |
1013 | gcc::jit::recording::block::get_function method, in |
1014 | jit-recording.h. */ |
1015 | |
1016 | gcc_jit_function * |
1017 | gcc_jit_block_get_function (gcc_jit_block *block) |
1018 | { |
1019 | RETURN_NULL_IF_FAIL (block, NULL, NULL, "NULL block"); |
1020 | |
1021 | return static_cast <gcc_jit_function *> (block->get_function ()); |
1022 | } |
1023 | |
1024 | /* Public entrypoint. See description in libgccjit.h. |
1025 | |
1026 | After error-checking, the real work is done by the |
1027 | gcc::jit::recording::context::new_global method, in |
1028 | jit-recording.c. */ |
1029 | |
1030 | gcc_jit_lvalue * |
1031 | gcc_jit_context_new_global (gcc_jit_context *ctxt, |
1032 | gcc_jit_location *loc, |
1033 | enum gcc_jit_global_kind kind, |
1034 | gcc_jit_type *type, |
1035 | const char *name) |
1036 | { |
1037 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
1038 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1039 | /* LOC can be NULL. */ |
1040 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
1041 | ((kind >= GCC_JIT_GLOBAL_EXPORTED) |
1042 | && (kind <= GCC_JIT_GLOBAL_IMPORTED)), |
1043 | ctxt, loc, |
1044 | "unrecognized value for enum gcc_jit_global_kind: %i", |
1045 | kind); |
1046 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); |
1047 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); |
1048 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
1049 | type->has_known_size (), |
1050 | ctxt, loc, |
1051 | "unknown size for global \"%s\" (type: %s)", |
1052 | name, |
1053 | type->get_debug_string ()); |
1054 | |
1055 | return (gcc_jit_lvalue *)ctxt->new_global (loc, kind, type, name); |
1056 | } |
1057 | |
1058 | /* Public entrypoint. See description in libgccjit.h. |
1059 | |
1060 | After error-checking, this calls the trivial |
1061 | gcc::jit::recording::memento::as_object method (an lvalue is a |
1062 | memento), in jit-recording.h. */ |
1063 | |
1064 | gcc_jit_object * |
1065 | gcc_jit_lvalue_as_object (gcc_jit_lvalue *lvalue) |
1066 | { |
1067 | RETURN_NULL_IF_FAIL (lvalue, NULL, NULL, "NULL lvalue"); |
1068 | |
1069 | return static_cast <gcc_jit_object *> (lvalue->as_object ()); |
1070 | } |
1071 | |
1072 | /* Public entrypoint. See description in libgccjit.h. |
1073 | |
1074 | After error-checking, this calls the trivial |
1075 | gcc::jit::recording::lvalue::as_rvalue method in jit-recording.h. */ |
1076 | |
1077 | gcc_jit_rvalue * |
1078 | gcc_jit_lvalue_as_rvalue (gcc_jit_lvalue *lvalue) |
1079 | { |
1080 | RETURN_NULL_IF_FAIL (lvalue, NULL, NULL, "NULL lvalue"); |
1081 | |
1082 | return (gcc_jit_rvalue *)lvalue->as_rvalue (); |
1083 | } |
1084 | |
1085 | /* Public entrypoint. See description in libgccjit.h. |
1086 | |
1087 | After error-checking, this calls the trivial |
1088 | gcc::jit::recording::memento::as_object method (an rvalue is a |
1089 | memento), in jit-recording.h. */ |
1090 | |
1091 | gcc_jit_object * |
1092 | gcc_jit_rvalue_as_object (gcc_jit_rvalue *rvalue) |
1093 | { |
1094 | RETURN_NULL_IF_FAIL (rvalue, NULL, NULL, "NULL rvalue"); |
1095 | |
1096 | return static_cast <gcc_jit_object *> (rvalue->as_object ()); |
1097 | } |
1098 | |
1099 | /* Public entrypoint. See description in libgccjit.h. |
1100 | |
1101 | After error-checking, the real work is done by the |
1102 | gcc::jit::recording::rvalue::get_type method, in |
1103 | jit-recording.h. */ |
1104 | |
1105 | gcc_jit_type * |
1106 | gcc_jit_rvalue_get_type (gcc_jit_rvalue *rvalue) |
1107 | { |
1108 | RETURN_NULL_IF_FAIL (rvalue, NULL, NULL, "NULL rvalue"); |
1109 | |
1110 | return static_cast <gcc_jit_type *> (rvalue->get_type ()); |
1111 | } |
1112 | |
1113 | /* Verify that NUMERIC_TYPE is non-NULL, and that it is a "numeric" |
1114 | type i.e. it satisfies gcc::jit::type::is_numeric (), such as the |
1115 | result of gcc_jit_context_get_type (GCC_JIT_TYPE_INT). */ |
1116 | |
1117 | #define RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE(CTXT, NUMERIC_TYPE) \ |
1118 | JIT_BEGIN_STMT \ |
1119 | RETURN_NULL_IF_FAIL (NUMERIC_TYPE, CTXT, NULL, "NULL type"); \ |
1120 | RETURN_NULL_IF_FAIL_PRINTF1 ( \ |
1121 | NUMERIC_TYPE->is_numeric (), ctxt, NULL, \ |
1122 | "not a numeric type: %s", \ |
1123 | NUMERIC_TYPE->get_debug_string ()); \ |
1124 | JIT_END_STMT |
1125 | |
1126 | /* Public entrypoint. See description in libgccjit.h. |
1127 | |
1128 | After error-checking, the real work is done by the |
1129 | gcc::jit::recording::context::new_rvalue_from_int method in |
1130 | jit-recording.c. */ |
1131 | |
1132 | gcc_jit_rvalue * |
1133 | gcc_jit_context_new_rvalue_from_int (gcc_jit_context *ctxt, |
1134 | gcc_jit_type *numeric_type, |
1135 | int value) |
1136 | { |
1137 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
1138 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1139 | RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type); |
1140 | |
1141 | return ((gcc_jit_rvalue *)ctxt |
1142 | ->new_rvalue_from_const <int> (numeric_type, value)); |
1143 | } |
1144 | |
1145 | /* FIXME. */ |
1146 | |
1147 | gcc_jit_rvalue * |
1148 | gcc_jit_context_new_rvalue_from_long (gcc_jit_context *ctxt, |
1149 | gcc_jit_type *numeric_type, |
1150 | long value) |
1151 | { |
1152 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
1153 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1154 | RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type); |
1155 | |
1156 | return ((gcc_jit_rvalue *)ctxt |
1157 | ->new_rvalue_from_const <long> (numeric_type, value)); |
1158 | } |
1159 | |
1160 | /* Public entrypoint. See description in libgccjit.h. |
1161 | |
1162 | This is essentially equivalent to: |
1163 | gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 0); |
1164 | albeit with slightly different error messages if an error occurs. */ |
1165 | |
1166 | gcc_jit_rvalue * |
1167 | gcc_jit_context_zero (gcc_jit_context *ctxt, |
1168 | gcc_jit_type *numeric_type) |
1169 | { |
1170 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
1171 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1172 | RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type); |
1173 | |
1174 | return gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 0); |
1175 | } |
1176 | |
1177 | /* Public entrypoint. See description in libgccjit.h. |
1178 | |
1179 | This is essentially equivalent to: |
1180 | gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 1); |
1181 | albeit with slightly different error messages if an error occurs. */ |
1182 | |
1183 | gcc_jit_rvalue * |
1184 | gcc_jit_context_one (gcc_jit_context *ctxt, |
1185 | gcc_jit_type *numeric_type) |
1186 | { |
1187 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
1188 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1189 | RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type); |
1190 | |
1191 | return gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 1); |
1192 | } |
1193 | |
1194 | /* Public entrypoint. See description in libgccjit.h. |
1195 | |
1196 | After error-checking, the real work is done by the |
1197 | gcc::jit::recording::context::new_rvalue_from_double method in |
1198 | jit-recording.c. */ |
1199 | |
1200 | gcc_jit_rvalue * |
1201 | gcc_jit_context_new_rvalue_from_double (gcc_jit_context *ctxt, |
1202 | gcc_jit_type *numeric_type, |
1203 | double value) |
1204 | { |
1205 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
1206 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1207 | RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type); |
1208 | |
1209 | return ((gcc_jit_rvalue *)ctxt |
1210 | ->new_rvalue_from_const <double> (numeric_type, value)); |
1211 | } |
1212 | |
1213 | /* Public entrypoint. See description in libgccjit.h. |
1214 | |
1215 | After error-checking, the real work is done by the |
1216 | gcc::jit::recording::context::new_rvalue_from_ptr method in |
1217 | jit-recording.c. */ |
1218 | |
1219 | gcc_jit_rvalue * |
1220 | gcc_jit_context_new_rvalue_from_ptr (gcc_jit_context *ctxt, |
1221 | gcc_jit_type *pointer_type, |
1222 | void *value) |
1223 | { |
1224 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
1225 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1226 | RETURN_NULL_IF_FAIL (pointer_type, ctxt, NULL, "NULL type"); |
1227 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
1228 | pointer_type->is_pointer (), |
1229 | ctxt, NULL, |
1230 | "not a pointer type (type: %s)", |
1231 | pointer_type->get_debug_string ()); |
1232 | |
1233 | return ((gcc_jit_rvalue *)ctxt |
1234 | ->new_rvalue_from_const <void *> (pointer_type, value)); |
1235 | } |
1236 | |
1237 | /* Public entrypoint. See description in libgccjit.h. |
1238 | |
1239 | This is essentially equivalent to: |
1240 | gcc_jit_context_new_rvalue_from_ptr (ctxt, pointer_type, NULL); |
1241 | albeit with slightly different error messages if an error occurs. */ |
1242 | |
1243 | gcc_jit_rvalue * |
1244 | gcc_jit_context_null (gcc_jit_context *ctxt, |
1245 | gcc_jit_type *pointer_type) |
1246 | { |
1247 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
1248 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1249 | RETURN_NULL_IF_FAIL (pointer_type, ctxt, NULL, "NULL type"); |
1250 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
1251 | pointer_type->is_pointer (), |
1252 | ctxt, NULL, |
1253 | "not a pointer type (type: %s)", |
1254 | pointer_type->get_debug_string ()); |
1255 | |
1256 | return gcc_jit_context_new_rvalue_from_ptr (ctxt, pointer_type, NULL); |
1257 | } |
1258 | |
1259 | /* Public entrypoint. See description in libgccjit.h. |
1260 | |
1261 | After error-checking, the real work is done by the |
1262 | gcc::jit::recording::context::new_string_literal method in |
1263 | jit-recording.c. */ |
1264 | |
1265 | gcc_jit_rvalue * |
1266 | gcc_jit_context_new_string_literal (gcc_jit_context *ctxt, |
1267 | const char *value) |
1268 | { |
1269 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
1270 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1271 | RETURN_NULL_IF_FAIL (value, ctxt, NULL, "NULL value"); |
1272 | |
1273 | return (gcc_jit_rvalue *)ctxt->new_string_literal (value); |
1274 | } |
1275 | |
1276 | /* Public entrypoint. See description in libgccjit.h. |
1277 | |
1278 | After error-checking, the real work is done by the |
1279 | gcc::jit::recording::context::new_unary_op method in |
1280 | jit-recording.c. */ |
1281 | |
1282 | gcc_jit_rvalue * |
1283 | gcc_jit_context_new_unary_op (gcc_jit_context *ctxt, |
1284 | gcc_jit_location *loc, |
1285 | enum gcc_jit_unary_op op, |
1286 | gcc_jit_type *result_type, |
1287 | gcc_jit_rvalue *rvalue) |
1288 | { |
1289 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
1290 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1291 | /* LOC can be NULL. */ |
1292 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
1293 | (op >= GCC_JIT_UNARY_OP_MINUS |
1294 | && op <= GCC_JIT_UNARY_OP_ABS), |
1295 | ctxt, loc, |
1296 | "unrecognized value for enum gcc_jit_unary_op: %i", |
1297 | op); |
1298 | RETURN_NULL_IF_FAIL (result_type, ctxt, loc, "NULL result_type"); |
1299 | RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); |
1300 | |
1301 | return (gcc_jit_rvalue *)ctxt->new_unary_op (loc, op, result_type, rvalue); |
1302 | } |
1303 | |
1304 | /* Determine if OP is a valid value for enum gcc_jit_binary_op. |
1305 | For use by both gcc_jit_context_new_binary_op and |
1306 | gcc_jit_block_add_assignment_op. */ |
1307 | |
1308 | static bool |
1309 | valid_binary_op_p (enum gcc_jit_binary_op op) |
1310 | { |
1311 | return (op >= GCC_JIT_BINARY_OP_PLUS |
1312 | && op <= GCC_JIT_BINARY_OP_RSHIFT); |
1313 | } |
1314 | |
1315 | /* Public entrypoint. See description in libgccjit.h. |
1316 | |
1317 | After error-checking, the real work is done by the |
1318 | gcc::jit::recording::context::new_binary_op method in |
1319 | jit-recording.c. */ |
1320 | |
1321 | gcc_jit_rvalue * |
1322 | gcc_jit_context_new_binary_op (gcc_jit_context *ctxt, |
1323 | gcc_jit_location *loc, |
1324 | enum gcc_jit_binary_op op, |
1325 | gcc_jit_type *result_type, |
1326 | gcc_jit_rvalue *a, gcc_jit_rvalue *b) |
1327 | { |
1328 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
1329 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1330 | /* LOC can be NULL. */ |
1331 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
1332 | valid_binary_op_p (op), |
1333 | ctxt, loc, |
1334 | "unrecognized value for enum gcc_jit_binary_op: %i", |
1335 | op); |
1336 | RETURN_NULL_IF_FAIL (result_type, ctxt, loc, "NULL result_type"); |
1337 | RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a"); |
1338 | RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b"); |
1339 | RETURN_NULL_IF_FAIL_PRINTF4 ( |
1340 | a->get_type ()->unqualified () == b->get_type ()->unqualified (), |
1341 | ctxt, loc, |
1342 | "mismatching types for binary op:" |
1343 | " a: %s (type: %s) b: %s (type: %s)", |
1344 | a->get_debug_string (), |
1345 | a->get_type ()->get_debug_string (), |
1346 | b->get_debug_string (), |
1347 | b->get_type ()->get_debug_string ()); |
1348 | |
1349 | return (gcc_jit_rvalue *)ctxt->new_binary_op (loc, op, result_type, a, b); |
1350 | } |
1351 | |
1352 | /* Public entrypoint. See description in libgccjit.h. |
1353 | |
1354 | After error-checking, the real work is done by the |
1355 | gcc::jit::recording::context::new_comparison method in |
1356 | jit-recording.c. */ |
1357 | |
1358 | gcc_jit_rvalue * |
1359 | gcc_jit_context_new_comparison (gcc_jit_context *ctxt, |
1360 | gcc_jit_location *loc, |
1361 | enum gcc_jit_comparison op, |
1362 | gcc_jit_rvalue *a, gcc_jit_rvalue *b) |
1363 | { |
1364 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
1365 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1366 | /* LOC can be NULL. */ |
1367 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
1368 | (op >= GCC_JIT_COMPARISON_EQ |
1369 | && op <= GCC_JIT_COMPARISON_GE), |
1370 | ctxt, loc, |
1371 | "unrecognized value for enum gcc_jit_comparison: %i", |
1372 | op); |
1373 | RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a"); |
1374 | RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b"); |
1375 | RETURN_NULL_IF_FAIL_PRINTF4 ( |
1376 | a->get_type ()->unqualified () == b->get_type ()->unqualified (), |
1377 | ctxt, loc, |
1378 | "mismatching types for comparison:" |
1379 | " a: %s (type: %s) b: %s (type: %s)", |
1380 | a->get_debug_string (), |
1381 | a->get_type ()->get_debug_string (), |
1382 | b->get_debug_string (), |
1383 | b->get_type ()->get_debug_string ()); |
1384 | |
1385 | return (gcc_jit_rvalue *)ctxt->new_comparison (loc, op, a, b); |
1386 | } |
1387 | |
1388 | /* Public entrypoint. See description in libgccjit.h. |
1389 | |
1390 | After error-checking, the real work is done by the |
1391 | gcc::jit::recording::context::new_call method in |
1392 | jit-recording.c. */ |
1393 | |
1394 | gcc_jit_rvalue * |
1395 | gcc_jit_context_new_call (gcc_jit_context *ctxt, |
1396 | gcc_jit_location *loc, |
1397 | gcc_jit_function *func, |
1398 | int numargs , gcc_jit_rvalue **args) |
1399 | { |
1400 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
1401 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1402 | /* LOC can be NULL. */ |
1403 | RETURN_NULL_IF_FAIL (func, ctxt, loc, "NULL function"); |
1404 | if (numargs) |
1405 | RETURN_NULL_IF_FAIL (args, ctxt, loc, "NULL args"); |
1406 | |
1407 | int min_num_params = func->get_params ().length (); |
1408 | bool is_variadic = func->is_variadic (); |
1409 | |
1410 | RETURN_NULL_IF_FAIL_PRINTF3 ( |
1411 | numargs >= min_num_params, |
1412 | ctxt, loc, |
1413 | "not enough arguments to function \"%s\"" |
1414 | " (got %i args, expected %i)", |
1415 | func->get_name ()->c_str (), |
1416 | numargs, min_num_params); |
1417 | |
1418 | RETURN_NULL_IF_FAIL_PRINTF3 ( |
1419 | (numargs == min_num_params || is_variadic), |
1420 | ctxt, loc, |
1421 | "too many arguments to function \"%s\"" |
1422 | " (got %i args, expected %i)", |
1423 | func->get_name ()->c_str (), |
1424 | numargs, min_num_params); |
1425 | |
1426 | for (int i = 0; i < min_num_params; i++) |
1427 | { |
1428 | gcc::jit::recording::param *param = func->get_param (i); |
1429 | gcc_jit_rvalue *arg = args[i]; |
1430 | |
1431 | RETURN_NULL_IF_FAIL_PRINTF4 ( |
1432 | arg, |
1433 | ctxt, loc, |
1434 | "NULL argument %i to function \"%s\":" |
1435 | " param %s (type: %s)", |
1436 | i + 1, |
1437 | func->get_name ()->c_str (), |
1438 | param->get_debug_string (), |
1439 | param->get_type ()->get_debug_string ()); |
1440 | |
1441 | RETURN_NULL_IF_FAIL_PRINTF6 ( |
1442 | compatible_types (param->get_type (), |
1443 | arg->get_type ()), |
1444 | ctxt, loc, |
1445 | "mismatching types for argument %d of function \"%s\":" |
1446 | " assignment to param %s (type: %s) from %s (type: %s)", |
1447 | i + 1, |
1448 | func->get_name ()->c_str (), |
1449 | param->get_debug_string (), |
1450 | param->get_type ()->get_debug_string (), |
1451 | arg->get_debug_string (), |
1452 | arg->get_type ()->get_debug_string ()); |
1453 | } |
1454 | |
1455 | return (gcc_jit_rvalue *)ctxt->new_call (loc, |
1456 | func, |
1457 | numargs, |
1458 | (gcc::jit::recording::rvalue **)args); |
1459 | } |
1460 | |
1461 | /* Public entrypoint. See description in libgccjit.h. |
1462 | |
1463 | After error-checking, the real work is done by the |
1464 | gcc::jit::recording::context::new_call_through_ptr method in |
1465 | jit-recording.c. */ |
1466 | |
1467 | gcc_jit_rvalue * |
1468 | gcc_jit_context_new_call_through_ptr (gcc_jit_context *ctxt, |
1469 | gcc_jit_location *loc, |
1470 | gcc_jit_rvalue *fn_ptr, |
1471 | int numargs, gcc_jit_rvalue **args) |
1472 | { |
1473 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
1474 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1475 | /* LOC can be NULL. */ |
1476 | RETURN_NULL_IF_FAIL (fn_ptr, ctxt, loc, "NULL fn_ptr"); |
1477 | if (numargs) |
1478 | RETURN_NULL_IF_FAIL (args, ctxt, loc, "NULL args"); |
1479 | |
1480 | gcc::jit::recording::type *ptr_type = fn_ptr->get_type ()->dereference (); |
1481 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
1482 | ptr_type, ctxt, loc, |
1483 | "fn_ptr is not a ptr: %s" |
1484 | " type: %s", |
1485 | fn_ptr->get_debug_string (), |
1486 | fn_ptr->get_type ()->get_debug_string ()); |
1487 | |
1488 | gcc::jit::recording::function_type *fn_type = |
1489 | ptr_type->dyn_cast_function_type(); |
1490 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
1491 | fn_type, ctxt, loc, |
1492 | "fn_ptr is not a function ptr: %s" |
1493 | " type: %s", |
1494 | fn_ptr->get_debug_string (), |
1495 | fn_ptr->get_type ()->get_debug_string ()); |
1496 | |
1497 | int min_num_params = fn_type->get_param_types ().length (); |
1498 | bool is_variadic = fn_type->is_variadic (); |
1499 | |
1500 | RETURN_NULL_IF_FAIL_PRINTF3 ( |
1501 | numargs >= min_num_params, |
1502 | ctxt, loc, |
1503 | "not enough arguments to fn_ptr: %s" |
1504 | " (got %i args, expected %i)", |
1505 | fn_ptr->get_debug_string (), |
1506 | numargs, min_num_params); |
1507 | |
1508 | RETURN_NULL_IF_FAIL_PRINTF3 ( |
1509 | (numargs == min_num_params || is_variadic), |
1510 | ctxt, loc, |
1511 | "too many arguments to fn_ptr: %s" |
1512 | " (got %i args, expected %i)", |
1513 | fn_ptr->get_debug_string (), |
1514 | numargs, min_num_params); |
1515 | |
1516 | for (int i = 0; i < min_num_params; i++) |
1517 | { |
1518 | gcc::jit::recording::type *param_type = fn_type->get_param_types ()[i]; |
1519 | gcc_jit_rvalue *arg = args[i]; |
1520 | |
1521 | RETURN_NULL_IF_FAIL_PRINTF3 ( |
1522 | arg, |
1523 | ctxt, loc, |
1524 | "NULL argument %i to fn_ptr: %s" |
1525 | " (type: %s)", |
1526 | i + 1, |
1527 | fn_ptr->get_debug_string (), |
1528 | param_type->get_debug_string ()); |
1529 | |
1530 | RETURN_NULL_IF_FAIL_PRINTF6 ( |
1531 | compatible_types (param_type, |
1532 | arg->get_type ()), |
1533 | ctxt, loc, |
1534 | "mismatching types for argument %d of fn_ptr: %s:" |
1535 | " assignment to param %d (type: %s) from %s (type: %s)", |
1536 | i + 1, |
1537 | fn_ptr->get_debug_string (), |
1538 | i + 1, |
1539 | param_type->get_debug_string (), |
1540 | arg->get_debug_string (), |
1541 | arg->get_type ()->get_debug_string ()); |
1542 | } |
1543 | |
1544 | return (gcc_jit_rvalue *)( |
1545 | ctxt->new_call_through_ptr (loc, |
1546 | fn_ptr, |
1547 | numargs, |
1548 | (gcc::jit::recording::rvalue **)args)); |
1549 | } |
1550 | |
1551 | /* Helper function for determining if we can cast an rvalue from SRC_TYPE |
1552 | to DST_TYPE, for use by gcc_jit_context_new_cast. |
1553 | |
1554 | We only permit these kinds of cast: |
1555 | |
1556 | int <-> float |
1557 | int <-> bool |
1558 | P* <-> Q* for pointer types P and Q. */ |
1559 | |
1560 | static bool |
1561 | is_valid_cast (gcc::jit::recording::type *src_type, |
1562 | gcc_jit_type *dst_type) |
1563 | { |
1564 | bool src_is_int = src_type->is_int (); |
1565 | bool dst_is_int = dst_type->is_int (); |
1566 | bool src_is_float = src_type->is_float (); |
1567 | bool dst_is_float = dst_type->is_float (); |
1568 | bool src_is_bool = src_type->is_bool (); |
1569 | bool dst_is_bool = dst_type->is_bool (); |
1570 | |
1571 | if (src_is_int) |
1572 | if (dst_is_int || dst_is_float || dst_is_bool) |
1573 | return true; |
1574 | |
1575 | if (src_is_float) |
1576 | if (dst_is_int || dst_is_float) |
1577 | return true; |
1578 | |
1579 | if (src_is_bool) |
1580 | if (dst_is_int || dst_is_bool) |
1581 | return true; |
1582 | |
1583 | /* Permit casts between pointer types. */ |
1584 | gcc::jit::recording::type *deref_src_type = src_type->is_pointer (); |
1585 | gcc::jit::recording::type *deref_dst_type = dst_type->is_pointer (); |
1586 | if (deref_src_type && deref_dst_type) |
1587 | return true; |
1588 | |
1589 | return false; |
1590 | } |
1591 | |
1592 | /* Public entrypoint. See description in libgccjit.h. |
1593 | |
1594 | After error-checking, the real work is done by the |
1595 | gcc::jit::recording::context::new_cast method in jit-recording.c. */ |
1596 | |
1597 | gcc_jit_rvalue * |
1598 | gcc_jit_context_new_cast (gcc_jit_context *ctxt, |
1599 | gcc_jit_location *loc, |
1600 | gcc_jit_rvalue *rvalue, |
1601 | gcc_jit_type *type) |
1602 | { |
1603 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
1604 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1605 | /* LOC can be NULL. */ |
1606 | RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); |
1607 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); |
1608 | RETURN_NULL_IF_FAIL_PRINTF3 ( |
1609 | is_valid_cast (rvalue->get_type (), type), |
1610 | ctxt, loc, |
1611 | "cannot cast %s from type: %s to type: %s", |
1612 | rvalue->get_debug_string (), |
1613 | rvalue->get_type ()->get_debug_string (), |
1614 | type->get_debug_string ()); |
1615 | |
1616 | return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc, rvalue, type)); |
1617 | } |
1618 | |
1619 | /* Public entrypoint. See description in libgccjit.h. |
1620 | |
1621 | After error-checking, the real work is done by the |
1622 | gcc::jit::recording::context::new_array_access method in |
1623 | jit-recording.c. */ |
1624 | |
1625 | extern gcc_jit_lvalue * |
1626 | gcc_jit_context_new_array_access (gcc_jit_context *ctxt, |
1627 | gcc_jit_location *loc, |
1628 | gcc_jit_rvalue *ptr, |
1629 | gcc_jit_rvalue *index) |
1630 | { |
1631 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); |
1632 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1633 | /* LOC can be NULL. */ |
1634 | RETURN_NULL_IF_FAIL (ptr, ctxt, loc, "NULL ptr"); |
1635 | RETURN_NULL_IF_FAIL (index, ctxt, loc, "NULL index"); |
1636 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
1637 | ptr->get_type ()->dereference (), |
1638 | ctxt, loc, |
1639 | "ptr: %s (type: %s) is not a pointer or array", |
1640 | ptr->get_debug_string (), |
1641 | ptr->get_type ()->get_debug_string ()); |
1642 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
1643 | index->get_type ()->is_numeric (), |
1644 | ctxt, loc, |
1645 | "index: %s (type: %s) is not of numeric type", |
1646 | index->get_debug_string (), |
1647 | index->get_type ()->get_debug_string ()); |
1648 | |
1649 | return (gcc_jit_lvalue *)ctxt->new_array_access (loc, ptr, index); |
1650 | } |
1651 | |
1652 | /* Public entrypoint. See description in libgccjit.h. |
1653 | |
1654 | After error-checking, the real work is done by the |
1655 | gcc::jit::recording::memento::get_context method in |
1656 | jit-recording.h. */ |
1657 | |
1658 | gcc_jit_context * |
1659 | gcc_jit_object_get_context (gcc_jit_object *obj) |
1660 | { |
1661 | RETURN_NULL_IF_FAIL (obj, NULL, NULL, "NULL object"); |
1662 | |
1663 | return static_cast <gcc_jit_context *> (obj->get_context ()); |
1664 | } |
1665 | |
1666 | /* Public entrypoint. See description in libgccjit.h. |
1667 | |
1668 | After error-checking, the real work is done by the |
1669 | gcc::jit::recording::memento::get_debug_string method in |
1670 | jit-recording.c. */ |
1671 | |
1672 | const char * |
1673 | gcc_jit_object_get_debug_string (gcc_jit_object *obj) |
1674 | { |
1675 | RETURN_NULL_IF_FAIL (obj, NULL, NULL, "NULL object"); |
1676 | |
1677 | return obj->get_debug_string (); |
1678 | } |
1679 | |
1680 | /* Public entrypoint. See description in libgccjit.h. |
1681 | |
1682 | After error-checking, the real work is done by the |
1683 | gcc::jit::recording::lvalue::access_field method in |
1684 | jit-recording.c. */ |
1685 | |
1686 | gcc_jit_lvalue * |
1687 | gcc_jit_lvalue_access_field (gcc_jit_lvalue *struct_, |
1688 | gcc_jit_location *loc, |
1689 | gcc_jit_field *field) |
1690 | { |
1691 | RETURN_NULL_IF_FAIL (struct_, NULL, loc, "NULL struct"); |
1692 | gcc::jit::recording::context *ctxt = struct_->m_ctxt; |
1693 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1694 | /* LOC can be NULL. */ |
1695 | RETURN_NULL_IF_FAIL (field, ctxt, loc, "NULL field"); |
1696 | RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt, loc, |
1697 | "field %s has not been placed in a struct", |
1698 | field->get_debug_string ()); |
1699 | gcc::jit::recording::type *underlying_type = |
1700 | struct_->get_type (); |
1701 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
1702 | (field->get_container ()->unqualified () |
1703 | == underlying_type->unqualified ()), |
1704 | struct_->m_ctxt, loc, |
1705 | "%s is not a field of %s", |
1706 | field->get_debug_string (), |
1707 | underlying_type->get_debug_string ()); |
1708 | |
1709 | return (gcc_jit_lvalue *)struct_->access_field (loc, field); |
1710 | } |
1711 | |
1712 | /* Public entrypoint. See description in libgccjit.h. |
1713 | |
1714 | After error-checking, the real work is done by the |
1715 | gcc::jit::recording::rvalue::access_field method in |
1716 | jit-recording.c. */ |
1717 | |
1718 | gcc_jit_rvalue * |
1719 | gcc_jit_rvalue_access_field (gcc_jit_rvalue *struct_, |
1720 | gcc_jit_location *loc, |
1721 | gcc_jit_field *field) |
1722 | { |
1723 | RETURN_NULL_IF_FAIL (struct_, NULL, loc, "NULL struct"); |
1724 | gcc::jit::recording::context *ctxt = struct_->m_ctxt; |
1725 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1726 | /* LOC can be NULL. */ |
1727 | RETURN_NULL_IF_FAIL (field, ctxt, loc, "NULL field"); |
1728 | RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt, loc, |
1729 | "field %s has not been placed in a struct", |
1730 | field->get_debug_string ()); |
1731 | gcc::jit::recording::type *underlying_type = |
1732 | struct_->get_type (); |
1733 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
1734 | (field->get_container ()->unqualified () |
1735 | == underlying_type->unqualified ()), |
1736 | struct_->m_ctxt, loc, |
1737 | "%s is not a field of %s", |
1738 | field->get_debug_string (), |
1739 | underlying_type->get_debug_string ()); |
1740 | |
1741 | return (gcc_jit_rvalue *)struct_->access_field (loc, field); |
1742 | } |
1743 | |
1744 | /* Public entrypoint. See description in libgccjit.h. |
1745 | |
1746 | After error-checking, the real work is done by the |
1747 | gcc::jit::recording::rvalue::deference_field method in |
1748 | jit-recording.c. */ |
1749 | |
1750 | gcc_jit_lvalue * |
1751 | gcc_jit_rvalue_dereference_field (gcc_jit_rvalue *ptr, |
1752 | gcc_jit_location *loc, |
1753 | gcc_jit_field *field) |
1754 | { |
1755 | RETURN_NULL_IF_FAIL (ptr, NULL, loc, "NULL ptr"); |
1756 | JIT_LOG_FUNC (ptr->get_context ()->get_logger ()); |
1757 | /* LOC can be NULL. */ |
1758 | RETURN_NULL_IF_FAIL (field, NULL, loc, "NULL field"); |
1759 | gcc::jit::recording::type *underlying_type = |
1760 | ptr->get_type ()->is_pointer (); |
1761 | RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt, loc, |
1762 | "field %s has not been placed in a struct", |
1763 | field->get_debug_string ()); |
1764 | RETURN_NULL_IF_FAIL_PRINTF3 ( |
1765 | underlying_type, |
1766 | ptr->m_ctxt, loc, |
1767 | "dereference of non-pointer %s (type: %s) when accessing ->%s", |
1768 | ptr->get_debug_string (), |
1769 | ptr->get_type ()->get_debug_string (), |
1770 | field->get_debug_string ()); |
1771 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
1772 | (field->get_container ()->unqualified () |
1773 | == underlying_type->unqualified ()), |
1774 | ptr->m_ctxt, loc, |
1775 | "%s is not a field of %s", |
1776 | field->get_debug_string (), |
1777 | underlying_type->get_debug_string ()); |
1778 | |
1779 | return (gcc_jit_lvalue *)ptr->dereference_field (loc, field); |
1780 | } |
1781 | |
1782 | /* Public entrypoint. See description in libgccjit.h. |
1783 | |
1784 | After error-checking, the real work is done by the |
1785 | gcc::jit::recording::rvalue::deference method in |
1786 | jit-recording.c. */ |
1787 | |
1788 | gcc_jit_lvalue * |
1789 | gcc_jit_rvalue_dereference (gcc_jit_rvalue *rvalue, |
1790 | gcc_jit_location *loc) |
1791 | { |
1792 | RETURN_NULL_IF_FAIL (rvalue, NULL, loc, "NULL rvalue"); |
1793 | JIT_LOG_FUNC (rvalue->get_context ()->get_logger ()); |
1794 | /* LOC can be NULL. */ |
1795 | |
1796 | gcc::jit::recording::type *underlying_type = |
1797 | rvalue->get_type ()->is_pointer (); |
1798 | |
1799 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
1800 | underlying_type, |
1801 | rvalue->m_ctxt, loc, |
1802 | "dereference of non-pointer %s (type: %s)", |
1803 | rvalue->get_debug_string (), |
1804 | rvalue->get_type ()->get_debug_string ()); |
1805 | |
1806 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
1807 | !underlying_type->is_void (), |
1808 | rvalue->m_ctxt, loc, |
1809 | "dereference of void pointer %s (type: %s)", |
1810 | rvalue->get_debug_string (), |
1811 | rvalue->get_type ()->get_debug_string ()); |
1812 | |
1813 | return (gcc_jit_lvalue *)rvalue->dereference (loc); |
1814 | } |
1815 | |
1816 | /* Public entrypoint. See description in libgccjit.h. |
1817 | |
1818 | After error-checking, the real work is done by the |
1819 | gcc::jit::recording::lvalue::get_address method in jit-recording.c. */ |
1820 | |
1821 | gcc_jit_rvalue * |
1822 | gcc_jit_lvalue_get_address (gcc_jit_lvalue *lvalue, |
1823 | gcc_jit_location *loc) |
1824 | { |
1825 | RETURN_NULL_IF_FAIL (lvalue, NULL, loc, "NULL lvalue"); |
1826 | JIT_LOG_FUNC (lvalue->get_context ()->get_logger ()); |
1827 | /* LOC can be NULL. */ |
1828 | |
1829 | return (gcc_jit_rvalue *)lvalue->get_address (loc); |
1830 | } |
1831 | |
1832 | /* Public entrypoint. See description in libgccjit.h. |
1833 | |
1834 | After error-checking, the real work is done by the |
1835 | gcc::jit::recording::function::new_local method in jit-recording.c. */ |
1836 | |
1837 | gcc_jit_lvalue * |
1838 | gcc_jit_function_new_local (gcc_jit_function *func, |
1839 | gcc_jit_location *loc, |
1840 | gcc_jit_type *type, |
1841 | const char *name) |
1842 | { |
1843 | RETURN_NULL_IF_FAIL (func, NULL, loc, "NULL function"); |
1844 | gcc::jit::recording::context *ctxt = func->m_ctxt; |
1845 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1846 | /* LOC can be NULL. */ |
1847 | RETURN_NULL_IF_FAIL (func->get_kind () != GCC_JIT_FUNCTION_IMPORTED, |
1848 | ctxt, loc, |
1849 | "Cannot add locals to an imported function"); |
1850 | RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); |
1851 | RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); |
1852 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
1853 | type->has_known_size (), |
1854 | ctxt, loc, |
1855 | "unknown size for local \"%s\" (type: %s)", |
1856 | name, |
1857 | type->get_debug_string ()); |
1858 | |
1859 | return (gcc_jit_lvalue *)func->new_local (loc, type, name); |
1860 | } |
1861 | |
1862 | /* Public entrypoint. See description in libgccjit.h. |
1863 | |
1864 | After error-checking, the real work is done by the |
1865 | gcc::jit::recording::block::add_eval method in jit-recording.c. */ |
1866 | |
1867 | void |
1868 | gcc_jit_block_add_eval (gcc_jit_block *block, |
1869 | gcc_jit_location *loc, |
1870 | gcc_jit_rvalue *rvalue) |
1871 | { |
1872 | RETURN_IF_NOT_VALID_BLOCK (block, loc); |
1873 | gcc::jit::recording::context *ctxt = block->get_context (); |
1874 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1875 | /* LOC can be NULL. */ |
1876 | RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); |
1877 | |
1878 | gcc::jit::recording::statement *stmt = block->add_eval (loc, rvalue); |
1879 | |
1880 | /* "stmt" should be good enough to be usable in error-messages, |
1881 | but might still not be compilable; perform some more |
1882 | error-checking here. We do this here so that the error messages |
1883 | can contain a stringified version of "stmt", whilst appearing |
1884 | as close as possible to the point of failure. */ |
1885 | rvalue->verify_valid_within_stmt (__func__, stmt); |
1886 | } |
1887 | |
1888 | /* Public entrypoint. See description in libgccjit.h. |
1889 | |
1890 | After error-checking, the real work is done by the |
1891 | gcc::jit::recording::block::add_assignment method in |
1892 | jit-recording.c. */ |
1893 | |
1894 | void |
1895 | gcc_jit_block_add_assignment (gcc_jit_block *block, |
1896 | gcc_jit_location *loc, |
1897 | gcc_jit_lvalue *lvalue, |
1898 | gcc_jit_rvalue *rvalue) |
1899 | { |
1900 | RETURN_IF_NOT_VALID_BLOCK (block, loc); |
1901 | gcc::jit::recording::context *ctxt = block->get_context (); |
1902 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1903 | /* LOC can be NULL. */ |
1904 | RETURN_IF_FAIL (lvalue, ctxt, loc, "NULL lvalue"); |
1905 | RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); |
1906 | RETURN_IF_FAIL_PRINTF4 ( |
1907 | compatible_types (lvalue->get_type (), |
1908 | rvalue->get_type ()), |
1909 | ctxt, loc, |
1910 | "mismatching types:" |
1911 | " assignment to %s (type: %s) from %s (type: %s)", |
1912 | lvalue->get_debug_string (), |
1913 | lvalue->get_type ()->get_debug_string (), |
1914 | rvalue->get_debug_string (), |
1915 | rvalue->get_type ()->get_debug_string ()); |
1916 | |
1917 | gcc::jit::recording::statement *stmt = block->add_assignment (loc, lvalue, rvalue); |
1918 | |
1919 | /* "stmt" should be good enough to be usable in error-messages, |
1920 | but might still not be compilable; perform some more |
1921 | error-checking here. We do this here so that the error messages |
1922 | can contain a stringified version of "stmt", whilst appearing |
1923 | as close as possible to the point of failure. */ |
1924 | lvalue->verify_valid_within_stmt (__func__, stmt); |
1925 | rvalue->verify_valid_within_stmt (__func__, stmt); |
1926 | } |
1927 | |
1928 | /* Public entrypoint. See description in libgccjit.h. |
1929 | |
1930 | After error-checking, the real work is done by the |
1931 | gcc::jit::recording::block::add_assignment_op method in |
1932 | jit-recording.c. */ |
1933 | |
1934 | void |
1935 | gcc_jit_block_add_assignment_op (gcc_jit_block *block, |
1936 | gcc_jit_location *loc, |
1937 | gcc_jit_lvalue *lvalue, |
1938 | enum gcc_jit_binary_op op, |
1939 | gcc_jit_rvalue *rvalue) |
1940 | { |
1941 | RETURN_IF_NOT_VALID_BLOCK (block, loc); |
1942 | gcc::jit::recording::context *ctxt = block->get_context (); |
1943 | JIT_LOG_FUNC (ctxt->get_logger ()); |
1944 | /* LOC can be NULL. */ |
1945 | RETURN_IF_FAIL (lvalue, ctxt, loc, "NULL lvalue"); |
1946 | RETURN_IF_FAIL_PRINTF1 ( |
1947 | valid_binary_op_p (op), |
1948 | ctxt, loc, |
1949 | "unrecognized value for enum gcc_jit_binary_op: %i", |
1950 | op); |
1951 | RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); |
1952 | RETURN_IF_FAIL_PRINTF4 ( |
1953 | compatible_types (lvalue->get_type (), |
1954 | rvalue->get_type ()), |
1955 | ctxt, loc, |
1956 | "mismatching types:" |
1957 | " assignment to %s (type: %s) involving %s (type: %s)", |
1958 | lvalue->get_debug_string (), |
1959 | lvalue->get_type ()->get_debug_string (), |
1960 | rvalue->get_debug_string (), |
1961 | rvalue->get_type ()->get_debug_string ()); |
1962 | |
1963 | gcc::jit::recording::statement *stmt = block->add_assignment_op (loc, lvalue, op, rvalue); |
1964 | |
1965 | /* "stmt" should be good enough to be usable in error-messages, |
1966 | but might still not be compilable; perform some more |
1967 | error-checking here. We do this here so that the error messages |
1968 | can contain a stringified version of "stmt", whilst appearing |
1969 | as close as possible to the point of failure. */ |
1970 | lvalue->verify_valid_within_stmt (__func__, stmt); |
1971 | rvalue->verify_valid_within_stmt (__func__, stmt); |
1972 | } |
1973 | |
1974 | /* Internal helper function for determining if rvalue BOOLVAL is of |
1975 | boolean type. For use by gcc_jit_block_end_with_conditional. */ |
1976 | |
1977 | static bool |
1978 | is_bool (gcc_jit_rvalue *boolval) |
1979 | { |
1980 | gcc::jit::recording::type *actual_type = boolval->get_type (); |
1981 | gcc::jit::recording::type *bool_type = |
1982 | boolval->m_ctxt->get_type (GCC_JIT_TYPE_BOOL); |
1983 | return actual_type == bool_type; |
1984 | } |
1985 | |
1986 | /* Public entrypoint. See description in libgccjit.h. |
1987 | |
1988 | After error-checking, the real work is done by the |
1989 | gcc::jit::recording::block::end_with_conditional method in |
1990 | jit-recording.c. */ |
1991 | |
1992 | void |
1993 | gcc_jit_block_end_with_conditional (gcc_jit_block *block, |
1994 | gcc_jit_location *loc, |
1995 | gcc_jit_rvalue *boolval, |
1996 | gcc_jit_block *on_true, |
1997 | gcc_jit_block *on_false) |
1998 | { |
1999 | RETURN_IF_NOT_VALID_BLOCK (block, loc); |
2000 | gcc::jit::recording::context *ctxt = block->get_context (); |
2001 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2002 | /* LOC can be NULL. */ |
2003 | RETURN_IF_FAIL (boolval, ctxt, loc, "NULL boolval"); |
2004 | RETURN_IF_FAIL_PRINTF2 ( |
2005 | is_bool (boolval), ctxt, loc, |
2006 | "%s (type: %s) is not of boolean type ", |
2007 | boolval->get_debug_string (), |
2008 | boolval->get_type ()->get_debug_string ()); |
2009 | RETURN_IF_FAIL (on_true, ctxt, loc, "NULL on_true"); |
2010 | RETURN_IF_FAIL (on_true, ctxt, loc, "NULL on_false"); |
2011 | RETURN_IF_FAIL_PRINTF4 ( |
2012 | block->get_function () == on_true->get_function (), |
2013 | ctxt, loc, |
2014 | "\"on_true\" block is not in same function:" |
2015 | " source block %s is in function %s" |
2016 | " whereas target block %s is in function %s", |
2017 | block->get_debug_string (), |
2018 | block->get_function ()->get_debug_string (), |
2019 | on_true->get_debug_string (), |
2020 | on_true->get_function ()->get_debug_string ()); |
2021 | RETURN_IF_FAIL_PRINTF4 ( |
2022 | block->get_function () == on_false->get_function (), |
2023 | ctxt, loc, |
2024 | "\"on_false\" block is not in same function:" |
2025 | " source block %s is in function %s" |
2026 | " whereas target block %s is in function %s", |
2027 | block->get_debug_string (), |
2028 | block->get_function ()->get_debug_string (), |
2029 | on_false->get_debug_string (), |
2030 | on_false->get_function ()->get_debug_string ()); |
2031 | |
2032 | gcc::jit::recording::statement *stmt = block->end_with_conditional (loc, boolval, on_true, on_false); |
2033 | |
2034 | /* "stmt" should be good enough to be usable in error-messages, |
2035 | but might still not be compilable; perform some more |
2036 | error-checking here. We do this here so that the error messages |
2037 | can contain a stringified version of "stmt", whilst appearing |
2038 | as close as possible to the point of failure. */ |
2039 | boolval->verify_valid_within_stmt (__func__, stmt); |
2040 | } |
2041 | |
2042 | /* Public entrypoint. See description in libgccjit.h. |
2043 | |
2044 | After error-checking, the real work is done by the |
2045 | gcc::jit::recording::block::add_comment method in |
2046 | jit-recording.c. */ |
2047 | |
2048 | void |
2049 | gcc_jit_block_add_comment (gcc_jit_block *block, |
2050 | gcc_jit_location *loc, |
2051 | const char *text) |
2052 | { |
2053 | RETURN_IF_NOT_VALID_BLOCK (block, loc); |
2054 | gcc::jit::recording::context *ctxt = block->get_context (); |
2055 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2056 | /* LOC can be NULL. */ |
2057 | RETURN_IF_FAIL (text, ctxt, loc, "NULL text"); |
2058 | |
2059 | block->add_comment (loc, text); |
2060 | } |
2061 | |
2062 | /* Public entrypoint. See description in libgccjit.h. |
2063 | |
2064 | After error-checking, the real work is done by the |
2065 | gcc::jit::recording::block::end_with_jump method in |
2066 | jit-recording.c. */ |
2067 | |
2068 | void |
2069 | gcc_jit_block_end_with_jump (gcc_jit_block *block, |
2070 | gcc_jit_location *loc, |
2071 | gcc_jit_block *target) |
2072 | { |
2073 | RETURN_IF_NOT_VALID_BLOCK (block, loc); |
2074 | gcc::jit::recording::context *ctxt = block->get_context (); |
2075 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2076 | /* LOC can be NULL. */ |
2077 | RETURN_IF_FAIL (target, ctxt, loc, "NULL target"); |
2078 | RETURN_IF_FAIL_PRINTF4 ( |
2079 | block->get_function () == target->get_function (), |
2080 | ctxt, loc, |
2081 | "target block is not in same function:" |
2082 | " source block %s is in function %s" |
2083 | " whereas target block %s is in function %s", |
2084 | block->get_debug_string (), |
2085 | block->get_function ()->get_debug_string (), |
2086 | target->get_debug_string (), |
2087 | target->get_function ()->get_debug_string ()); |
2088 | |
2089 | block->end_with_jump (loc, target); |
2090 | } |
2091 | |
2092 | /* Public entrypoint. See description in libgccjit.h. |
2093 | |
2094 | After error-checking, the real work is done by the |
2095 | gcc::jit::recording::block::end_with_return method in |
2096 | jit-recording.c. */ |
2097 | |
2098 | void |
2099 | gcc_jit_block_end_with_return (gcc_jit_block *block, |
2100 | gcc_jit_location *loc, |
2101 | gcc_jit_rvalue *rvalue) |
2102 | { |
2103 | RETURN_IF_NOT_VALID_BLOCK (block, loc); |
2104 | gcc::jit::recording::context *ctxt = block->get_context (); |
2105 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2106 | /* LOC can be NULL. */ |
2107 | gcc::jit::recording::function *func = block->get_function (); |
2108 | RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); |
2109 | RETURN_IF_FAIL_PRINTF4 ( |
2110 | compatible_types ( |
2111 | func->get_return_type (), |
2112 | rvalue->get_type ()), |
2113 | ctxt, loc, |
2114 | "mismatching types:" |
2115 | " return of %s (type: %s) in function %s (return type: %s)", |
2116 | rvalue->get_debug_string (), |
2117 | rvalue->get_type ()->get_debug_string (), |
2118 | func->get_debug_string (), |
2119 | func->get_return_type ()->get_debug_string ()); |
2120 | |
2121 | gcc::jit::recording::statement *stmt = block->end_with_return (loc, rvalue); |
2122 | |
2123 | /* "stmt" should be good enough to be usable in error-messages, |
2124 | but might still not be compilable; perform some more |
2125 | error-checking here. We do this here so that the error messages |
2126 | can contain a stringified version of "stmt", whilst appearing |
2127 | as close as possible to the point of failure. */ |
2128 | rvalue->verify_valid_within_stmt (__func__, stmt); |
2129 | } |
2130 | |
2131 | /* Public entrypoint. See description in libgccjit.h. |
2132 | |
2133 | After error-checking, the real work is done by the |
2134 | gcc::jit::recording::block::end_with_return method in |
2135 | jit-recording.c. */ |
2136 | |
2137 | void |
2138 | gcc_jit_block_end_with_void_return (gcc_jit_block *block, |
2139 | gcc_jit_location *loc) |
2140 | { |
2141 | RETURN_IF_NOT_VALID_BLOCK (block, loc); |
2142 | gcc::jit::recording::context *ctxt = block->get_context (); |
2143 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2144 | /* LOC can be NULL. */ |
2145 | gcc::jit::recording::function *func = block->get_function (); |
2146 | RETURN_IF_FAIL_PRINTF2 ( |
2147 | func->get_return_type () == ctxt->get_type (GCC_JIT_TYPE_VOID), |
2148 | ctxt, loc, |
2149 | "mismatching types:" |
2150 | " void return in function %s (return type: %s)", |
2151 | func->get_debug_string (), |
2152 | func->get_return_type ()->get_debug_string ()); |
2153 | |
2154 | block->end_with_return (loc, NULL); |
2155 | } |
2156 | |
2157 | /* Public entrypoint. See description in libgccjit.h. |
2158 | |
2159 | After error-checking, the real work is done by the |
2160 | gcc::jit::recording::context::new_case method in |
2161 | jit-recording.c. */ |
2162 | |
2163 | gcc_jit_case * |
2164 | gcc_jit_context_new_case (gcc_jit_context *ctxt, |
2165 | gcc_jit_rvalue *min_value, |
2166 | gcc_jit_rvalue *max_value, |
2167 | gcc_jit_block *block) |
2168 | { |
2169 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2170 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2171 | RETURN_NULL_IF_FAIL (min_value, ctxt, NULL, "NULL min_value"); |
2172 | RETURN_NULL_IF_FAIL (max_value, ctxt, NULL, "NULL max_value"); |
2173 | RETURN_NULL_IF_FAIL (block, ctxt, NULL, "NULL block"); |
2174 | |
2175 | RETURN_NULL_IF_FAIL_PRINTF1 (min_value->is_constant (), ctxt, NULL, |
2176 | "min_value is not a constant: %s", |
2177 | min_value->get_debug_string ()); |
2178 | RETURN_NULL_IF_FAIL_PRINTF1 (max_value->is_constant (), ctxt, NULL, |
2179 | "max_value is not a constant: %s", |
2180 | max_value->get_debug_string ()); |
2181 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
2182 | min_value->get_type ()->is_int (), |
2183 | ctxt, NULL, |
2184 | "min_value: %s (type: %s) is not of integer type", |
2185 | min_value->get_debug_string (), |
2186 | min_value->get_type ()->get_debug_string ()); |
2187 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
2188 | max_value->get_type ()->is_int (), |
2189 | ctxt, NULL, |
2190 | "max_value: %s (type: %s) is not of integer type", |
2191 | max_value->get_debug_string (), |
2192 | max_value->get_type ()->get_debug_string ()); |
2193 | |
2194 | wide_int wi_min, wi_max; |
2195 | if (!min_value->get_wide_int (&wi_min)) |
2196 | gcc_unreachable (); |
2197 | if (!max_value->get_wide_int (&wi_max)) |
2198 | gcc_unreachable (); |
2199 | RETURN_NULL_IF_FAIL_PRINTF2 ( |
2200 | wi::les_p (wi_min, wi_max), |
2201 | ctxt, NULL, |
2202 | "min_value: %s > max_value: %s", |
2203 | min_value->get_debug_string (), |
2204 | max_value->get_debug_string ()); |
2205 | return (gcc_jit_case *)ctxt->new_case (min_value, |
2206 | max_value, |
2207 | block); |
2208 | } |
2209 | |
2210 | /* Public entrypoint. See description in libgccjit.h. |
2211 | |
2212 | After error-checking, this calls the trivial |
2213 | gcc::jit::recording::memento::as_object method (a case is a |
2214 | memento), in jit-recording.h. */ |
2215 | |
2216 | gcc_jit_object * |
2217 | gcc_jit_case_as_object (gcc_jit_case *case_) |
2218 | { |
2219 | RETURN_NULL_IF_FAIL (case_, NULL, NULL, "NULL case"); |
2220 | |
2221 | return static_cast <gcc_jit_object *> (case_->as_object ()); |
2222 | } |
2223 | |
2224 | /* Helper function for gcc_jit_block_end_with_switch and |
2225 | valid_case_for_switch. */ |
2226 | |
2227 | static bool |
2228 | valid_dest_for_switch (gcc::jit::recording::context *ctxt, |
2229 | gcc_jit_location *loc, |
2230 | const char *api_funcname, |
2231 | gcc::jit::recording::block *switch_block, |
2232 | gcc::jit::recording::block *dest_block, |
2233 | const char *dest_block_desc) |
2234 | { |
2235 | if (!dest_block) |
2236 | { |
2237 | jit_error (ctxt, loc, "%s: NULL %s", api_funcname, dest_block_desc); |
2238 | return false; |
2239 | } |
2240 | gcc::jit::recording::function *switch_fn = switch_block->get_function (); |
2241 | gcc::jit::recording::function *dest_fn = dest_block->get_function (); |
2242 | if (switch_fn != dest_fn) |
2243 | { |
2244 | jit_error (ctxt, loc, |
2245 | "%s: %s is not in same function:" |
2246 | " switch block %s is in function %s" |
2247 | " whereas %s %s is in function %s", |
2248 | api_funcname, |
2249 | dest_block_desc, |
2250 | switch_block->get_debug_string (), |
2251 | switch_fn->get_debug_string (), |
2252 | dest_block_desc, |
2253 | dest_block->get_debug_string (), |
2254 | dest_fn->get_debug_string ()); |
2255 | return false; |
2256 | } |
2257 | return true; |
2258 | } |
2259 | |
2260 | /* Helper function for gcc_jit_block_end_with_switch. */ |
2261 | |
2262 | static bool |
2263 | valid_case_for_switch (gcc::jit::recording::context *ctxt, |
2264 | gcc_jit_location *loc, |
2265 | const char *api_funcname, |
2266 | gcc_jit_block *switch_block, |
2267 | gcc_jit_rvalue *expr, |
2268 | gcc_jit_case *case_, |
2269 | const char *case_desc, |
2270 | int case_idx) |
2271 | { |
2272 | if (!case_) |
2273 | { |
2274 | jit_error (ctxt, loc, |
2275 | "%s:" |
2276 | " NULL case %i", |
2277 | api_funcname, |
2278 | case_idx); |
2279 | return false; |
2280 | } |
2281 | if (!valid_dest_for_switch (ctxt, loc, |
2282 | api_funcname, |
2283 | switch_block, |
2284 | case_->get_dest_block (), |
2285 | case_desc)) |
2286 | return false; |
2287 | gcc::jit::recording::type *expr_type = expr->get_type (); |
2288 | if (expr_type != case_->get_min_value ()->get_type ()) |
2289 | { |
2290 | jit_error (ctxt, loc, |
2291 | "%s:" |
2292 | " mismatching types between case and expression:" |
2293 | " cases[%i]->min_value: %s (type: %s)" |
2294 | " expr: %s (type: %s)", |
2295 | api_funcname, |
2296 | case_idx, |
2297 | case_->get_min_value ()->get_debug_string (), |
2298 | case_->get_min_value ()->get_type ()->get_debug_string (), |
2299 | expr->get_debug_string (), |
2300 | expr_type->get_debug_string ()); |
2301 | return false; |
2302 | } |
2303 | if (expr_type != case_->get_max_value ()->get_type ()) |
2304 | { |
2305 | jit_error (ctxt, loc, |
2306 | "%s:" |
2307 | " mismatching types between case and expression:" |
2308 | " cases[%i]->max_value: %s (type: %s)" |
2309 | " expr: %s (type: %s)", |
2310 | api_funcname, |
2311 | case_idx, |
2312 | case_->get_max_value ()->get_debug_string (), |
2313 | case_->get_max_value ()->get_type ()->get_debug_string (), |
2314 | expr->get_debug_string (), |
2315 | expr_type->get_debug_string ()); |
2316 | return false; |
2317 | } |
2318 | return true; |
2319 | } |
2320 | |
2321 | /* A class for holding the data we need to perform error-checking |
2322 | on a libgccjit API call. */ |
2323 | |
2324 | class api_call_validator |
2325 | { |
2326 | public: |
2327 | api_call_validator (gcc::jit::recording::context *ctxt, |
2328 | gcc_jit_location *loc, |
2329 | const char *funcname) |
2330 | : m_ctxt (ctxt), |
2331 | m_loc (loc), |
2332 | m_funcname (funcname) |
2333 | {} |
2334 | |
2335 | protected: |
2336 | gcc::jit::recording::context *m_ctxt; |
2337 | gcc_jit_location *m_loc; |
2338 | const char *m_funcname; |
2339 | }; |
2340 | |
2341 | /* A class for verifying that the ranges of cases within |
2342 | gcc_jit_block_end_with_switch don't overlap. */ |
2343 | |
2344 | class case_range_validator : public api_call_validator |
2345 | { |
2346 | public: |
2347 | case_range_validator (gcc::jit::recording::context *ctxt, |
2348 | gcc_jit_location *loc, |
2349 | const char *funcname); |
2350 | |
2351 | bool |
2352 | validate (gcc_jit_case *case_, int idx); |
2353 | |
2354 | private: |
2355 | static int |
2356 | case_compare (gcc::jit::recording::rvalue *k1, |
2357 | gcc::jit::recording::rvalue *k2); |
2358 | |
2359 | static wide_int |
2360 | get_wide_int (gcc::jit::recording::rvalue *k); |
2361 | |
2362 | private: |
2363 | typed_splay_tree <gcc::jit::recording::rvalue *, gcc_jit_case *> m_cases; |
2364 | }; |
2365 | |
2366 | /* case_range_validator's ctor. */ |
2367 | |
2368 | case_range_validator::case_range_validator (gcc::jit::recording::context *ctxt, |
2369 | gcc_jit_location *loc, |
2370 | const char *funcname) |
2371 | : api_call_validator (ctxt, loc, funcname), |
2372 | m_cases (case_compare, NULL, NULL) |
2373 | { |
2374 | } |
2375 | |
2376 | /* Ensure that the range of CASE_ does not overlap with any of the |
2377 | ranges of cases we've already seen. |
2378 | Return true if everything is OK. |
2379 | Return false and emit an error if there is an overlap. |
2380 | Compare with c-family/c-common.c:c_add_case_label. */ |
2381 | |
2382 | bool |
2383 | case_range_validator::validate (gcc_jit_case *case_, |
2384 | int case_idx) |
2385 | { |
2386 | /* Look up the LOW_VALUE in the table of case labels we already |
2387 | have. */ |
2388 | gcc_jit_case *other = m_cases.lookup (case_->get_min_value ()); |
2389 | |
2390 | /* If there was not an exact match, check for overlapping ranges. */ |
2391 | if (!other) |
2392 | { |
2393 | gcc_jit_case *pred; |
2394 | gcc_jit_case *succ; |
2395 | |
2396 | /* Even though there wasn't an exact match, there might be an |
2397 | overlap between this case range and another case range. |
2398 | Since we've (inductively) not allowed any overlapping case |
2399 | ranges, we simply need to find the greatest low case label |
2400 | that is smaller that CASE_MIN_VALUE, and the smallest low case |
2401 | label that is greater than CASE_MAX_VALUE. If there is an overlap |
2402 | it will occur in one of these two ranges. */ |
2403 | pred = m_cases.predecessor (case_->get_min_value ()); |
2404 | succ = m_cases.successor (case_->get_max_value ()); |
2405 | |
2406 | /* Check to see if the PRED overlaps. It is smaller than |
2407 | the LOW_VALUE, so we only need to check its max value. */ |
2408 | if (pred) |
2409 | { |
2410 | wide_int wi_case_min = get_wide_int (case_->get_min_value ()); |
2411 | wide_int wi_pred_max = get_wide_int (pred->get_max_value ()); |
2412 | if (wi::ges_p (wi_pred_max, wi_case_min)) |
2413 | other = pred; |
2414 | } |
2415 | |
2416 | if (!other && succ) |
2417 | { |
2418 | /* Check to see if the SUCC overlaps. The low end of that |
2419 | range is bigger than the low end of the current range. */ |
2420 | wide_int wi_case_max = get_wide_int (case_->get_max_value ()); |
2421 | wide_int wi_succ_min = get_wide_int (succ->get_min_value ()); |
2422 | if (wi::les_p (wi_succ_min, wi_case_max)) |
2423 | other = succ; |
2424 | } |
2425 | } |
2426 | |
2427 | /* If there was an overlap, issue an error. */ |
2428 | if (other) |
2429 | { |
2430 | jit_error (m_ctxt, m_loc, |
2431 | "%s: duplicate (or overlapping) cases values:" |
2432 | " case %i: %s overlaps %s", |
2433 | m_funcname, |
2434 | case_idx, |
2435 | case_->get_debug_string (), |
2436 | other->get_debug_string ()); |
2437 | return false; |
2438 | } |
2439 | |
2440 | /* Register this case label in the splay tree. */ |
2441 | m_cases.insert (case_->get_min_value (), |
2442 | case_); |
2443 | return true; |
2444 | } |
2445 | |
2446 | /* Compare with c-family/c-common.c:case_compare, which acts on tree |
2447 | nodes, rather than rvalue *. |
2448 | |
2449 | Comparator for case label values. K1 and K2 must be constant integer |
2450 | values (anything else should have been rejected by |
2451 | gcc_jit_context_new_case. |
2452 | |
2453 | Returns -1 if K1 is ordered before K2, -1 if K1 is ordered after |
2454 | K2, and 0 if K1 and K2 are equal. */ |
2455 | |
2456 | int |
2457 | case_range_validator::case_compare (gcc::jit::recording::rvalue * k1, |
2458 | gcc::jit::recording::rvalue * k2) |
2459 | { |
2460 | wide_int wi1 = get_wide_int (k1); |
2461 | wide_int wi2 = get_wide_int (k2); |
2462 | return wi::cmps(wi1, wi2); |
2463 | } |
2464 | |
2465 | /* Given a const int rvalue K, get the underlying value as a wide_int. */ |
2466 | |
2467 | wide_int |
2468 | case_range_validator::get_wide_int (gcc::jit::recording::rvalue *k) |
2469 | { |
2470 | wide_int wi; |
2471 | bool got_wi = k->get_wide_int (&wi); |
2472 | gcc_assert (got_wi); |
2473 | return wi; |
2474 | } |
2475 | |
2476 | /* Public entrypoint. See description in libgccjit.h. |
2477 | |
2478 | After error-checking, the real work is done by the |
2479 | gcc::jit::recording::block::end_with_switch method in |
2480 | jit-recording.c. */ |
2481 | |
2482 | void |
2483 | gcc_jit_block_end_with_switch (gcc_jit_block *block, |
2484 | gcc_jit_location *loc, |
2485 | gcc_jit_rvalue *expr, |
2486 | gcc_jit_block *default_block, |
2487 | int num_cases, |
2488 | gcc_jit_case **cases) |
2489 | { |
2490 | RETURN_IF_NOT_VALID_BLOCK (block, loc); |
2491 | gcc::jit::recording::context *ctxt = block->get_context (); |
2492 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2493 | /* LOC can be NULL. */ |
2494 | RETURN_IF_FAIL (expr, ctxt, loc, |
2495 | "NULL expr"); |
2496 | gcc::jit::recording::type *expr_type = expr->get_type (); |
2497 | RETURN_IF_FAIL_PRINTF2 ( |
2498 | expr_type->is_int (), |
2499 | ctxt, loc, |
2500 | "expr: %s (type: %s) is not of integer type", |
2501 | expr->get_debug_string (), |
2502 | expr_type->get_debug_string ()); |
2503 | if (!valid_dest_for_switch (ctxt, loc, |
2504 | __func__, |
2505 | block, |
2506 | default_block, |
2507 | "default_block")) |
2508 | return; |
2509 | RETURN_IF_FAIL (num_cases >= 0, ctxt, loc, "num_cases < 0"); |
2510 | case_range_validator crv (ctxt, loc, __func__); |
2511 | for (int i = 0; i < num_cases; i++) |
2512 | { |
2513 | char case_desc[32]; |
2514 | snprintf (case_desc, sizeof (case_desc), |
2515 | "cases[%i]", i); |
2516 | if (!valid_case_for_switch (ctxt, loc, |
2517 | __func__, |
2518 | block, |
2519 | expr, |
2520 | cases[i], |
2521 | case_desc, |
2522 | i)) |
2523 | return; |
2524 | if (!crv.validate (cases[i], i)) |
2525 | return; |
2526 | } |
2527 | |
2528 | block->end_with_switch (loc, expr, default_block, |
2529 | num_cases, |
2530 | (gcc::jit::recording::case_ **)cases); |
2531 | } |
2532 | |
2533 | /********************************************************************** |
2534 | Option-management |
2535 | **********************************************************************/ |
2536 | |
2537 | /* Public entrypoint. See description in libgccjit.h. |
2538 | |
2539 | After error-checking, the real work is done by the |
2540 | gcc::jit::recording::context::set_str_option method in |
2541 | jit-recording.c. */ |
2542 | |
2543 | void |
2544 | gcc_jit_context_set_str_option (gcc_jit_context *ctxt, |
2545 | enum gcc_jit_str_option opt, |
2546 | const char *value) |
2547 | { |
2548 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2549 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2550 | /* opt is checked by the inner function. |
2551 | value can be NULL. */ |
2552 | |
2553 | ctxt->set_str_option (opt, value); |
2554 | } |
2555 | |
2556 | /* Public entrypoint. See description in libgccjit.h. |
2557 | |
2558 | After error-checking, the real work is done by the |
2559 | gcc::jit::recording::context::set_int_option method in |
2560 | jit-recording.c. */ |
2561 | |
2562 | void |
2563 | gcc_jit_context_set_int_option (gcc_jit_context *ctxt, |
2564 | enum gcc_jit_int_option opt, |
2565 | int value) |
2566 | { |
2567 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2568 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2569 | /* opt is checked by the inner function. */ |
2570 | |
2571 | ctxt->set_int_option (opt, value); |
2572 | } |
2573 | |
2574 | /* Public entrypoint. See description in libgccjit.h. |
2575 | |
2576 | After error-checking, the real work is done by the |
2577 | gcc::jit::recording::context::set_bool_option method in |
2578 | jit-recording.c. */ |
2579 | |
2580 | void |
2581 | gcc_jit_context_set_bool_option (gcc_jit_context *ctxt, |
2582 | enum gcc_jit_bool_option opt, |
2583 | int value) |
2584 | { |
2585 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2586 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2587 | /* opt is checked by the inner function. */ |
2588 | |
2589 | ctxt->set_bool_option (opt, value); |
2590 | } |
2591 | |
2592 | /* Public entrypoint. See description in libgccjit.h. |
2593 | |
2594 | After error-checking, the real work is done by the |
2595 | gcc::jit::recording::context::set_inner_bool_option method in |
2596 | jit-recording.c. */ |
2597 | |
2598 | void |
2599 | gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context *ctxt, |
2600 | int bool_value) |
2601 | { |
2602 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2603 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2604 | ctxt->set_inner_bool_option ( |
2605 | gcc::jit::INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS, |
2606 | bool_value); |
2607 | } |
2608 | |
2609 | /* Public entrypoint. See description in libgccjit.h. |
2610 | |
2611 | After error-checking, the real work is done by the |
2612 | gcc::jit::recording::context::set_inner_bool_option method in |
2613 | jit-recording.c. */ |
2614 | |
2615 | extern void |
2616 | gcc_jit_context_set_bool_use_external_driver (gcc_jit_context *ctxt, |
2617 | int bool_value) |
2618 | { |
2619 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2620 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2621 | ctxt->set_inner_bool_option ( |
2622 | gcc::jit::INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER, |
2623 | bool_value); |
2624 | } |
2625 | |
2626 | /* Public entrypoint. See description in libgccjit.h. |
2627 | |
2628 | After error-checking, the real work is done by the |
2629 | gcc::jit::recording::context::add_command_line_option method in |
2630 | jit-recording.c. */ |
2631 | |
2632 | void |
2633 | gcc_jit_context_add_command_line_option (gcc_jit_context *ctxt, |
2634 | const char *optname) |
2635 | { |
2636 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2637 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2638 | RETURN_IF_FAIL (optname, ctxt, NULL, "NULL optname"); |
2639 | if (ctxt->get_logger ()) |
2640 | ctxt->get_logger ()->log ("optname: %s", optname); |
2641 | |
2642 | ctxt->add_command_line_option (optname); |
2643 | } |
2644 | |
2645 | /* Public entrypoint. See description in libgccjit.h. |
2646 | |
2647 | After error-checking, the real work is done by the |
2648 | gcc::jit::recording::context::enable_dump method in |
2649 | jit-recording.c. */ |
2650 | |
2651 | void |
2652 | gcc_jit_context_enable_dump (gcc_jit_context *ctxt, |
2653 | const char *dumpname, |
2654 | char **out_ptr) |
2655 | { |
2656 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2657 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2658 | RETURN_IF_FAIL (dumpname, ctxt, NULL, "NULL dumpname"); |
2659 | RETURN_IF_FAIL (out_ptr, ctxt, NULL, "NULL out_ptr"); |
2660 | |
2661 | ctxt->enable_dump (dumpname, out_ptr); |
2662 | } |
2663 | |
2664 | /* Public entrypoint. See description in libgccjit.h. |
2665 | |
2666 | After error-checking, the real work is done by the |
2667 | gcc::jit::recording::context::compile method in |
2668 | jit-recording.c. */ |
2669 | |
2670 | gcc_jit_result * |
2671 | gcc_jit_context_compile (gcc_jit_context *ctxt) |
2672 | { |
2673 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2674 | |
2675 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2676 | |
2677 | ctxt->log ("in-memory compile of ctxt: %p", (void *)ctxt); |
2678 | |
2679 | gcc_jit_result *result = (gcc_jit_result *)ctxt->compile (); |
2680 | |
2681 | ctxt->log ("%s: returning (gcc_jit_result *)%p", |
2682 | __func__, (void *)result); |
2683 | |
2684 | return result; |
2685 | } |
2686 | |
2687 | /* Public entrypoint. See description in libgccjit.h. |
2688 | |
2689 | After error-checking, the real work is done by the |
2690 | gcc::jit::recording::context::compile_to_file method in |
2691 | jit-recording.c. */ |
2692 | |
2693 | void |
2694 | gcc_jit_context_compile_to_file (gcc_jit_context *ctxt, |
2695 | enum gcc_jit_output_kind output_kind, |
2696 | const char *output_path) |
2697 | { |
2698 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2699 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2700 | RETURN_IF_FAIL_PRINTF1 ( |
2701 | ((output_kind >= GCC_JIT_OUTPUT_KIND_ASSEMBLER) |
2702 | && (output_kind <= GCC_JIT_OUTPUT_KIND_EXECUTABLE)), |
2703 | ctxt, NULL, |
2704 | "unrecognized output_kind: %i", |
2705 | output_kind); |
2706 | RETURN_IF_FAIL (output_path, ctxt, NULL, "NULL output_path"); |
2707 | |
2708 | ctxt->log ("compile_to_file of ctxt: %p", (void *)ctxt); |
2709 | ctxt->log ("output_kind: %i", output_kind); |
2710 | ctxt->log ("output_path: %s", output_path); |
2711 | |
2712 | ctxt->compile_to_file (output_kind, output_path); |
2713 | } |
2714 | |
2715 | |
2716 | /* Public entrypoint. See description in libgccjit.h. |
2717 | |
2718 | After error-checking, the real work is done by the |
2719 | gcc::jit::recording::context::dump_to_file method in |
2720 | jit-recording.c. */ |
2721 | |
2722 | void |
2723 | gcc_jit_context_dump_to_file (gcc_jit_context *ctxt, |
2724 | const char *path, |
2725 | int update_locations) |
2726 | { |
2727 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2728 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2729 | RETURN_IF_FAIL (path, ctxt, NULL, "NULL path"); |
2730 | ctxt->dump_to_file (path, update_locations); |
2731 | } |
2732 | |
2733 | /* Public entrypoint. See description in libgccjit.h. */ |
2734 | |
2735 | void |
2736 | gcc_jit_context_set_logfile (gcc_jit_context *ctxt, |
2737 | FILE *logfile, |
2738 | int flags, |
2739 | int verbosity) |
2740 | { |
2741 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2742 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2743 | RETURN_IF_FAIL ((flags == 0), ctxt, NULL, "flags must be 0 for now"); |
2744 | RETURN_IF_FAIL ((verbosity == 0), ctxt, NULL, "verbosity must be 0 for now"); |
2745 | |
2746 | gcc::jit::logger *logger; |
2747 | if (logfile) |
2748 | logger = new gcc::jit::logger (logfile, flags, verbosity); |
2749 | else |
2750 | logger = NULL; |
2751 | ctxt->set_logger (logger); |
2752 | } |
2753 | |
2754 | /* Public entrypoint. See description in libgccjit.h. |
2755 | |
2756 | After error-checking, the real work is done by the |
2757 | gcc::jit::recording::context::dump_reproducer_to_file method in |
2758 | jit-recording.c. */ |
2759 | |
2760 | void |
2761 | gcc_jit_context_dump_reproducer_to_file (gcc_jit_context *ctxt, |
2762 | const char *path) |
2763 | { |
2764 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2765 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2766 | RETURN_IF_FAIL (path, ctxt, NULL, "NULL path"); |
2767 | ctxt->dump_reproducer_to_file (path); |
2768 | } |
2769 | |
2770 | /* Public entrypoint. See description in libgccjit.h. |
2771 | |
2772 | After error-checking, the real work is done by the |
2773 | gcc::jit::recording::context::get_first_error method in |
2774 | jit-recording.c. */ |
2775 | |
2776 | const char * |
2777 | gcc_jit_context_get_first_error (gcc_jit_context *ctxt) |
2778 | { |
2779 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2780 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2781 | |
2782 | return ctxt->get_first_error (); |
2783 | } |
2784 | |
2785 | /* Public entrypoint. See description in libgccjit.h. |
2786 | |
2787 | After error-checking, the real work is done by the |
2788 | gcc::jit::recording::context::get_last_error method in |
2789 | jit-recording.c. */ |
2790 | |
2791 | const char * |
2792 | gcc_jit_context_get_last_error (gcc_jit_context *ctxt) |
2793 | { |
2794 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); |
2795 | |
2796 | return ctxt->get_last_error (); |
2797 | } |
2798 | |
2799 | /* Public entrypoint. See description in libgccjit.h. |
2800 | |
2801 | After error-checking, the real work is done by the |
2802 | gcc::jit::result::get_code method in jit-result.c. */ |
2803 | |
2804 | void * |
2805 | gcc_jit_result_get_code (gcc_jit_result *result, |
2806 | const char *fnname) |
2807 | { |
2808 | RETURN_NULL_IF_FAIL (result, NULL, NULL, "NULL result"); |
2809 | JIT_LOG_FUNC (result->get_logger ()); |
2810 | RETURN_NULL_IF_FAIL (fnname, NULL, NULL, "NULL fnname"); |
2811 | |
2812 | result->log ("locating fnname: %s", fnname); |
2813 | void *code = result->get_code (fnname); |
2814 | result->log ("%s: returning (void *)%p", __func__, code); |
2815 | |
2816 | return code; |
2817 | } |
2818 | |
2819 | /* Public entrypoint. See description in libgccjit.h. |
2820 | |
2821 | After error-checking, the real work is done by the |
2822 | gcc::jit::result::get_global method in jit-result.c. */ |
2823 | |
2824 | void * |
2825 | gcc_jit_result_get_global (gcc_jit_result *result, |
2826 | const char *name) |
2827 | { |
2828 | RETURN_NULL_IF_FAIL (result, NULL, NULL, "NULL result"); |
2829 | JIT_LOG_FUNC (result->get_logger ()); |
2830 | RETURN_NULL_IF_FAIL (name, NULL, NULL, "NULL name"); |
2831 | |
2832 | void *global = result->get_global (name); |
2833 | result->log ("%s: returning (void *)%p", __func__, global); |
2834 | |
2835 | return global; |
2836 | } |
2837 | |
2838 | /* Public entrypoint. See description in libgccjit.h. |
2839 | |
2840 | After error-checking, this is essentially a wrapper around the |
2841 | destructor for gcc::jit::result in jit-result.c. */ |
2842 | |
2843 | void |
2844 | gcc_jit_result_release (gcc_jit_result *result) |
2845 | { |
2846 | RETURN_IF_FAIL (result, NULL, NULL, "NULL result"); |
2847 | JIT_LOG_FUNC (result->get_logger ()); |
2848 | result->log ("deleting result: %p", (void *)result); |
2849 | delete result; |
2850 | } |
2851 | |
2852 | /********************************************************************** |
2853 | Timing support. |
2854 | **********************************************************************/ |
2855 | |
2856 | /* Create a gcc_jit_timer instance, and start timing. */ |
2857 | |
2858 | gcc_jit_timer * |
2859 | gcc_jit_timer_new (void) |
2860 | { |
2861 | gcc_jit_timer *timer = new gcc_jit_timer (); |
2862 | timer->start (TV_TOTAL); |
2863 | timer->push (TV_JIT_CLIENT_CODE); |
2864 | return timer; |
2865 | } |
2866 | |
2867 | /* Release a gcc_jit_timer instance. */ |
2868 | |
2869 | void |
2870 | gcc_jit_timer_release (gcc_jit_timer *timer) |
2871 | { |
2872 | RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer"); |
2873 | |
2874 | delete timer; |
2875 | } |
2876 | |
2877 | /* Associate a gcc_jit_timer instance with a context. */ |
2878 | |
2879 | void |
2880 | gcc_jit_context_set_timer (gcc_jit_context *ctxt, |
2881 | gcc_jit_timer *timer) |
2882 | { |
2883 | RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL ctxt"); |
2884 | RETURN_IF_FAIL (timer, ctxt, NULL, "NULL timer"); |
2885 | |
2886 | ctxt->set_timer (timer); |
2887 | } |
2888 | |
2889 | /* Get the timer associated with a context (if any). */ |
2890 | |
2891 | gcc_jit_timer * |
2892 | gcc_jit_context_get_timer (gcc_jit_context *ctxt) |
2893 | { |
2894 | RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL ctxt"); |
2895 | |
2896 | return (gcc_jit_timer *)ctxt->get_timer (); |
2897 | } |
2898 | |
2899 | /* Push the given item onto the timing stack. */ |
2900 | |
2901 | void |
2902 | gcc_jit_timer_push (gcc_jit_timer *timer, |
2903 | const char *item_name) |
2904 | { |
2905 | RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer"); |
2906 | RETURN_IF_FAIL (item_name, NULL, NULL, "NULL item_name"); |
2907 | timer->push_client_item (item_name); |
2908 | } |
2909 | |
2910 | /* Pop the top item from the timing stack. */ |
2911 | |
2912 | void |
2913 | gcc_jit_timer_pop (gcc_jit_timer *timer, |
2914 | const char *item_name) |
2915 | { |
2916 | RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer"); |
2917 | |
2918 | if (item_name) |
2919 | { |
2920 | const char *top_item_name = timer->get_topmost_item_name (); |
2921 | |
2922 | RETURN_IF_FAIL_PRINTF1 |
2923 | (top_item_name, NULL, NULL, |
2924 | "pop of empty timing stack (attempting to pop: \"%s\")", |
2925 | item_name); |
2926 | |
2927 | RETURN_IF_FAIL_PRINTF2 |
2928 | (0 == strcmp (item_name, top_item_name), NULL, NULL, |
2929 | "mismatching item_name:" |
2930 | " top of timing stack: \"%s\"," |
2931 | " attempting to pop: \"%s\"", |
2932 | top_item_name, |
2933 | item_name); |
2934 | } |
2935 | |
2936 | timer->pop_client_item (); |
2937 | } |
2938 | |
2939 | /* Print timing information to the given stream about activity since |
2940 | the timer was started. */ |
2941 | |
2942 | void |
2943 | gcc_jit_timer_print (gcc_jit_timer *timer, |
2944 | FILE *f_out) |
2945 | { |
2946 | RETURN_IF_FAIL (timer, NULL, NULL, "NULL timer"); |
2947 | RETURN_IF_FAIL (f_out, NULL, NULL, "NULL f_out"); |
2948 | |
2949 | timer->pop (TV_JIT_CLIENT_CODE); |
2950 | timer->stop (TV_TOTAL); |
2951 | timer->print (f_out); |
2952 | timer->start (TV_TOTAL); |
2953 | timer->push (TV_JIT_CLIENT_CODE); |
2954 | } |
2955 | |
2956 | /* Public entrypoint. See description in libgccjit.h. |
2957 | |
2958 | After error-checking, the real work is effectively done by the |
2959 | gcc::jit::base_call::set_require_tail_call setter in jit-recording.h. */ |
2960 | |
2961 | void |
2962 | gcc_jit_rvalue_set_bool_require_tail_call (gcc_jit_rvalue *rvalue, |
2963 | int require_tail_call) |
2964 | { |
2965 | RETURN_IF_FAIL (rvalue, NULL, NULL, "NULL call"); |
2966 | JIT_LOG_FUNC (rvalue->get_context ()->get_logger ()); |
2967 | |
2968 | /* Verify that it's a call. */ |
2969 | gcc::jit::recording::base_call *call = rvalue->dyn_cast_base_call (); |
2970 | RETURN_IF_FAIL_PRINTF1 (call, NULL, NULL, "not a call: %s", |
2971 | rvalue->get_debug_string ()); |
2972 | |
2973 | call->set_require_tail_call (require_tail_call); |
2974 | } |
2975 | |
2976 | /* Public entrypoint. See description in libgccjit.h. |
2977 | |
2978 | After error-checking, the real work is done by the |
2979 | gcc::jit::recording::type::get_aligned method, in |
2980 | jit-recording.c. */ |
2981 | |
2982 | gcc_jit_type * |
2983 | gcc_jit_type_get_aligned (gcc_jit_type *type, |
2984 | size_t alignment_in_bytes) |
2985 | { |
2986 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); |
2987 | |
2988 | gcc::jit::recording::context *ctxt = type->m_ctxt; |
2989 | |
2990 | JIT_LOG_FUNC (ctxt->get_logger ()); |
2991 | |
2992 | RETURN_NULL_IF_FAIL_PRINTF1 |
2993 | (pow2_or_zerop (alignment_in_bytes), ctxt, NULL, |
2994 | "alignment not a power of two: %zi", |
2995 | alignment_in_bytes); |
2996 | |
2997 | return (gcc_jit_type *)type->get_aligned (alignment_in_bytes); |
2998 | } |
2999 | |
3000 | /* Public entrypoint. See description in libgccjit.h. |
3001 | |
3002 | After error-checking, the real work is done by the |
3003 | gcc::jit::recording::type::get_vector method, in |
3004 | jit-recording.c. */ |
3005 | |
3006 | gcc_jit_type * |
3007 | gcc_jit_type_get_vector (gcc_jit_type *type, size_t num_units) |
3008 | { |
3009 | RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); |
3010 | |
3011 | gcc::jit::recording::context *ctxt = type->m_ctxt; |
3012 | |
3013 | JIT_LOG_FUNC (ctxt->get_logger ()); |
3014 | |
3015 | RETURN_NULL_IF_FAIL_PRINTF1 |
3016 | (type->is_int () || type->is_float (), ctxt, NULL, |
3017 | "type is not integral or floating point: %s", |
3018 | type->get_debug_string ()); |
3019 | |
3020 | RETURN_NULL_IF_FAIL_PRINTF1 |
3021 | (pow2_or_zerop (num_units), ctxt, NULL, |
3022 | "num_units not a power of two: %zi", |
3023 | num_units); |
3024 | |
3025 | return (gcc_jit_type *)type->get_vector (num_units); |
3026 | } |
3027 | |
3028 | /* Public entrypoint. See description in libgccjit.h. |
3029 | |
3030 | After error-checking, the real work is done by the |
3031 | gcc::jit::recording::function::get_address method, in |
3032 | jit-recording.c. */ |
3033 | |
3034 | gcc_jit_rvalue * |
3035 | gcc_jit_function_get_address (gcc_jit_function *fn, |
3036 | gcc_jit_location *loc) |
3037 | { |
3038 | RETURN_NULL_IF_FAIL (fn, NULL, NULL, "NULL function"); |
3039 | |
3040 | gcc::jit::recording::context *ctxt = fn->m_ctxt; |
3041 | |
3042 | JIT_LOG_FUNC (ctxt->get_logger ()); |
3043 | /* LOC can be NULL. */ |
3044 | |
3045 | return (gcc_jit_rvalue *)fn->get_address (loc); |
3046 | } |
3047 | |
3048 | /* Public entrypoint. See description in libgccjit.h. |
3049 | |
3050 | After error-checking, the real work is done by the |
3051 | gcc::jit::recording::context::new_rvalue_from_vector method, in |
3052 | jit-recording.c. */ |
3053 | |
3054 | extern gcc_jit_rvalue * |
3055 | gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt, |
3056 | gcc_jit_location *loc, |
3057 | gcc_jit_type *vec_type, |
3058 | size_t num_elements, |
3059 | gcc_jit_rvalue **elements) |
3060 | { |
3061 | RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL ctxt"); |
3062 | JIT_LOG_FUNC (ctxt->get_logger ()); |
3063 | |
3064 | /* LOC can be NULL. */ |
3065 | RETURN_NULL_IF_FAIL (vec_type, ctxt, loc, "NULL vec_type"); |
3066 | |
3067 | /* "vec_type" must be a vector type. */ |
3068 | gcc::jit::recording::vector_type *as_vec_type |
3069 | = vec_type->dyn_cast_vector_type (); |
3070 | RETURN_NULL_IF_FAIL_PRINTF1 (as_vec_type, ctxt, loc, |
3071 | "%s is not a vector type", |
3072 | vec_type->get_debug_string ()); |
3073 | |
3074 | /* "num_elements" must match. */ |
3075 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
3076 | num_elements == as_vec_type->get_num_units (), ctxt, loc, |
3077 | "num_elements != %zi", as_vec_type->get_num_units ()); |
3078 | |
3079 | /* "elements must be non-NULL. */ |
3080 | RETURN_NULL_IF_FAIL (elements, ctxt, loc, "NULL elements"); |
3081 | |
3082 | /* Each of "elements" must be non-NULL and of the correct type. */ |
3083 | gcc::jit::recording::type *element_type |
3084 | = as_vec_type->get_element_type (); |
3085 | for (size_t i = 0; i < num_elements; i++) |
3086 | { |
3087 | RETURN_NULL_IF_FAIL_PRINTF1 ( |
3088 | elements[i], ctxt, loc, "NULL elements[%zi]", i); |
3089 | RETURN_NULL_IF_FAIL_PRINTF4 ( |
3090 | compatible_types (element_type, |
3091 | elements[i]->get_type ()), |
3092 | ctxt, loc, |
3093 | "mismatching type for element[%zi] (expected type: %s): %s (type: %s)", |
3094 | i, |
3095 | element_type->get_debug_string (), |
3096 | elements[i]->get_debug_string (), |
3097 | elements[i]->get_type ()->get_debug_string ()); |
3098 | } |
3099 | |
3100 | return (gcc_jit_rvalue *)ctxt->new_rvalue_from_vector |
3101 | (loc, |
3102 | as_vec_type, |
3103 | (gcc::jit::recording::rvalue **)elements); |
3104 | } |
3105 |
Warning: That file was not part of the compilation database. It may have many parsing errors.