test-nested-contexts.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include "libgccjit.h"
  4. #define TEST_ESCHEWS_TEST_JIT
  5. #define TEST_PROVIDES_MAIN
  6. #include "harness.h"
  7. struct quadratic
  8. {
  9. double a;
  10. double b;
  11. double c;
  12. double discriminant;
  13. };
  14. /* This is an adapted version of test-quadratic.c
  15. Like that test, we'll try to inject the following code, but we'll
  16. split it up into some nested contexts, in 3 levels, to test
  17. how nested contexts work.
  18. ***** In top-level context: *****
  19. (shared type declarations, for int, double, struct quadratic);
  20. extern double sqrt (double);
  21. ***** In mid-level context: *****
  22. void
  23. calc_discriminant (struct quadratic *q)
  24. {
  25. // (b^2 - 4ac)
  26. q->discriminant = (q->b * q->b) - (4 * q->a * q->c);
  27. }
  28. ***** In bottom context: *****
  29. int
  30. test_quadratic (double a, double b, double c, double *r1, double *r2)
  31. {
  32. struct quadratic q;
  33. q.a = a;
  34. q.b = b;
  35. q.c = c;
  36. calc_discriminant (&q);
  37. if (q.discriminant > 0)
  38. {
  39. double s = sqrt (q.discriminant);
  40. *r1 = (-b + s) / (2 * a);
  41. *r2 = (-b - s) / (2 * a);
  42. return 2;
  43. }
  44. else if (q.discriminant == 0)
  45. {
  46. *r1 = -b / (2 * a);
  47. return 1;
  48. }
  49. else return 0;
  50. }
  51. */
  52. struct top_level
  53. {
  54. gcc_jit_context *ctxt;
  55. /* "double" and "(double *)". */
  56. gcc_jit_type *numeric_type;
  57. gcc_jit_type *numeric_type_ptr;
  58. /* The value (double)0. */
  59. gcc_jit_rvalue *zero;
  60. gcc_jit_type *int_type;
  61. gcc_jit_type *void_type;
  62. /* "struct quadratic" */
  63. gcc_jit_type *struct_quadratic;
  64. gcc_jit_field *a;
  65. gcc_jit_field *b;
  66. gcc_jit_field *c;
  67. gcc_jit_field *discriminant;
  68. /* "(struct quadratic *)" */
  69. gcc_jit_type *quadratic_ptr;
  70. gcc_jit_function *sqrt;
  71. };
  72. struct middle_level
  73. {
  74. gcc_jit_context *ctxt;
  75. gcc_jit_function *calc_discriminant;
  76. };
  77. struct bottom_level
  78. {
  79. gcc_jit_context *ctxt;
  80. };
  81. static void
  82. make_types (struct top_level *top_level)
  83. {
  84. top_level->numeric_type =
  85. gcc_jit_context_get_type (top_level->ctxt, GCC_JIT_TYPE_DOUBLE);
  86. top_level->numeric_type_ptr =
  87. gcc_jit_type_get_pointer (top_level->numeric_type);
  88. top_level->zero =
  89. gcc_jit_context_zero (top_level->ctxt, top_level->numeric_type);
  90. top_level->int_type =
  91. gcc_jit_context_get_type (top_level->ctxt, GCC_JIT_TYPE_INT);
  92. top_level->void_type =
  93. gcc_jit_context_get_type (top_level->ctxt, GCC_JIT_TYPE_VOID);
  94. top_level->a =
  95. gcc_jit_context_new_field (top_level->ctxt,
  96. NULL,
  97. top_level->numeric_type,
  98. "a");
  99. top_level->b =
  100. gcc_jit_context_new_field (top_level->ctxt,
  101. NULL,
  102. top_level->numeric_type,
  103. "b");
  104. top_level->c =
  105. gcc_jit_context_new_field (top_level->ctxt,
  106. NULL,
  107. top_level->numeric_type,
  108. "c");
  109. top_level->discriminant =
  110. gcc_jit_context_new_field (top_level->ctxt,
  111. NULL,
  112. top_level->numeric_type,
  113. "discriminant");
  114. gcc_jit_field *fields[] = {top_level->a,
  115. top_level->b,
  116. top_level->c,
  117. top_level->discriminant};
  118. top_level->struct_quadratic =
  119. gcc_jit_struct_as_type (
  120. gcc_jit_context_new_struct_type (top_level->ctxt, NULL,
  121. "quadratic", 4, fields));
  122. top_level->quadratic_ptr =
  123. gcc_jit_type_get_pointer (top_level->struct_quadratic);
  124. }
  125. static void
  126. make_sqrt (struct top_level *top_level)
  127. {
  128. gcc_jit_param *param_x =
  129. gcc_jit_context_new_param (top_level->ctxt, NULL,
  130. top_level->numeric_type, "x");
  131. top_level->sqrt =
  132. gcc_jit_context_new_function (top_level->ctxt, NULL,
  133. GCC_JIT_FUNCTION_IMPORTED,
  134. top_level->numeric_type,
  135. "sqrt",
  136. 1, &param_x,
  137. 0);
  138. }
  139. static void
  140. make_calc_discriminant (struct top_level *top_level,
  141. struct middle_level *middle_level)
  142. {
  143. /* Build "calc_discriminant". */
  144. gcc_jit_param *param_q =
  145. gcc_jit_context_new_param (middle_level->ctxt, NULL,
  146. top_level->quadratic_ptr, "q");
  147. middle_level->calc_discriminant =
  148. gcc_jit_context_new_function (middle_level->ctxt, NULL,
  149. GCC_JIT_FUNCTION_EXPORTED,
  150. top_level->void_type,
  151. "calc_discriminant",
  152. 1, &param_q,
  153. 0);
  154. gcc_jit_block *blk =
  155. gcc_jit_function_new_block (middle_level->calc_discriminant, NULL);
  156. gcc_jit_block_add_comment (
  157. blk, NULL,
  158. "(b^2 - 4ac)");
  159. gcc_jit_rvalue *q_a =
  160. gcc_jit_lvalue_as_rvalue (
  161. gcc_jit_rvalue_dereference_field (
  162. gcc_jit_param_as_rvalue (param_q),
  163. NULL, top_level->a));
  164. gcc_jit_rvalue *q_b =
  165. gcc_jit_lvalue_as_rvalue (
  166. gcc_jit_rvalue_dereference_field (
  167. gcc_jit_param_as_rvalue (param_q),
  168. NULL, top_level->b));
  169. gcc_jit_rvalue *q_c =
  170. gcc_jit_lvalue_as_rvalue (
  171. gcc_jit_rvalue_dereference_field (
  172. gcc_jit_param_as_rvalue (param_q),
  173. NULL, top_level->c));
  174. gcc_jit_block_add_assignment (
  175. blk, NULL,
  176. /* q->discriminant =... */
  177. gcc_jit_rvalue_dereference_field (
  178. gcc_jit_param_as_rvalue (param_q),
  179. NULL,
  180. top_level->discriminant),
  181. /* (q->b * q->b) - (4 * q->a * q->c) */
  182. gcc_jit_context_new_binary_op (
  183. middle_level->ctxt, NULL,
  184. GCC_JIT_BINARY_OP_MINUS,
  185. top_level->numeric_type,
  186. /* (q->b * q->b) */
  187. gcc_jit_context_new_binary_op (
  188. middle_level->ctxt, NULL,
  189. GCC_JIT_BINARY_OP_MULT,
  190. top_level->numeric_type,
  191. q_b, q_b),
  192. /* (4 * (q->a * q->c)) */
  193. gcc_jit_context_new_binary_op (
  194. middle_level->ctxt, NULL,
  195. GCC_JIT_BINARY_OP_MULT,
  196. top_level->numeric_type,
  197. /* 4.0 */
  198. gcc_jit_context_new_rvalue_from_int (
  199. middle_level->ctxt,
  200. top_level->numeric_type,
  201. 4),
  202. /* (q->a * q->c) */
  203. gcc_jit_context_new_binary_op (
  204. middle_level->ctxt, NULL,
  205. GCC_JIT_BINARY_OP_MULT,
  206. top_level->numeric_type,
  207. q_a, q_c)))); /* end of gcc_jit_function_add_assignment call. */
  208. gcc_jit_block_end_with_void_return (blk, NULL);
  209. }
  210. static void
  211. make_test_quadratic (struct top_level *top_level,
  212. struct middle_level *middle_level,
  213. struct bottom_level *bottom_level)
  214. {
  215. gcc_jit_param *a =
  216. gcc_jit_context_new_param (bottom_level->ctxt, NULL,
  217. top_level->numeric_type, "a");
  218. gcc_jit_param *b =
  219. gcc_jit_context_new_param (bottom_level->ctxt, NULL,
  220. top_level->numeric_type, "b");
  221. gcc_jit_param *c =
  222. gcc_jit_context_new_param (bottom_level->ctxt, NULL,
  223. top_level->numeric_type, "c");
  224. gcc_jit_param *r1 =
  225. gcc_jit_context_new_param (bottom_level->ctxt, NULL,
  226. top_level->numeric_type_ptr, "r1");
  227. gcc_jit_param *r2 =
  228. gcc_jit_context_new_param (bottom_level->ctxt, NULL,
  229. top_level->numeric_type_ptr, "r2");
  230. gcc_jit_param *params[] = {a, b, c, r1, r2};
  231. gcc_jit_function *test_quadratic =
  232. gcc_jit_context_new_function (bottom_level->ctxt, NULL,
  233. GCC_JIT_FUNCTION_EXPORTED,
  234. top_level->int_type,
  235. "test_quadratic",
  236. 5, params,
  237. 0);
  238. /* struct quadratic q; */
  239. gcc_jit_lvalue *q =
  240. gcc_jit_function_new_local (
  241. test_quadratic, NULL,
  242. top_level->struct_quadratic,
  243. "q");
  244. gcc_jit_block *initial =
  245. gcc_jit_function_new_block (test_quadratic,
  246. "initial");
  247. gcc_jit_block *on_positive_discriminant
  248. = gcc_jit_function_new_block (test_quadratic,
  249. "positive_discriminant");
  250. gcc_jit_block *on_nonpositive_discriminant
  251. = gcc_jit_function_new_block (test_quadratic,
  252. "nonpositive_discriminant");
  253. gcc_jit_block *on_zero_discriminant
  254. = gcc_jit_function_new_block (test_quadratic,
  255. "zero_discriminant");
  256. gcc_jit_block *on_negative_discriminant
  257. = gcc_jit_function_new_block (test_quadratic,
  258. "negative_discriminant");
  259. /* Initial block. */
  260. /* q.a = a; */
  261. gcc_jit_block_add_assignment (
  262. initial, NULL,
  263. gcc_jit_lvalue_access_field (q, NULL, top_level->a),
  264. gcc_jit_param_as_rvalue (a));
  265. /* q.b = b; */
  266. gcc_jit_block_add_assignment (
  267. initial, NULL,
  268. gcc_jit_lvalue_access_field (q, NULL, top_level->b),
  269. gcc_jit_param_as_rvalue (b));
  270. /* q.c = c; */
  271. gcc_jit_block_add_assignment (
  272. initial, NULL,
  273. gcc_jit_lvalue_access_field (q, NULL, top_level->c),
  274. gcc_jit_param_as_rvalue (c));
  275. /* calc_discriminant (&q); */
  276. gcc_jit_rvalue *address_of_q = gcc_jit_lvalue_get_address (q, NULL);
  277. gcc_jit_block_add_eval (
  278. initial, NULL,
  279. gcc_jit_context_new_call (
  280. bottom_level->ctxt, NULL,
  281. middle_level->calc_discriminant,
  282. 1, &address_of_q));
  283. gcc_jit_block_add_comment (
  284. initial, NULL,
  285. "if (q.discriminant > 0)");
  286. gcc_jit_block_end_with_conditional (
  287. initial, NULL,
  288. gcc_jit_context_new_comparison (
  289. bottom_level->ctxt, NULL,
  290. GCC_JIT_COMPARISON_GT,
  291. gcc_jit_rvalue_access_field (
  292. gcc_jit_lvalue_as_rvalue (q),
  293. NULL,
  294. top_level->discriminant),
  295. top_level->zero),
  296. on_positive_discriminant,
  297. on_nonpositive_discriminant);
  298. /* Block: "on_positive_discriminant" */
  299. /* double s = sqrt (q.discriminant); */
  300. gcc_jit_lvalue *s = gcc_jit_function_new_local (
  301. test_quadratic, NULL,
  302. top_level->numeric_type,
  303. "s");
  304. gcc_jit_rvalue *discriminant_of_q =
  305. gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (q),
  306. NULL,
  307. top_level->discriminant);
  308. gcc_jit_block_add_assignment (
  309. on_positive_discriminant, NULL,
  310. s,
  311. gcc_jit_context_new_call (
  312. bottom_level->ctxt, NULL,
  313. top_level->sqrt,
  314. 1, &discriminant_of_q));
  315. gcc_jit_rvalue *minus_b =
  316. gcc_jit_context_new_unary_op (
  317. bottom_level->ctxt, NULL,
  318. GCC_JIT_UNARY_OP_MINUS,
  319. top_level->numeric_type,
  320. gcc_jit_param_as_rvalue (b));
  321. gcc_jit_rvalue *two_a =
  322. gcc_jit_context_new_binary_op (
  323. bottom_level->ctxt, NULL,
  324. GCC_JIT_BINARY_OP_MULT,
  325. top_level->numeric_type,
  326. gcc_jit_context_new_rvalue_from_int (
  327. bottom_level->ctxt,
  328. top_level->numeric_type,
  329. 2),
  330. gcc_jit_param_as_rvalue (a));
  331. gcc_jit_block_add_comment (
  332. on_positive_discriminant, NULL,
  333. "*r1 = (-b + s) / (2 * a);");
  334. gcc_jit_block_add_assignment (
  335. on_positive_discriminant, NULL,
  336. /* "*r1 = ..." */
  337. gcc_jit_rvalue_dereference (
  338. gcc_jit_param_as_rvalue (r1), NULL),
  339. /* (-b + s) / (2 * a) */
  340. gcc_jit_context_new_binary_op (
  341. bottom_level->ctxt, NULL,
  342. GCC_JIT_BINARY_OP_DIVIDE,
  343. top_level->numeric_type,
  344. gcc_jit_context_new_binary_op (
  345. bottom_level->ctxt, NULL,
  346. GCC_JIT_BINARY_OP_PLUS,
  347. top_level->numeric_type,
  348. minus_b,
  349. gcc_jit_lvalue_as_rvalue (s)),
  350. two_a));
  351. gcc_jit_block_add_comment (
  352. on_positive_discriminant, NULL,
  353. "*r2 = (-b - s) / (2 * a)");
  354. gcc_jit_block_add_assignment (
  355. on_positive_discriminant, NULL,
  356. /* "*r2 = ..." */
  357. gcc_jit_rvalue_dereference (
  358. gcc_jit_param_as_rvalue (r2), NULL),
  359. /* (-b - s) / (2 * a) */
  360. gcc_jit_context_new_binary_op (
  361. bottom_level->ctxt, NULL,
  362. GCC_JIT_BINARY_OP_DIVIDE,
  363. top_level->numeric_type,
  364. gcc_jit_context_new_binary_op (
  365. bottom_level->ctxt, NULL,
  366. GCC_JIT_BINARY_OP_MINUS,
  367. top_level->numeric_type,
  368. minus_b,
  369. gcc_jit_lvalue_as_rvalue (s)),
  370. two_a));
  371. /* "return 2;" */
  372. gcc_jit_block_end_with_return (
  373. on_positive_discriminant, NULL,
  374. gcc_jit_context_new_rvalue_from_int (
  375. bottom_level->ctxt,
  376. top_level->int_type,
  377. 2));
  378. /* Block: "on_nonpositive_discriminant" */
  379. gcc_jit_block_add_comment (
  380. on_nonpositive_discriminant, NULL,
  381. "else if (q.discriminant == 0)");
  382. gcc_jit_block_end_with_conditional (
  383. on_nonpositive_discriminant, NULL,
  384. gcc_jit_context_new_comparison (
  385. bottom_level->ctxt, NULL,
  386. GCC_JIT_COMPARISON_EQ,
  387. gcc_jit_rvalue_access_field (
  388. gcc_jit_lvalue_as_rvalue (q),
  389. NULL,
  390. top_level->discriminant),
  391. top_level->zero),
  392. on_zero_discriminant,
  393. on_negative_discriminant);
  394. /* Block: "on_zero_discriminant" */
  395. gcc_jit_block_add_comment (
  396. on_zero_discriminant, NULL,
  397. "*r1 = -b / (2 * a);");
  398. gcc_jit_block_add_assignment (
  399. on_zero_discriminant, NULL,
  400. /* "*r1 = ..." */
  401. gcc_jit_rvalue_dereference (
  402. gcc_jit_param_as_rvalue (r1), NULL),
  403. /* -b / (2 * a) */
  404. gcc_jit_context_new_binary_op (
  405. bottom_level->ctxt, NULL,
  406. GCC_JIT_BINARY_OP_DIVIDE,
  407. top_level->numeric_type,
  408. minus_b,
  409. two_a));
  410. /* "return 1;" */
  411. gcc_jit_block_end_with_return (
  412. on_zero_discriminant, NULL,
  413. gcc_jit_context_one (bottom_level->ctxt, top_level->int_type));
  414. /* Block: "on_negative_discriminant" */
  415. gcc_jit_block_end_with_return (
  416. /* else return 0; */
  417. on_negative_discriminant, NULL,
  418. gcc_jit_context_zero (bottom_level->ctxt, top_level->int_type));
  419. }
  420. void
  421. verify_middle_code (gcc_jit_context *ctxt, gcc_jit_result *result)
  422. {
  423. struct quadratic q;
  424. typedef void (*fn_type) (struct quadratic *q);
  425. fn_type calc_discriminant =
  426. (fn_type)gcc_jit_result_get_code (result,
  427. "calc_discriminant");
  428. CHECK_NON_NULL (calc_discriminant);
  429. q.a = 3;
  430. q.b = 5;
  431. q.c = 7;
  432. q.discriminant = 0;
  433. calc_discriminant (&q);
  434. CHECK_VALUE (q.discriminant, -59);
  435. }
  436. void
  437. verify_bottom_code (gcc_jit_context *ctxt, gcc_jit_result *result)
  438. {
  439. typedef int (*fn_type) (double a, double b, double c,
  440. double *r1, double *r2);
  441. CHECK_NON_NULL (result);
  442. fn_type test_quadratic =
  443. (fn_type)gcc_jit_result_get_code (result, "test_quadratic");
  444. CHECK_NON_NULL (test_quadratic);
  445. /* Verify that the code correctly solves quadratic equations. */
  446. double r1, r2;
  447. /* This one has two solutions: */
  448. CHECK_VALUE (test_quadratic (1, 3, -4, &r1, &r2), 2);
  449. CHECK_VALUE (r1, 1);
  450. CHECK_VALUE (r2, -4);
  451. /* This one has one solution: */
  452. CHECK_VALUE (test_quadratic (4, 4, 1, &r1, &r2), 1);
  453. CHECK_VALUE (r1, -0.5);
  454. /* This one has no real solutions: */
  455. CHECK_VALUE (test_quadratic (4, 1, 1, &r1, &r2), 0);
  456. }
  457. int
  458. main (int argc, char **argv)
  459. {
  460. int i, j, k;
  461. const int NUM_TOP_ITERATIONS = 2;
  462. const int NUM_MIDDLE_ITERATIONS = 2;
  463. const int NUM_BOTTOM_ITERATIONS = 2;
  464. /* We do the whole thing multiple times to shake out state-management
  465. issues in the underlying code. */
  466. FILE *logfile = fopen ("test-nested-contexts.c.exe.log.txt", "w");
  467. if (!logfile)
  468. fail ("error opening logfile");
  469. for (i = 1; i <= NUM_TOP_ITERATIONS; i++)
  470. {
  471. /* Create the top-level context. */
  472. snprintf (test, sizeof (test),
  473. "%s iteration %d of %d of top level",
  474. extract_progname (argv[0]),
  475. i, NUM_TOP_ITERATIONS);
  476. struct top_level top_level;
  477. memset (&top_level, 0, sizeof (top_level));
  478. top_level.ctxt = gcc_jit_context_acquire ();
  479. gcc_jit_context_set_logfile (top_level.ctxt,
  480. logfile,
  481. 0, 0);
  482. set_options (top_level.ctxt, argv[0]);
  483. make_types (&top_level);
  484. make_sqrt (&top_level);
  485. /* No errors should have occurred. */
  486. CHECK_VALUE (gcc_jit_context_get_first_error (top_level.ctxt), NULL);
  487. gcc_jit_context_dump_to_file (top_level.ctxt,
  488. "dump-of-test-nested-contexts-top.c",
  489. 1);
  490. for (j = 1; j <= NUM_MIDDLE_ITERATIONS; j++)
  491. {
  492. /* Create and populate the middle-level context, using
  493. objects from the top-level context. */
  494. snprintf (test, sizeof (test),
  495. ("%s iteration %d of %d of top level;"
  496. " %d of %d of middle level"),
  497. extract_progname (argv[0]),
  498. i, NUM_TOP_ITERATIONS,
  499. j, NUM_MIDDLE_ITERATIONS);
  500. struct middle_level middle_level;
  501. memset (&middle_level, 0, sizeof (middle_level));
  502. middle_level.ctxt =
  503. gcc_jit_context_new_child_context (top_level.ctxt);
  504. make_calc_discriminant (&top_level,
  505. &middle_level);
  506. /* No errors should have occurred. */
  507. CHECK_VALUE (gcc_jit_context_get_first_error (middle_level.ctxt),
  508. NULL);
  509. gcc_jit_context_dump_to_file (middle_level.ctxt,
  510. "dump-of-test-nested-contexts-middle.c",
  511. 1);
  512. gcc_jit_result *middle_result =
  513. gcc_jit_context_compile (middle_level.ctxt);
  514. CHECK_NON_NULL (middle_result);
  515. verify_middle_code (middle_level.ctxt, middle_result);
  516. for (k = 1; k <= NUM_BOTTOM_ITERATIONS; k++)
  517. {
  518. /* Create and populate the innermost context, using
  519. objects from the top-level and middle-level contexts. */
  520. snprintf (test, sizeof (test),
  521. ("%s iteration %d of %d of top level;"
  522. " %d of %d of middle level;"
  523. " %d of %d of bottom level"),
  524. extract_progname (argv[0]),
  525. i, NUM_TOP_ITERATIONS,
  526. j, NUM_MIDDLE_ITERATIONS,
  527. k, NUM_BOTTOM_ITERATIONS);
  528. struct bottom_level bottom_level;
  529. memset (&bottom_level, 0, sizeof (bottom_level));
  530. bottom_level.ctxt =
  531. gcc_jit_context_new_child_context (middle_level.ctxt);
  532. make_test_quadratic (&top_level,
  533. &middle_level,
  534. &bottom_level);
  535. /* No errors should have occurred. */
  536. CHECK_VALUE (gcc_jit_context_get_first_error (bottom_level.ctxt),
  537. NULL);
  538. gcc_jit_context_dump_to_file (bottom_level.ctxt,
  539. "dump-of-test-nested-contexts-bottom.c",
  540. 1);
  541. /* Dump a reproducer for the bottom context.
  542. The generated reproducer needs to also regenerate the
  543. parent contexts, so this gives us test coverage for
  544. that case. */
  545. gcc_jit_context_dump_reproducer_to_file (
  546. bottom_level.ctxt,
  547. "test-nested-contexts.c.exe.reproducer.c");
  548. gcc_jit_result *bottom_result =
  549. gcc_jit_context_compile (bottom_level.ctxt);
  550. verify_bottom_code (bottom_level.ctxt, bottom_result);
  551. gcc_jit_result_release (bottom_result);
  552. gcc_jit_context_release (bottom_level.ctxt);
  553. }
  554. gcc_jit_result_release (middle_result);
  555. gcc_jit_context_release (middle_level.ctxt);
  556. }
  557. gcc_jit_context_release (top_level.ctxt);
  558. }
  559. if (logfile)
  560. fclose (logfile);
  561. totals ();
  562. return 0;
  563. }