xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/jit/docs/examples/tut03-sum-of-squares.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 /* Usage example for libgccjit.so
2    Copyright (C) 2014-2020 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
create_code(gcc_jit_context * ctxt)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
main(int argc,char ** argv)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 }
173