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