better output of testprograms, warning removed,
[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(id_from_str ("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 (id_from_str ("class_prima_ptr", 15),
78                                   class_prima);
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, id_from_str ("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(id_from_str("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, id_from_str ("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(id_from_str("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, id_from_str ("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(id_from_str("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, id_from_str ("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   obj_size = new_SymConst((type_or_id_p)class_prima, size);
125   obj_o    = new_Alloc(get_store(), obj_size, class_prima, heap_alloc);
126   set_store(new_Proj(obj_o, mode_M, 0));  /* make the changed memory visible */
127   obj_o    = new_Proj(obj_o, mode_P, 2);  /* remember the pointer to the object */
128   set_value(o_pos, obj_o);
129
130   /* Get the pointer to the procedure from the object.  */
131   proc_ptr = new_simpleSel(get_store(),             /* The memory containing the object. */
132                            get_value(o_pos, mode_P),/* The pointer to the object. */
133                            proc_set_a_e );            /* The feature to select. */
134
135   /* Call procedure set_a, first built array with parameters. */
136   {
137     ir_node *in[2];
138     in[0] = get_value(o_pos, mode_P);
139     in[1] = c2;
140     set_a_call = new_Call(get_store(), proc_ptr, 2, in, proc_set_a);
141
142   }
143   /* Make the change to memory visible.  There are no results.  */
144   set_store(new_Proj(set_a_call, mode_M, 0));
145
146   /* Get the pointer to the nest procedure from the object. */
147   proc_ptr = new_simpleSel(get_store(), get_value(o_pos, mode_P), proc_c_e);
148
149   /* call procedure c, first built array with parameters */
150   {
151     ir_node *in[2];
152     in[0] = get_value(o_pos, mode_P);
153     in[1] = c5;
154     c_call = new_Call(get_store(), proc_ptr, 2, in, proc_c);
155   }
156   /* make the change to memory visible */
157   set_store(new_Proj(c_call, mode_M, 0));
158   /* Get the result of the procedure: select the result tuple from the call,
159      then the proper result from the tuple. */
160   res = new_Proj(new_Proj(c_call, mode_T, 2), mode_Is, 0);
161
162   /* return the results of procedure main */
163   {
164      ir_node *in[1];
165      in[0] = res;
166      x = new_Return (get_store(), 1, in);
167   }
168   mature_block (get_irg_current_block(main_irg));
169
170   /* complete the end_block */
171   add_in_edge (get_irg_end_block(main_irg), x);
172   mature_block (get_irg_end_block(main_irg));
173
174   irg_vrfy(main_irg);
175   finalize_cons (main_irg);
176
177   /****************************************************************************/
178
179   printf("Creating IR graph for set_a: \n");
180
181   /* Local variables: self, e */
182   set_a_irg = new_ir_graph (proc_set_a_e, 2);
183   self_pos = 0; e_pos = 1;
184
185   /* get the procedure parameter */
186   self = new_Proj(get_irg_args(set_a_irg), mode_P, 0);
187   set_value(self_pos, self);
188   par1 = new_Proj(get_irg_args(set_a_irg), mode_Is, 1);
189   set_value(e_pos, par1);
190   /* Create and select the entity to set */
191   a_ptr = new_simpleSel(get_store(), self, a_e);
192   /* perform the assignment */
193   set_store(new_Proj(new_Store(get_store(), a_ptr, par1), mode_M, 0));
194
195   /* return nothing */
196   x = new_Return (get_store (), 0, NULL);
197   mature_block (get_irg_current_block(set_a_irg));
198
199   /* complete the end_block */
200   add_in_edge (get_irg_end_block(set_a_irg), x);
201   mature_block (get_irg_end_block(set_a_irg));
202
203   /* verify the graph */
204   irg_vrfy(set_a_irg);
205   finalize_cons (set_a_irg);
206
207   /****************************************************************************/
208
209   printf("Creating IR graph for c: \n");
210
211   /* Local variables self, d */
212   c_irg = new_ir_graph (proc_c_e, 5);
213
214   /* get the procedure parameter */
215   self = new_Proj(get_irg_args(c_irg), mode_P, 0);
216   set_value(0, self);
217   par1 = new_Proj(get_irg_args(c_irg), mode_Is, 1);
218   set_value(1, par1);
219   set_value(2, new_Const (mode_Is, new_tarval_from_long (0, mode_Is)));
220
221   x = new_Jmp();
222   mature_block (get_irg_current_block(c_irg));
223
224   /* generate a block for the loop header and the conditional branch */
225   r = new_immBlock ();
226   add_in_edge (r, x);
227   x = new_Cond (new_Proj(new_Cmp(new_Const (mode_Is, new_tarval_from_long (0, mode_Is)),
228                                  new_Const (mode_Is, new_tarval_from_long (0, mode_Is))),
229                          mode_b, Eq));
230
231   /*  x = new_Cond (new_Proj(new_Cmp(new_Const (mode_Is, new_tarval_from_long (0, mode_Is)),
232                                  get_value(1, mode_Is)),
233                                  mode_b, Eq));*/
234   f = new_Proj (x, mode_X, 0);
235   t = new_Proj (x, mode_X, 1);
236
237   /* generate the block for the loop body */
238   b = new_immBlock ();
239   add_in_edge (b, t);
240
241   /* The code in the loop body,
242      as we are dealing with local variables only the dataflow edges
243      are manipulated. */
244   set_value (3, get_value (1, mode_Is));
245   set_value (1, get_value (2, mode_Is));
246   set_value (2, get_value (3, mode_Is));
247   a_ptr = new_simpleSel(get_store(), self, a_e);
248   set_store(new_Store(get_store(), a_ptr, get_value(2, mode_Is)));
249   x = new_Jmp ();
250   add_in_edge(r, x);
251   mature_block (b);
252   mature_block (r);
253
254   /* generate the return block */
255   r = new_immBlock ();
256   add_in_edge (r, f);
257   /* Select the entity and load the value */
258   a_ptr = new_simpleSel(get_store(), self, a_e);
259   a_val = new_Load(get_store(), a_ptr);
260   set_store(new_Proj(a_val, mode_M, 0));
261   a_val = new_Proj(a_val, mode_Is, 2);
262
263   /* return the result */
264   {
265     ir_node *in[1];
266     in[0] = new_Add(par1, a_val, mode_Is);
267
268     x = new_Return (get_store (), 1, in);
269   }
270   mature_block (r);
271
272   /* complete the end_block */
273   add_in_edge (get_irg_end_block(c_irg), x);
274   mature_block (get_irg_end_block(c_irg));
275
276   /* verify the graph */
277   irg_vrfy(c_irg);
278   finalize_cons (c_irg);
279
280   /****************************************************************************/
281
282   collect_phiprojs(main_irg);
283   current_ir_graph = main_irg;
284   printf("Inlining set_a ...\n");
285   inline_method(set_a_call, set_a_irg);
286   printf("Inlineing c ...\n");
287   inline_method(c_call, c_irg);
288
289   printf("Optimizing ...\n");
290
291   for (i = 0; i < get_irp_n_irgs(); i++) {
292     local_optimize_graph(get_irp_irg(i));
293     dead_node_elimination(get_irp_irg(i));
294   }
295
296   printf("Dumping graphs of all procedures and a type graph.\n");
297   /* Touch ld names to distinguish names from oo_inline names. */
298   get_entity_ld_ident(proc_set_a_e);
299   get_entity_ld_ident(proc_c_e);
300   turn_off_edge_labels();
301   dump_all_ir_graphs(dump_ir_block_graph);
302   dump_all_ir_graphs(dump_ir_block_graph_w_types);
303   dump_all_types();
304
305   printf("Use xvcg to view these graphs:\n");
306   printf("/ben/goetz/bin/xvcg GRAPHNAME\n\n");
307   return (0);
308 }