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