1  /* Smoketest 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  static void
      26  create_code (gcc_jit_context *ctxt)
      27  {
      28    /* Let's try to inject the equivalent of:
      29       void
      30       greet (const char *name)
      31       {
      32          printf ("hello %s\n", name);
      33       }
      34    */
      35    gcc_jit_type *void_type =
      36      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
      37    gcc_jit_type *const_char_ptr_type =
      38      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR);
      39    gcc_jit_param *param_name =
      40      gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "name");
      41    gcc_jit_function *func =
      42      gcc_jit_context_new_function (ctxt, NULL,
      43                                    GCC_JIT_FUNCTION_EXPORTED,
      44                                    void_type,
      45                                    "greet",
      46                                    1, ¶m_name,
      47                                    0);
      48  
      49    gcc_jit_param *param_format =
      50      gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "format");
      51    gcc_jit_function *printf_func =
      52      gcc_jit_context_new_function (ctxt, NULL,
      53  				  GCC_JIT_FUNCTION_IMPORTED,
      54  				  gcc_jit_context_get_type (
      55  				     ctxt, GCC_JIT_TYPE_INT),
      56  				  "printf",
      57  				  1, ¶m_format,
      58  				  1);
      59    gcc_jit_rvalue *args[2];
      60    args[0] = gcc_jit_context_new_string_literal (ctxt, "hello %s\n");
      61    args[1] = gcc_jit_param_as_rvalue (param_name);
      62  
      63    gcc_jit_block *block = gcc_jit_function_new_block (func, NULL);
      64  
      65    gcc_jit_block_add_eval (
      66      block, NULL,
      67      gcc_jit_context_new_call (ctxt,
      68                                NULL,
      69                                printf_func,
      70                                2, args));
      71    gcc_jit_block_end_with_void_return (block, NULL);
      72  }
      73  
      74  int
      75  main (int argc, char **argv)
      76  {
      77    gcc_jit_context *ctxt;
      78    gcc_jit_result *result;
      79  
      80    /* Get a "context" object for working with the library.  */
      81    ctxt = gcc_jit_context_acquire ();
      82    if (!ctxt)
      83      {
      84        fprintf (stderr, "NULL ctxt");
      85        exit (1);
      86      }
      87  
      88    /* Set some options on the context.
      89       Let's see the code being generated, in assembler form.  */
      90    gcc_jit_context_set_bool_option (
      91      ctxt,
      92      GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
      93      0);
      94  
      95    /* Populate the context.  */
      96    create_code (ctxt);
      97  
      98    /* Compile the code.  */
      99    result = gcc_jit_context_compile (ctxt);
     100    if (!result)
     101      {
     102        fprintf (stderr, "NULL result");
     103        exit (1);
     104      }
     105  
     106    /* Extract the generated code from "result".  */
     107    typedef void (*fn_type) (const char *);
     108    fn_type greet =
     109      (fn_type)gcc_jit_result_get_code (result, "greet");
     110    if (!greet)
     111      {
     112        fprintf (stderr, "NULL greet");
     113        exit (1);
     114      }
     115  
     116    /* Now call the generated function: */
     117    greet ("world");
     118    fflush (stdout);
     119  
     120    gcc_jit_context_release (ctxt);
     121    gcc_jit_result_release (result);
     122    return 0;
     123  }