1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 
5 #include "libgccjit.h"
6 
7 #include "harness.h"
8 
9 static char *dump_vrp1;
10 
11 void
create_code(gcc_jit_context * ctxt,void * user_data)12 create_code (gcc_jit_context *ctxt, void *user_data)
13 {
14   /*
15     Simple sum-of-squares, to test conditionals and looping
16 
17     int loop_test (int n)
18     {
19       int i;
20       int sum = 0;
21       for (i = 0; i < n ; i ++)
22       {
23 	sum += i * i;
24       }
25       return sum;
26    */
27   gcc_jit_context_enable_dump (ctxt, "tree-vrp1", &dump_vrp1);
28 
29   gcc_jit_type *the_type =
30     gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
31   gcc_jit_type *return_type = the_type;
32 
33   gcc_jit_param *n =
34     gcc_jit_context_new_param (ctxt, NULL, the_type, "n");
35   gcc_jit_param *params[1] = {n};
36   gcc_jit_function *func =
37     gcc_jit_context_new_function (ctxt, NULL,
38 				  GCC_JIT_FUNCTION_EXPORTED,
39 				  return_type,
40 				  "loop_test",
41 				  1, params, 0);
42 
43   /* Build locals:  */
44   gcc_jit_lvalue *i =
45     gcc_jit_function_new_local (func, NULL, the_type, "i");
46   gcc_jit_lvalue *sum =
47     gcc_jit_function_new_local (func, NULL, the_type, "sum");
48 
49   gcc_jit_block *initial =
50     gcc_jit_function_new_block (func, "initial");
51   gcc_jit_block *loop_cond =
52     gcc_jit_function_new_block (func, "loop_cond");
53   gcc_jit_block *loop_body =
54     gcc_jit_function_new_block (func, "loop_body");
55   gcc_jit_block *after_loop =
56     gcc_jit_function_new_block (func, "after_loop");
57 
58   /* sum = 0; */
59   gcc_jit_block_add_assignment (
60     initial, NULL,
61     sum,
62     gcc_jit_context_new_rvalue_from_int (ctxt, the_type, 0));
63 
64   /* i = 0; */
65   gcc_jit_block_add_assignment (
66     initial, NULL,
67     i,
68     gcc_jit_context_new_rvalue_from_int (ctxt, the_type, 0));
69 
70   gcc_jit_block_end_with_jump (initial, NULL, loop_cond);
71 
72   /* if (i >= n) */
73   gcc_jit_block_end_with_conditional (
74     loop_cond, NULL,
75     gcc_jit_context_new_comparison (
76        ctxt, NULL,
77        GCC_JIT_COMPARISON_GE,
78        gcc_jit_lvalue_as_rvalue (i),
79        gcc_jit_param_as_rvalue (n)),
80     after_loop,
81     loop_body);
82 
83   /* sum += i * i */
84   gcc_jit_block_add_assignment (
85     loop_body, NULL,
86     sum,
87     gcc_jit_context_new_binary_op (
88       ctxt, NULL,
89       GCC_JIT_BINARY_OP_PLUS, the_type,
90       gcc_jit_lvalue_as_rvalue (sum),
91       gcc_jit_context_new_binary_op (
92 	 ctxt, NULL,
93 	 GCC_JIT_BINARY_OP_MULT, the_type,
94 	 gcc_jit_lvalue_as_rvalue (i),
95 	 gcc_jit_lvalue_as_rvalue (i))));
96 
97   /* i++ */
98   gcc_jit_block_add_assignment (
99     loop_body, NULL,
100     i,
101     gcc_jit_context_new_binary_op (
102       ctxt, NULL,
103       GCC_JIT_BINARY_OP_PLUS, the_type,
104       gcc_jit_lvalue_as_rvalue (i),
105       gcc_jit_context_new_rvalue_from_int (
106 	ctxt,
107 	the_type,
108 	1)));
109 
110   gcc_jit_block_end_with_jump (loop_body, NULL, loop_cond);
111 
112   /* return sum */
113   gcc_jit_block_end_with_return (
114     after_loop,
115     NULL,
116     gcc_jit_lvalue_as_rvalue (sum));
117 }
118 
119 void
verify_code(gcc_jit_context * ctxt,gcc_jit_result * result)120 verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
121 {
122   typedef int (*loop_test_fn_type) (int);
123   CHECK_NON_NULL (result);
124   loop_test_fn_type loop_test =
125     (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test");
126   CHECK_NON_NULL (loop_test);
127   int val = loop_test (10);
128   note ("loop_test returned: %d", val);
129   CHECK_VALUE (val, 285);
130 
131   CHECK_NON_NULL (dump_vrp1);
132   /* PR jit/64166
133      An example of using gcc_jit_context_enable_dump to verify a property
134      of the compile.
135 
136      In this case, verify that vrp is able to deduce the
137      bounds of the iteration variable. Specifically, verify that some
138      variable is known to be in the range negative infinity to some
139      expression based on param "n" (actually n-1).  */
140   CHECK_STRING_CONTAINS (dump_vrp1, "[-INF, n_");
141   free (dump_vrp1);
142 }
143