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