1  /* Usage example for libgccjit.so
       2     Copyright (C) 2014-2023 Free Software Foundation, Inc.
       3  
       4  This file is part of GCC.
       5  
       6  GCC is free software; you can redistribute it and/or modify it
       7  under the terms of the GNU General Public License as published by
       8  the Free Software Foundation; either version 3, or (at your option)
       9  any later version.
      10  
      11  GCC is distributed in the hope that it will be useful, but
      12  WITHOUT ANY WARRANTY; without even the implied warranty of
      13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14  General Public License for more details.
      15  
      16  You should have received a copy of the GNU General Public License
      17  along with GCC; see the file COPYING3.  If not see
      18  <http://www.gnu.org/licenses/>.  */
      19  
      20  #include <libgccjit.h>
      21  
      22  #include <stdlib.h>
      23  #include <stdio.h>
      24  
      25  void
      26  create_code (gcc_jit_context *ctxt)
      27  {
      28    /*
      29      Simple sum-of-squares, to test conditionals and looping
      30  
      31      int loop_test (int n)
      32      {
      33        int i;
      34        int sum = 0;
      35        for (i = 0; i < n ; i ++)
      36        {
      37  	sum += i * i;
      38        }
      39        return sum;
      40     */
      41    gcc_jit_type *the_type =
      42      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
      43    gcc_jit_type *return_type = the_type;
      44  
      45    gcc_jit_param *n =
      46      gcc_jit_context_new_param (ctxt, NULL, the_type, "n");
      47    gcc_jit_param *params[1] = {n};
      48    gcc_jit_function *func =
      49      gcc_jit_context_new_function (ctxt, NULL,
      50  				  GCC_JIT_FUNCTION_EXPORTED,
      51  				  return_type,
      52  				  "loop_test",
      53  				  1, params, 0);
      54  
      55    /* Build locals:  */
      56    gcc_jit_lvalue *i =
      57      gcc_jit_function_new_local (func, NULL, the_type, "i");
      58    gcc_jit_lvalue *sum =
      59      gcc_jit_function_new_local (func, NULL, the_type, "sum");
      60  
      61    gcc_jit_block *b_initial =
      62      gcc_jit_function_new_block (func, "initial");
      63    gcc_jit_block *b_loop_cond =
      64      gcc_jit_function_new_block (func, "loop_cond");
      65    gcc_jit_block *b_loop_body =
      66      gcc_jit_function_new_block (func, "loop_body");
      67    gcc_jit_block *b_after_loop =
      68      gcc_jit_function_new_block (func, "after_loop");
      69  
      70    /* sum = 0; */
      71    gcc_jit_block_add_assignment (
      72      b_initial, NULL,
      73      sum,
      74      gcc_jit_context_zero (ctxt, the_type));
      75  
      76    /* i = 0; */
      77    gcc_jit_block_add_assignment (
      78      b_initial, NULL,
      79      i,
      80      gcc_jit_context_zero (ctxt, the_type));
      81  
      82    gcc_jit_block_end_with_jump (b_initial, NULL, b_loop_cond);
      83  
      84    /* if (i >= n) */
      85    gcc_jit_block_end_with_conditional (
      86      b_loop_cond, NULL,
      87      gcc_jit_context_new_comparison (
      88         ctxt, NULL,
      89         GCC_JIT_COMPARISON_GE,
      90         gcc_jit_lvalue_as_rvalue (i),
      91         gcc_jit_param_as_rvalue (n)),
      92      b_after_loop,
      93      b_loop_body);
      94  
      95    /* sum += i * i */
      96    gcc_jit_block_add_assignment_op (
      97      b_loop_body, NULL,
      98      sum,
      99      GCC_JIT_BINARY_OP_PLUS,
     100      gcc_jit_context_new_binary_op (
     101        ctxt, NULL,
     102        GCC_JIT_BINARY_OP_MULT, the_type,
     103        gcc_jit_lvalue_as_rvalue (i),
     104        gcc_jit_lvalue_as_rvalue (i)));
     105  
     106    /* i++ */
     107    gcc_jit_block_add_assignment_op (
     108      b_loop_body, NULL,
     109      i,
     110      GCC_JIT_BINARY_OP_PLUS,
     111      gcc_jit_context_one (ctxt, the_type));
     112  
     113    gcc_jit_block_end_with_jump (b_loop_body, NULL, b_loop_cond);
     114  
     115    /* return sum */
     116    gcc_jit_block_end_with_return (
     117      b_after_loop,
     118      NULL,
     119      gcc_jit_lvalue_as_rvalue (sum));
     120  }
     121  
     122  int
     123  main (int argc, char **argv)
     124  {
     125    gcc_jit_context *ctxt = NULL;
     126    gcc_jit_result *result = NULL;
     127  
     128    /* Get a "context" object for working with the library.  */
     129    ctxt = gcc_jit_context_acquire ();
     130    if (!ctxt)
     131      {
     132        fprintf (stderr, "NULL ctxt");
     133        goto error;
     134      }
     135  
     136    /* Set some options on the context.
     137       Let's see the code being generated, in assembler form.  */
     138    gcc_jit_context_set_bool_option (
     139      ctxt,
     140      GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
     141      0);
     142  
     143    /* Populate the context.  */
     144    create_code (ctxt);
     145  
     146    /* Compile the code.  */
     147    result = gcc_jit_context_compile (ctxt);
     148    if (!result)
     149      {
     150        fprintf (stderr, "NULL result");
     151        goto error;
     152      }
     153  
     154    /* Extract the generated code from "result".  */
     155    typedef int (*loop_test_fn_type) (int);
     156    loop_test_fn_type loop_test =
     157      (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test");
     158    if (!loop_test)
     159      {
     160        fprintf (stderr, "NULL loop_test");
     161        goto error;
     162      }
     163  
     164    /* Run the generated code.  */
     165    int val = loop_test (10);
     166    printf("loop_test returned: %d\n", val);
     167  
     168   error:
     169    gcc_jit_context_release (ctxt);
     170    gcc_jit_result_release (result);
     171    return 0;
     172  }