init_firm() takes now a parameter, the old behavior is enfrced with NULL.
[libfirm] / testprograms / oo_inline_example.c
1 /* Copyright (C)2002 by Universitaet Karlsruhe
2 * All rights reserved.
3 *
4 * Authors: Goetz Lindenmaier
5 *
6 * testprogram.
7 */
8
9 /* $ID$ */
10
11
12 # include <stdio.h>
13 # include <string.h>
14
15 # include "irvrfy.h"
16 # include "irdump.h"
17 # include "firm.h"
18
19 /**
20 *  @@@ this is no more correct ...
21 *  class PRIMA {
22 *    a: int;
23 *
24 *    int c(d: int) {
25 *      return (d + self.a);
26 *    }
27 *
28 *    void set_a(e:int) {
29 *      self.a = e;
30 *    }
31 *
32 *  }
33 *
34 *  int main() {
35 *    o: PRIMA;
36 *    o = new PRIMA;
37 *    o.set_a(2);
38 *    return o.c(5);
39 *  };
40 *
41 **/
42
43 int
44 main(void)
45 {
46   type     *prim_t_int;
47   type     *owner, *class_prima;
48   type     *proc_main, *proc_set_a, *proc_c;
49   type     *class_p_ptr;
50   entity   *proc_main_e, *proc_set_a_e, *proc_c_e, *a_e;
51
52   ir_graph     *main_irg, *set_a_irg, *c_irg;
53   ir_node      *c2, *c5, *obj_o, *obj_size, *proc_ptr, *res, *x, *set_a_call, *c_call;
54   ir_node      *self, *par1, *a_ptr;
55   ir_node      *a_val, *r, *t, *b, *f;
56
57   int o_pos, self_pos, e_pos;
58
59   int i;
60
61   init_firm (NULL);
62
63   set_optimize(1);
64   set_opt_inline (1);
65   set_opt_constant_folding(1);
66   set_opt_cse(1);
67   set_opt_dead_node_elimination(1);
68
69   /*** Make basic type information for primitive type int. ***/
70   prim_t_int = new_type_primitive(id_from_str ("int", 3), mode_Is);
71
72   /*** Make type information for the class (PRIMA). ***/
73   /* The type of the class */
74   class_prima = new_type_class(id_from_str ("PRIMA_INLINE", 5));
75   /* We need type information for pointers to the class: */
76   class_p_ptr = new_type_pointer (id_from_str ("class_prima_ptr", 15),
77                                   class_prima);
78   /* An entity for the field (a).  The entity constructor automatically adds
79      the entity as member of the owner. */
80   a_e = new_entity(class_prima, id_from_str ("a", 1), prim_t_int);
81   /* An entity for the method set_a.  But first we need type information
82      for the method. */
83   proc_set_a = new_type_method(id_from_str("set_a", 5), 2, 0);
84   set_method_param_type(proc_set_a, 0, class_p_ptr);
85   set_method_param_type(proc_set_a, 1, prim_t_int);
86   proc_set_a_e = new_entity(class_prima, id_from_str ("set_a", 5), proc_set_a);
87   /* An entity for the method c. Implicit argument "self" must be modeled
88      explicit! */
89   proc_c   = new_type_method(id_from_str("c", 1 ), 2, 1);
90   set_method_param_type(proc_c, 0, class_p_ptr);
91   set_method_param_type(proc_c, 1, prim_t_int);
92   set_method_res_type(proc_c, 0, prim_t_int);
93   proc_c_e = new_entity(class_prima, id_from_str ("c", 1), proc_c);
94
95   /*** Now build procedure main. ***/
96   /** Type information for main. **/
97   printf("\nCreating an IR graph: OO_INLINE_EXAMPLE...\n");
98   /* Main is not modeled as part of an explicit class here. Therefore the
99      owner is the global type. */
100   owner = get_glob_type();
101   /* Main has zero parameters and one result. */
102   proc_main = new_type_method(id_from_str("OO_INLINE_EXAMPLE_main", 22), 0, 1);
103   /* The result type is int. */
104   set_method_res_type(proc_main, 0, prim_t_int);
105
106   /* The entity for main. */
107   proc_main_e = new_entity (owner, id_from_str ("OO_INLINE_EXAMPLE_main", 22), proc_main);
108
109   /** Build code for procedure main. **/
110   /* We need one local variable (for "o"). */
111   main_irg = new_ir_graph (proc_main_e, 1);
112   o_pos = 0;
113
114   /* Remark that this irg is the main routine of the program. */
115   set_irp_main_irg(main_irg);
116
117   /* Make the constants.  They are independent of a block. */
118   c2 = new_Const (mode_Is, tarval_from_long (mode_Is, 2));
119   c5 = new_Const (mode_Is, tarval_from_long (mode_Is, 5));
120
121   /* There is only one block in main, it contains the allocation and the calls. */
122   /* Allocate the defined object and generate the type information. */
123   obj_size = new_SymConst((type_or_id_p)class_prima, size);
124   obj_o    = new_Alloc(get_store(), obj_size, class_prima, heap_alloc);
125   set_store(new_Proj(obj_o, mode_M, 0));  /* make the changed memory visible */
126   obj_o    = new_Proj(obj_o, mode_P, 2);  /* remember the pointer to the object */
127   set_value(o_pos, obj_o);
128
129   /* Get the pointer to the procedure from the object.  */
130   proc_ptr = new_simpleSel(get_store(),             /* The memory containing the object. */
131                            get_value(o_pos, mode_P),/* The pointer to the object. */
132                            proc_set_a_e );            /* The feature to select. */
133
134   /* Call procedure set_a, first built array with parameters. */
135   {
136     ir_node *in[2];
137     in[0] = get_value(o_pos, mode_P);
138     in[1] = c2;
139     set_a_call = new_Call(get_store(), proc_ptr, 2, in, proc_set_a);
140
141   }
142   /* Make the change to memory visible.  There are no results.  */
143   set_store(new_Proj(set_a_call, mode_M, 0));
144
145   /* Get the pointer to the nest procedure from the object. */
146   proc_ptr = new_simpleSel(get_store(), get_value(o_pos, mode_P), proc_c_e);
147
148   /* call procedure c, first built array with parameters */
149   {
150     ir_node *in[2];
151     in[0] = get_value(o_pos, mode_P);
152     in[1] = c5;
153     c_call = new_Call(get_store(), proc_ptr, 2, in, proc_c);
154   }
155   /* make the change to memory visible */
156   set_store(new_Proj(c_call, mode_M, 0));
157   /* Get the result of the procedure: select the result tuple from the call,
158      then the proper result from the tuple. */
159   res = new_Proj(new_Proj(c_call, mode_T, 2), mode_Is, 0);
160
161   /* return the results of procedure main */
162   {
163      ir_node *in[1];
164      in[0] = res;
165      x = new_Return (get_store(), 1, in);
166   }
167   mature_block (get_irg_current_block(main_irg));
168
169   /* complete the end_block */
170   add_in_edge (get_irg_end_block(main_irg), x);
171   mature_block (get_irg_end_block(main_irg));
172
173   irg_vrfy(main_irg);
174   finalize_cons (main_irg);
175
176   /****************************************************************************/
177
178   printf("Creating IR graph for set_a: \n");
179
180   /* Local variables: self, e */
181   set_a_irg = new_ir_graph (proc_set_a_e, 2);
182   self_pos = 0; e_pos = 1;
183
184   /* get the procedure parameter */
185   self = new_Proj(get_irg_args(set_a_irg), mode_P, 0);
186   set_value(self_pos, self);
187   par1 = new_Proj(get_irg_args(set_a_irg), mode_Is, 1);
188   set_value(e_pos, par1);
189   /* Create and select the entity to set */
190   a_ptr = new_simpleSel(get_store(), self, a_e);
191   /* perform the assignment */
192   set_store(new_Proj(new_Store(get_store(), a_ptr, par1), mode_M, 0));
193
194   /* return nothing */
195   x = new_Return (get_store (), 0, NULL);
196   mature_block (get_irg_current_block(set_a_irg));
197
198   /* complete the end_block */
199   add_in_edge (get_irg_end_block(set_a_irg), x);
200   mature_block (get_irg_end_block(set_a_irg));
201
202   /* verify the graph */
203   irg_vrfy(set_a_irg);
204   finalize_cons (set_a_irg);
205
206   /****************************************************************************/
207
208   printf("Creating IR graph for c: \n");
209
210   /* Local variables self, d */
211   c_irg = new_ir_graph (proc_c_e, 5);
212
213   /* get the procedure parameter */
214   self = new_Proj(get_irg_args(c_irg), mode_P, 0);
215   set_value(0, self);
216   par1 = new_Proj(get_irg_args(c_irg), mode_Is, 1);
217   set_value(1, par1);
218   set_value(2, new_Const (mode_Is, tarval_from_long (mode_Is, 0)));
219
220   x = new_Jmp();
221   mature_block (get_irg_current_block(c_irg));
222
223   /* generate a block for the loop header and the conditional branch */
224   r = new_immBlock ();
225   add_in_edge (r, x);
226   x = new_Cond (new_Proj(new_Cmp(new_Const (mode_Is, tarval_from_long (mode_Is, 0)),
227                                  new_Const (mode_Is, tarval_from_long (mode_Is, 0))),
228                          mode_b, Eq));
229
230   /*  x = new_Cond (new_Proj(new_Cmp(new_Const (mode_Is, tarval_from_long (mode_Is, 0)),
231                                  get_value(1, mode_Is)),
232                                  mode_b, Eq));*/
233   f = new_Proj (x, mode_X, 0);
234   t = new_Proj (x, mode_X, 1);
235
236   /* generate the block for the loop body */
237   b = new_immBlock ();
238   add_in_edge (b, t);
239
240   /* The code in the loop body,
241      as we are dealing with local variables only the dataflow edges
242      are manipulated. */
243   set_value (3, get_value (1, mode_Is));
244   set_value (1, get_value (2, mode_Is));
245   set_value (2, get_value (3, mode_Is));
246   a_ptr = new_simpleSel(get_store(), self, a_e);
247   set_store(new_Store(get_store(), a_ptr, get_value(2, mode_Is)));
248   x = new_Jmp ();
249   add_in_edge(r, x);
250   mature_block (b);
251   mature_block (r);
252
253   /* generate the return block */
254   r = new_immBlock ();
255   add_in_edge (r, f);
256   /* Select the entity and load the value */
257   a_ptr = new_simpleSel(get_store(), self, a_e);
258   a_val = new_Load(get_store(), a_ptr);
259   set_store(new_Proj(a_val, mode_M, 0));
260   a_val = new_Proj(a_val, mode_Is, 2);
261
262   /* return the result */
263   {
264     ir_node *in[1];
265     in[0] = new_Add(par1, a_val, mode_Is);
266
267     x = new_Return (get_store (), 1, in);
268   }
269   mature_block (r);
270
271   /* complete the end_block */
272   add_in_edge (get_irg_end_block(c_irg), x);
273   mature_block (get_irg_end_block(c_irg));
274
275   /* verify the graph */
276   irg_vrfy(c_irg);
277   finalize_cons (c_irg);
278
279   /****************************************************************************/
280
281   collect_phiprojs(main_irg);
282   current_ir_graph = main_irg;
283   printf("Inlining set_a ...\n");
284   inline_method(set_a_call, set_a_irg);
285   printf("INLINEing c ...\n");
286   inline_method(c_call, c_irg);
287
288   printf("Optimizing ...\n");
289
290   for (i = 0; i < get_irp_n_irgs(); i++) {
291     local_optimize_graph(get_irp_irg(i));
292     dead_node_elimination(get_irp_irg(i));
293   }
294
295   printf("Dumping graphs of all procedures and a type graph.\n");
296   turn_off_edge_labels();
297   dump_all_ir_graphs(dump_ir_block_graph);
298   dump_all_ir_graphs(dump_ir_block_graph_w_types);
299   dump_all_types();
300
301   printf("Use xvcg to view these graphs:\n");
302   printf("/ben/goetz/bin/xvcg GRAPHNAME\n\n");
303   return (0);
304 }