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