First implementation of lowering for calls with compound return values
[libfirm] / testprograms / oo_program_example.c
1 /*
2  * Project:     libFIRM
3  * File name:   testprograms/oo_program_example.c
4  * Purpose:     A complex example.
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 *
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, *call, *res, *x;
55   ir_node      *self, *par1, *a_ptr;
56   ir_node      *a_val;
57
58   int o_pos, self_pos, e_pos;
59
60   int i;
61
62   init_firm (NULL);
63
64   set_opt_constant_folding(1);
65   set_opt_cse(1);
66   set_opt_dead_node_elimination(1);
67
68   /*** Make basic type information for primitive type int. ***/
69   prim_t_int = new_type_primitive(new_id_from_chars ("int", 3), mode_Is);
70
71   /*** Make type information for the class (PRIMA). ***/
72   /* The type of the class */
73   class_prima = new_type_class(new_id_from_chars ("PRIMA", 5));
74   /* We need type information for pointers to the class: */
75   class_p_ptr = new_type_pointer (new_id_from_chars("class_prima_ptr", 15),
76                                   class_prima, mode_P);
77   /* An entity for the field (a).  The entity constructor automatically adds
78      the entity as member of the owner. */
79   a_e = new_entity(class_prima, new_id_from_chars ("a", 1), prim_t_int);
80   /* An entity for the method set_a.  But first we need type information
81      for the method. */
82   proc_set_a = new_type_method(new_id_from_chars("set_a", 5), 2, 0);
83   set_method_param_type(proc_set_a, 0, class_p_ptr);
84   set_method_param_type(proc_set_a, 1, prim_t_int);
85   proc_set_a_e = new_entity(class_prima, new_id_from_chars ("set_a", 5), proc_set_a);
86   /* An entity for the method c. Implicit argument "self" must be modeled
87      explicit! */
88   proc_c   = new_type_method(new_id_from_chars("c", 1 ), 2, 1);
89   set_method_param_type(proc_c, 0, class_p_ptr);
90   set_method_param_type(proc_c, 1, prim_t_int);
91   set_method_res_type(proc_c, 0, prim_t_int);
92   proc_c_e = new_entity(class_prima, new_id_from_chars ("c", 1), proc_c);
93
94   /*** Now build procedure main. ***/
95   /** Type information for main. **/
96   printf("\nCreating an IR graph: OO_PROGRAM_EXAMPLE...\n");
97   /* Main is not modeled as part of an explicit class here. Therefore the
98      owner is the global type. */
99   owner = get_glob_type();
100   /* Main has zero parameters and one result. */
101   proc_main = new_type_method(new_id_from_chars("OO_PROGRAM_EXAMPLE_main", 23), 0, 1);
102   /* The result type is int. */
103   set_method_res_type(proc_main, 0, prim_t_int);
104
105   /* The entity for main. */
106   proc_main_e = new_entity (owner, new_id_from_chars ("OO_PROGRAM_EXAMPLE_main", 23), proc_main);
107
108   /** Build code for procedure main. **/
109   /* We need one local variable (for "o"). */
110   main_irg = new_ir_graph (proc_main_e, 1);
111   o_pos = 0;
112
113   /* Remark that this irg is the main routine of the program. */
114   set_irp_main_irg(main_irg);
115
116   /* Make the constants.  They are independent of a block. */
117   c2 = new_Const (mode_Is, new_tarval_from_long (2, mode_Is));
118   c5 = new_Const (mode_Is, new_tarval_from_long (5, mode_Is));
119
120   /* There is only one block in main, it contains the allocation and the calls. */
121   /* Allocate the defined object and generate the type information. */
122   symconst_symbol sym = {class_prima};
123   obj_size = new_SymConst(sym, symconst_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     call = new_Call(get_store(), proc_ptr, 2, in, proc_set_a);
140   }
141   /* Make the change to memory visible.  There are no results.  */
142   set_store(new_Proj(call, mode_M, 0));
143
144   /* Get the pointer to the nest procedure from the object. */
145   proc_ptr = new_simpleSel(get_store(), get_value(o_pos, mode_P), proc_c_e);
146
147   /* call procedure c, first built array with parameters */
148   {
149     ir_node *in[2];
150     in[0] = get_value(o_pos, mode_P);
151     in[1] = c5;
152     call = new_Call(get_store(), proc_ptr, 2, in, proc_c);
153   }
154   /* make the change to memory visible */
155   set_store(new_Proj(call, mode_M, 0));
156   /* Get the result of the procedure: select the result tuple from the call,
157      then the proper result from the tuple. */
158   res = new_Proj(new_Proj(call, mode_T, 2), mode_Is, 0);
159
160   /* return the results of procedure main */
161   {
162      ir_node *in[1];
163      in[0] = res;
164      x = new_Return (get_store(), 1, in);
165   }
166   mature_immBlock (get_irg_current_block(main_irg));
167
168   /* complete the end_block */
169   add_immBlock_pred (get_irg_end_block(main_irg), x);
170   mature_immBlock (get_irg_end_block(main_irg));
171
172   irg_vrfy(main_irg);
173   irg_finalize_cons (main_irg);
174
175   /****************************************************************************/
176
177   printf("Creating IR graph for set_a: \n");
178
179   /* Local variables: self, e */
180   set_a_irg = new_ir_graph (proc_set_a_e, 2);
181   self_pos = 0; e_pos = 1;
182
183   /* get the procedure parameter */
184   self = new_Proj(get_irg_args(set_a_irg), mode_P, 0);
185   set_value(self_pos, self);
186   par1 = new_Proj(get_irg_args(set_a_irg), mode_Is, 1);
187   set_value(e_pos, par1);
188   /* Create and select the entity to set */
189   a_ptr = new_simpleSel(get_store(), self, a_e);
190   /* perform the assignment */
191   set_store(new_Proj(new_Store(get_store(), a_ptr, par1), mode_M, 0));
192
193   /* return nothing */
194   x = new_Return (get_store (), 0, NULL);
195   mature_immBlock (get_irg_current_block(set_a_irg));
196
197   /* complete the end_block */
198   add_immBlock_pred (get_irg_end_block(set_a_irg), x);
199   mature_immBlock (get_irg_end_block(set_a_irg));
200
201   /* verify the graph */
202   irg_vrfy(set_a_irg);
203   irg_finalize_cons (set_a_irg);
204
205   /****************************************************************************/
206
207   printf("Creating IR graph for c: \n");
208
209   /* Local variables self, d */
210   c_irg = new_ir_graph (proc_c_e, 2);
211
212   /* get the procedure parameter */
213   self = new_Proj(get_irg_args(c_irg), mode_P, 0);
214   par1 = new_Proj(get_irg_args(c_irg), mode_Is, 1);
215
216   /* Select the entity and load the value */
217   a_ptr = new_simpleSel(get_store(), self, a_e);
218   a_val = new_Load(get_store(), a_ptr, mode_Is);
219   set_store(new_Proj(a_val, mode_M, 0));
220   a_val = new_Proj(a_val, mode_Is, 2);
221
222   /* return the result */
223   {
224     ir_node *in[1];
225     in[0] = new_Add(par1, a_val, mode_Is);
226
227     x = new_Return (get_store (), 1, in);
228   }
229   mature_immBlock (get_irg_current_block(c_irg));
230
231   /* complete the end_block */
232   add_immBlock_pred (get_irg_end_block(c_irg), x);
233   mature_immBlock (get_irg_end_block(c_irg));
234
235   /* verify the graph */
236   irg_vrfy(c_irg);
237   irg_finalize_cons (c_irg);
238
239   /****************************************************************************/
240
241   printf("Optimizing ...\n");
242   for (i = 0; i < get_irp_n_irgs(); i++) {
243     local_optimize_graph(get_irp_irg(i));
244     dead_node_elimination(get_irp_irg(i));
245   }
246
247   printf("Dumping graphs of all procedures and a type graph.\n");
248   /* Touch ld names to distinguish names from oo_inline names. */
249   get_entity_ld_ident(proc_set_a_e);
250   get_entity_ld_ident(proc_c_e);
251
252   dump_consts_local(1);
253   turn_off_edge_labels();
254
255   dump_all_ir_graphs(dump_ir_graph, "");
256   dump_all_ir_graphs(dump_ir_block_graph, "");
257   dump_all_ir_graphs(dump_ir_graph_w_types, "");
258   dump_all_ir_graphs(dump_ir_block_graph_w_types, "");
259   dump_all_ir_graphs(dump_type_graph, "");
260   dump_all_ir_graphs(dump_graph_as_text, "");
261   dump_all_types("");
262   dump_class_hierarchy (1, "");
263
264   entity **free_methods;
265   int arr_len;
266   cgana(&arr_len, &free_methods);
267   cg_construct(arr_len, free_methods);
268
269   set_interprocedural_view(1);
270   dump_ir_graph(main_irg, "");
271   dump_ir_block_graph(main_irg, "");
272   dump_ir_graph_w_types(main_irg, "");
273   dump_ir_block_graph_w_types(main_irg, "");
274   dump_all_cg_block_graph("");
275
276   printf("Use xvcg to view these graphs:\n");
277   printf("/ben/goetz/bin/xvcg GRAPHNAME\n\n");
278   return (0);
279 }