c373bbb662dbce5667a3aa584fcf9838cdc25df3
[libfirm] / ir / external / read.c
1 /* -*- c -*- */
2
3 /*
4  * Project:     libFIRM
5  * File name:   ir/external/read.c
6  * Purpose:     Read descriptions of external effects
7  * Author:      Florian
8  * Modified by: Boris Boesler
9  * Created:     11.10.2004
10  * CVS-ID:      $Id$
11  * Copyright:   (c) 1999-2004 Universität Karlsruhe
12  * Licence:     This file is protected by GPL -  GNU GENERAL PUBLIC LICENSE.
13  */
14
15 #ifdef HAVE_CONFIG_H
16 # include "config.h"
17 #endif
18
19 /* get prototype for alloca somehow */
20 #ifdef HAVE_ALLOCA_H
21 # include <alloca.h>
22 #endif
23 #ifdef HAVE_STDLIB_H
24 # include <stdlib.h>
25 #endif
26
27 # include "read.h"
28 #include "irprog.h"
29 #include "irgraph.h"
30 #include "ircons.h"
31 #include "irmode.h"
32 #include "irdump.h"
33 #include "irvrfy.h"
34 #include "type.h"
35 #include "tv.h"
36
37 #define VERBOSE_PRINTING 0
38
39 #if VERBOSE_PRINTING
40 # define VERBOSE_PRINT(s) fprintf s
41 #else
42 # define VERBOSE_PRINT(s)
43 #endif
44
45 #define NO_ID NULL
46
47 static type_t *types = NULL;
48 static entity_t *entities = NULL;
49 static proc_t *procs = NULL;
50 static module_t *modules = NULL;
51
52 /* @@@ HACK */
53 static module_t *current_module = NULL;
54
55 static char *effect_string[] = {
56   "arg",
57   "valref",
58   "select",
59   "load",
60   "store",
61   "alloc",
62   "call",
63   "unknown",
64   "join",
65   "raise",
66   "ret"
67 };
68
69 static const ident*
70 getNodeModuleIdent (xmlNodePtr node)
71 {
72   const char *mod_str = (const char*) xmlGetProp (node, BAD_CAST "module");
73
74   if (NULL == mod_str) {
75     return (NULL);
76   } else {
77     const ident *res = new_id_from_str (mod_str);
78     return (res);
79   }
80 }
81
82 static const char*
83 getNodeProcName (xmlNodePtr node)
84 {
85   const char *proc_str = (const char*) xmlGetProp (node, BAD_CAST "procname");
86   assert (proc_str);
87   return (proc_str);
88 }
89
90 static char*
91 getNodeClassName (xmlNodePtr node)
92 {
93   char *proc_str = (char*) xmlGetProp (node, BAD_CAST "class");
94   assert (proc_str);
95   return ( (proc_str));
96 }
97
98 static const char*
99 getNodeId (xmlNodePtr node)
100 {
101   const char *id_str = (const char*) xmlGetProp (node, BAD_CAST "id");
102   assert (id_str);
103   return (id_str);
104 }
105
106 static const char *
107 getNodeRefId (xmlNodePtr node)
108 {
109   const char *refid_str = (char*) xmlGetProp (node, BAD_CAST "refid");
110   assert (refid_str);
111   return ((refid_str));
112 }
113
114 static const char*
115 getNodeTypeId (xmlNodePtr node)
116 {
117   const char *type_str = (char*) xmlGetProp (node, BAD_CAST "type");
118   assert (type_str);
119   return ((type_str));
120 }
121
122 static const char
123 *getNodeTypeStr (xmlNodePtr node)
124 {
125   const char *type_str = (char*) xmlGetProp (node, BAD_CAST "type");
126   assert (type_str);
127   return (type_str);
128 }
129
130 static const char*
131 getNodeOwnerStr (xmlNodePtr node)
132 {
133   const char *owner_str = (char*) xmlGetProp (node, BAD_CAST "owner");
134   assert (owner_str);
135   return (owner_str);
136 }
137
138 static const char
139 *getNodeEntityStr (xmlNodePtr node)
140 {
141   const char *ent_str = (char*) xmlGetProp (node, BAD_CAST "entity");
142   assert (ent_str);
143
144   return (ent_str);
145 }
146
147
148 /*
149   was Public Interface
150 */
151 static
152 type_t *getTypeByIdent (const ident *id)
153 {
154   type_t *curr = types; // @@@ TODO module -> types
155
156   while (NULL != curr) {
157     if (id == curr -> type_ident) {
158       return (curr);
159     }
160     curr = curr->prev;
161   }
162
163   return (NULL);
164 }
165
166 static
167 type_t *getTypeById (const ident *id)
168 {
169   type_t *curr = types; // which ones?
170
171   while (NULL != curr) {
172     if (id == curr -> id) {
173       return (curr);
174     }
175     curr = curr->prev;
176   }
177
178   return (NULL);
179 }
180
181 static
182 entity_t *getEntityByIdents (const ident *name, const ident *tp_ident)
183 {
184   entity_t *curr = entities; // TODO module -> entities
185
186   while (NULL != curr) {
187     if ((name == curr -> ent_ident)
188         && (tp_ident == curr -> tp_ident)) {
189       return (curr);
190     }
191     curr = curr->prev;
192   }
193
194   return (NULL);
195 }
196
197 static
198 entity_t *getEntityById (const ident *id)
199 {
200   entity_t *curr = entities;
201
202   while (NULL != curr) {
203     if (id == curr -> id) {
204       return (curr);
205     }
206     curr = curr->prev;
207   }
208
209   return (NULL);
210 }
211
212 static
213 proc_t *getEffectByName (const ident *proc_ident)
214 {
215   proc_t *curr_effs = procs;
216
217   while (NULL != curr_effs) {
218     if (proc_ident == curr_effs -> proc_ident) {
219       return (curr_effs);
220     }
221     curr_effs = curr_effs->next;
222   }
223
224   return (NULL);
225 }
226
227
228 /*
229  * parse XML structure and construct an additional structure
230  */
231 static eff_t *
232 parseArg (xmlDocPtr doc, xmlNodePtr argelm)
233 {
234   const char *id;
235   const char *typeid;
236   int num;
237   char *num_str;
238   eff_t *arg;
239
240   CHECK_NAME (argelm, arg);
241   VERBOSE_PRINT ((stdout, "arg node \t0x%08x\n", (int) argelm));
242
243   id = getNodeId (argelm);
244   VERBOSE_PRINT ((stdout, "arg->id = \"%s\"\n", id));
245   num_str = (char*) xmlGetProp (argelm, BAD_CAST "number");
246   num = atoi (num_str);
247   VERBOSE_PRINT ((stdout, "arg->no = \"%d\"\n", num));
248
249   typeid = getNodeTypeStr (argelm);
250
251   arg = NEW (eff_t);
252   arg -> kind = eff_arg;
253   arg -> id = new_id_from_str(id);
254   arg -> effect.arg.num = num;
255   arg -> effect.arg.type_ident = new_id_from_str(typeid);
256
257   return (arg);
258 }
259
260 static eff_t
261 *parseValref (xmlDocPtr doc, xmlNodePtr valelm)
262 {
263   const char *ref_id;
264   eff_t *valref;
265
266   CHECK_NAME (valelm, valref);
267   VERBOSE_PRINT ((stdout, "valref node \t0x%08x\n", (int) valelm));
268
269   ref_id = getNodeRefId (valelm);
270   VERBOSE_PRINT ((stdout, "val->refid = \"%s\"\n", ref_id));
271
272   valref = NEW (eff_t);
273   valref->kind = eff_valref;
274   valref-> id = new_id_from_str(ref_id);
275
276   return (valref);
277 }
278
279 static eff_t
280 *parseSelect (xmlDocPtr doc, xmlNodePtr selelm)
281 {
282   const ident *entity_id = new_id_from_str(getNodeEntityStr (selelm));
283   entity_t *ent;
284   xmlNodePtr child;
285   eff_t *valref = NULL;
286   eff_t *sel = NEW (eff_t);
287   sel->kind = eff_select;
288
289   CHECK_NAME (selelm, select);
290   VERBOSE_PRINT ((stdout, "select node \t0x%08x\n", (int) selelm));
291
292   ent = getEntityById (entity_id);
293   assert(ent && "entity not found");
294   VERBOSE_PRINT ((stdout, "select entity %s\n", get_id_str(ent -> ent_ident)));
295
296   child = selelm->xmlChildrenNode;
297
298   if (child) {
299     valref = parseValref (doc, child);
300   }
301
302   sel-> id = valref ? valref-> id : NO_ID;
303   sel-> effect.select.ent = ent;
304
305   if (valref) {
306     free (valref);
307   }
308
309   return (sel);
310 }
311
312 static eff_t
313 *parseLoad (xmlDocPtr doc, xmlNodePtr loadelm)
314 {
315   const ident *id;
316   xmlNodePtr child;
317   eff_t *sel;
318   eff_t *load = NEW (eff_t);
319   load->kind = eff_load;
320
321   CHECK_NAME (loadelm, load);
322   VERBOSE_PRINT ((stdout, "load node \t0x%08x\n", (int) loadelm));
323   id = new_id_from_str(getNodeId (loadelm));
324
325   child = loadelm->xmlChildrenNode;
326   sel = parseSelect (doc, child);
327
328   load-> id = id;
329   load-> effect.load.ptrrefid = sel-> id;
330   load-> effect.load.ent = sel-> effect.select.ent;
331   VERBOSE_PRINT ((stdout, "load entity \t%s\n",
332                   get_id_str(load -> effect.load.ent -> ent_ident)));
333
334   free (sel);
335
336   return (load);
337 }
338
339 static eff_t
340 *parseStore (xmlDocPtr doc, xmlNodePtr storeelm)
341 {
342   xmlNodePtr child;
343   eff_t *sel;
344   eff_t *valref;
345   eff_t *store = NEW (eff_t);
346   store->kind = eff_store;
347
348   CHECK_NAME (storeelm, store);
349   VERBOSE_PRINT ((stdout, "store node \t0x%08x\n", (int) storeelm));
350
351   child = storeelm->xmlChildrenNode;
352   sel = parseSelect (doc, child);
353   child = child->next;
354   valref = parseValref (doc, child);
355
356   store-> effect.store.ent = sel-> effect.select.ent;
357   store-> effect.store.ptrrefid = sel-> id;
358   store-> effect.store.valrefid = valref-> id;
359
360   free (sel);
361   free (valref);
362
363   return (store);
364 }
365
366 static eff_t
367 *parseAlloc (xmlDocPtr doc, xmlNodePtr allocelm)
368 {
369   const ident *id;
370   const ident *type_id;
371   eff_t *alloc = NEW (eff_t); /* ...! */
372   alloc->kind = eff_alloc;
373
374   CHECK_NAME (allocelm, alloc);
375   VERBOSE_PRINT ((stdout, "alloc node \t0x%08x\n", (int) allocelm));
376   id = new_id_from_str(getNodeId (allocelm));
377   VERBOSE_PRINT ((stdout, "alloc->id = \"%s\"\n", get_id_str(id)));
378   type_id = new_id_from_str(getNodeTypeId (allocelm));
379   VERBOSE_PRINT ((stdout, "alloc->type_id = \"%s\"\n", get_id_str(type_id)));
380
381   alloc-> id = id;
382   alloc-> effect.alloc.tp_id = type_id;
383
384   return (alloc);
385 }
386
387 static eff_t
388 *parseCall (xmlDocPtr doc, xmlNodePtr callelm)
389 {
390   const ident *id;
391   xmlNodePtr child;
392   eff_t *sel;
393   xmlNodePtr arg;
394   int n_args;
395   eff_t *call = NEW (eff_t);
396   call->kind = eff_call;
397
398   CHECK_NAME (callelm, call);
399   VERBOSE_PRINT ((stdout, "call node \t0x%08x\n", (int) callelm));
400   id = new_id_from_str(getNodeId (callelm));
401   VERBOSE_PRINT ((stdout, "call->id = \"%s\"\n", get_id_str(id)));
402
403   child = callelm->xmlChildrenNode;
404   sel = parseSelect (doc, child);
405   arg = child = child->next;
406   n_args = 0;
407
408   while (NULL != child) {
409     n_args ++;
410     child = child->next;
411   }
412
413   call-> id = id;
414   call-> effect.call.valrefid = sel-> id;
415   call-> effect.call.ent = sel-> effect.select.ent;
416   call-> effect.call.n_args = n_args;
417   call-> effect.call.args = NULL;
418
419   free (sel);
420
421   if (0 != n_args) {
422     const ident **args = (const ident**) malloc(n_args * sizeof(const ident*));
423     int i = 0;
424
425     while (NULL != arg) {
426       eff_t *valref = parseValref (doc, arg);
427       args [i ++] = valref-> id;
428       free (valref);
429       arg = arg->next;
430     }
431
432     call-> effect.call.args = args;
433   }
434
435   return (call);
436 }
437
438 static eff_t
439 *parseJoin (xmlDocPtr doc, xmlNodePtr joinelm)
440 {
441   const ident *id;
442   int n_ins;
443   const ident **ins;
444   int i;
445   xmlNodePtr child;
446   eff_t *join = NEW (eff_t);
447   join->kind = eff_join;
448
449   CHECK_NAME (joinelm, join);
450   VERBOSE_PRINT ((stdout, "join node \t0x%08x\n", (int) joinelm));
451   id = new_id_from_str(getNodeId (joinelm));
452   VERBOSE_PRINT ((stdout, "join->id = \"%s\"\n", get_id_str(id)));
453
454   child = joinelm->xmlChildrenNode;
455   n_ins = 0;
456
457   while (NULL != child) {
458     n_ins ++;
459     child = child->next;
460   }
461
462   ins = (const ident **) malloc (n_ins * sizeof (const ident *) );
463   i = 0;
464   child = joinelm->xmlChildrenNode;
465
466   while (NULL != child) {
467     eff_t *valref = parseValref (doc, child);
468     ins [i ++] = valref-> id;
469     free(valref);
470     child = child->next;
471   }
472
473   join-> id = id;
474   join-> effect.join.n_ins = n_ins;
475   join-> effect.join.ins = ins;
476
477   return (join);
478 }
479
480 static eff_t
481 *parseUnknown (xmlDocPtr doc, xmlNodePtr unknownelm)
482 {
483   const ident *id;
484   eff_t *unknown = NEW (eff_t);
485   unknown->kind = eff_unknown;
486
487   CHECK_NAME (unknownelm, unknown);
488   VERBOSE_PRINT ((stdout, "unknown node \t0x%08x\n", (int) unknownelm));
489   id = new_id_from_str(getNodeId (unknownelm));
490   unknown-> id = id;
491
492   return (unknown);
493 }
494
495 static eff_t
496 *parseReturn (xmlDocPtr doc, xmlNodePtr retelm)
497 {
498   xmlNodePtr child;
499   eff_t *ret = NEW (eff_t);
500   ret->kind = eff_ret;
501
502   CHECK_NAME (retelm, ret);
503   VERBOSE_PRINT ((stdout, "ret node \t0x%08x\n", (int) retelm));
504
505   child = retelm->xmlChildrenNode;
506
507   if (child) {
508     eff_t *valref = parseValref (doc, child);
509     ret-> effect.ret.ret_id = valref-> id;
510     free (valref);
511   } else {
512     ret-> effect.ret.ret_id = NO_ID;
513   }
514
515   return (ret);
516 }
517
518 static eff_t
519 *parseRaise (xmlDocPtr doc, xmlNodePtr raiseelm)
520 {
521   const char *tp_id;
522   eff_t *valref;
523   xmlNodePtr child;
524   eff_t *raise = NEW (eff_t);
525   raise->kind = eff_raise;
526
527   CHECK_NAME (raiseelm, raise);
528   VERBOSE_PRINT ((stdout, "raise node \t0x%08x\n", (int) raiseelm));
529   tp_id = getNodeTypeId (raiseelm);
530   VERBOSE_PRINT ((stdout, "raise->type = \"%s\"\n", tp_id));
531   child = raiseelm->xmlChildrenNode;
532
533   assert (NULL != child);
534
535   valref = parseValref (doc, child);
536   raise-> effect.raise.valref = valref-> id;
537   raise-> effect.raise.tp_id = new_id_from_str(tp_id);
538   free (valref);
539
540   return (raise);
541 }
542
543
544 /*
545   Types and Entities
546 */
547
548 /** parse a type node and insert it into the list */
549 static void
550 parseType (xmlDocPtr doc, xmlNodePtr typeelm)
551 {
552   type_t *type;
553   const char *tp_id = getNodeId (typeelm);
554   VERBOSE_PRINT ((stdout, "type node \t0x%08x (%s)\n", (int) typeelm, tp_id));
555   VERBOSE_PRINT ((stdout, "type = \"%s\"\n", getNodeTypeStr (typeelm)));
556
557   type = (type_t*) malloc (sizeof (type_t));
558   type -> type_ident = new_id_from_str(getNodeTypeStr (typeelm));
559   type -> id         = new_id_from_str(tp_id);
560
561   type->prev = types;
562   types = type;
563 }
564
565 /** parse an entity node and insert it into the list */
566 static void
567 parseEntity (xmlDocPtr doc, xmlNodePtr entelm)
568 {
569   entity_t *ent = NEW (entity_t);
570
571   /* parse it */
572   const char *ent_id = getNodeId (entelm);
573   /* fprintf (stdout, "entity node \t0x%08x (%d)\n", (int) entelm, ent_id); */
574   VERBOSE_PRINT ((stdout, "ent  = \"%s.%s\"\n",
575                   getNodeTypeStr (entelm),
576                   getNodeEntityStr (entelm)));
577
578
579   ent -> ent_ident = new_id_from_str (getNodeEntityStr (entelm));
580   ent -> tp_ident  = new_id_from_str (getNodeTypeStr   (entelm));
581   ent -> owner     = new_id_from_str (getNodeOwnerStr  (entelm));
582   ent -> id = new_id_from_str(ent_id);
583
584   ent->prev = entities;
585   entities = ent;
586 }
587
588 /** parse any effect, and turn it into an eff_t (TODO) */
589 static void
590 parseEffect (xmlDocPtr doc, xmlNodePtr effelm)
591 {
592   xmlNodePtr cur;
593   const char *procname = getNodeProcName (effelm);
594   const char *typeid = getNodeTypeStr (effelm);
595   proc_t *curr_effs = NULL;
596   int i = 0;
597   int n_effs = 0;
598
599   VERBOSE_PRINT ((stdout, "effect for method \"%s\"\n", procname));
600
601   cur = effelm -> xmlChildrenNode;
602   while (NULL != cur) {
603     n_effs ++;
604     cur = cur->next;
605   }
606   VERBOSE_PRINT ((stdout, "has %d effects\n", n_effs));
607
608   curr_effs = NEW (proc_t);
609   curr_effs -> proc_ident = new_id_from_str(procname);
610   curr_effs -> typeid = new_id_from_str(typeid);
611   curr_effs->effs = (eff_t**) malloc (n_effs * sizeof (eff_t*));
612
613   cur = effelm -> xmlChildrenNode;
614   while (NULL != cur) {
615     eff_t *eff = NULL;
616
617     if (NODE_NAME (cur, arg)) {
618       eff = (eff_t*) parseArg (doc, cur);
619     } else if (NODE_NAME (cur, load)) {
620       eff = (eff_t*) parseLoad (doc, cur);
621     } else if (NODE_NAME (cur, store)) {
622       eff = (eff_t*) parseStore (doc, cur);
623     } else if (NODE_NAME (cur, alloc)) {
624       eff = (eff_t*) parseAlloc (doc, cur);
625     } else if (NODE_NAME (cur, call)) {
626       eff = (eff_t*) parseCall (doc, cur);
627     } else if (NODE_NAME (cur, join)) {
628       eff = (eff_t*) parseJoin (doc, cur);
629     } else if (NODE_NAME (cur, unknown)) {
630       eff = (eff_t*) parseUnknown (doc, cur);
631     } else if (NODE_NAME (cur, ret)) {
632       eff = (eff_t*) parseReturn (doc, cur);
633     } else if (NODE_NAME (cur, raise)) {
634       eff = (eff_t*) parseRaise (doc, cur);
635     } else if (NODE_NAME (cur, comment)) {
636       /* comment */
637       --n_effs;
638     } else {
639       fprintf (stderr, "wrong element \"%s\"\n", BAD_CAST cur->name);
640       exit (EXIT_FAILURE);
641     }
642     if(eff) {
643       VERBOSE_PRINT ((stdout, "effect %p@%d\n", (void*)eff, i));
644       curr_effs -> effs[i++] = eff;
645     }
646     cur = cur -> next;
647   }
648   assert((i == n_effs) && "incorrect number of effects");
649   curr_effs -> n_effs = n_effs;
650   curr_effs -> next = procs;
651   procs = curr_effs;
652 }
653
654
655 static
656 void read_extern (const char *filename)
657 {
658   /* xmlNsPtr ns = NULL; */           /* no namespace for us */
659   xmlDocPtr doc;                /* whole document */
660   xmlNodePtr cur;               /* current node */
661   ident *mod_id;
662   module_t *module;
663
664   /* i've got no idea what the VERSION cast is all about. voodoo
665      programming at its finest. */
666   LIBXML_TEST_VERSION xmlKeepBlanksDefault (0);
667   VERBOSE_PRINT((stdout, "read file %s\n", filename));
668   doc = xmlParseFile (filename);
669   CHECK (doc, "xmlParseFile");
670
671   cur = xmlDocGetRootElement (doc);
672   CHECK (cur, "xmlDocGetRootElement");
673
674   if (! NODE_NAME (cur, effects)) {
675     fprintf (stderr,"root node \"%s\" != \"effects\"\n", BAD_CAST cur->name);
676     xmlFreeDoc (doc);
677     exit (EXIT_FAILURE);
678   }
679
680   mod_id = getNodeModuleIdent (cur);
681   if (NULL != mod_id) {
682     VERBOSE_PRINT ((stdout, "effects for \"%s\"\n",
683                     get_id_str(mod_id)));
684   }
685   else {
686     VERBOSE_PRINT ((stdout, "effects \t0x%08x\n", (int) cur));
687   }
688
689   /* parse entities */
690   cur = cur->xmlChildrenNode;
691   while (cur != NULL) {
692     if (NODE_NAME (cur, type)) {
693       parseType (doc, cur);
694     } else if (NODE_NAME (cur, entity)) {
695       parseEntity (doc, cur);
696     } else if (NODE_NAME (cur, effect)) {
697       parseEffect (doc, cur);
698     } else if ((NODE_NAME (cur, comment))) {
699       /* comment */
700     } else {
701       fprintf (stderr, "wrong element \"%s\"\n", BAD_CAST cur->name);
702       exit (EXIT_FAILURE);
703     }
704     cur = cur->next;
705   }
706
707   module = NEW(module_t);
708   module -> id = mod_id;
709   module -> types = types;
710   module -> entities = entities;
711   module -> procs = procs;
712
713   types = NULL;
714   entities = NULL;
715   procs = NULL;
716
717   module -> next = modules;
718   modules = module;
719 }
720
721 /********************************************************************/
722
723 /*
724  * free additional structure
725  */
726 static
727 void freeArg (eff_t *arg)
728 {
729   VERBOSE_PRINT ((stdout, "free arg node \t0x%08x\n", (int) arg));
730   free(arg);
731   return;
732 }
733
734 static
735 void freeValref (eff_t *valref)
736 {
737   VERBOSE_PRINT ((stdout, "free valref node \t0x%08x\n", (int) valref));
738   free(valref);
739   return;
740 }
741
742 static
743 void freeSelect (eff_t *sel)
744 {
745   VERBOSE_PRINT ((stdout, "free select node \t0x%08x\n", (int) sel));
746   free(sel);
747   return;
748 }
749
750 static
751 void freeLoad (eff_t *load)
752 {
753   VERBOSE_PRINT ((stdout, "free load node \t0x%08x\n", (int) load));
754   free (load);
755   return;
756 }
757
758 static
759 void freeStore (eff_t *store)
760 {
761   VERBOSE_PRINT ((stdout, "free store node \t0x%08x\n", (int) store));
762   free (store);
763   return;
764 }
765
766 static
767 void freeAlloc (eff_t *alloc)
768 {
769   VERBOSE_PRINT ((stdout, "free alloc node \t0x%08x\n", (int) alloc));
770   free(alloc);
771   return;
772 }
773
774 static
775 void freeCall (eff_t *call)
776 {
777   VERBOSE_PRINT ((stdout, "free call node \t0x%08x\n", (int) call));
778   free(call -> effect.call.args);
779   free(call);
780   return;
781 }
782
783 static
784 void freeJoin (eff_t *join)
785 {
786   VERBOSE_PRINT ((stdout, "free join node \t0x%08x\n", (int) join));
787   free(join -> effect.join.ins);
788   free(join);
789   return;
790 }
791
792 static
793 void freeUnknown (eff_t *unknown)
794 {
795   VERBOSE_PRINT ((stdout, "free unknown node \t0x%08x\n", (int) unknown));
796   free(unknown);
797   return;
798 }
799
800 static
801 void freeReturn (eff_t *ret)
802 {
803   VERBOSE_PRINT ((stdout, "free ret node \t0x%08x\n", (int) ret));
804   free(ret);
805   return;
806 }
807
808 static
809 void freeRaise (eff_t *raise)
810 {
811   VERBOSE_PRINT ((stdout, "free raise node \t0x%08x\n", (int) raise));
812   free (raise);
813   return;
814 }
815
816
817 static
818 void freeProcEffs(proc_t *proc)
819 {
820   int i;
821   int num;
822
823   VERBOSE_PRINT ((stdout, "free effect for method \"%s\"\n",
824                   get_id_str(proc -> proc_ident)));
825
826   num = proc -> n_effs;
827   for(i = 0; i < num; i++) {
828     switch(proc -> effs[i] -> kind) {
829     case eff_arg:
830       freeArg(proc -> effs[i]);
831       break;
832     case eff_valref:
833       freeValref(proc -> effs[i]);
834       break;
835     case eff_select:
836       freeSelect(proc -> effs[i]);
837       break;
838     case eff_load:
839       freeLoad(proc -> effs[i]);
840       break;
841     case eff_store:
842       freeStore(proc -> effs[i]);
843       break;
844     case eff_alloc:
845       freeAlloc(proc -> effs[i]);
846       break;
847     case eff_call:
848       freeCall(proc -> effs[i]);
849       break;
850     case eff_unknown:
851       freeUnknown(proc -> effs[i]);
852       break;
853     case eff_join:
854       freeJoin(proc -> effs[i]);
855       break;
856     case eff_raise:
857       freeRaise(proc -> effs[i]);
858       break;
859     case eff_ret:
860       freeReturn(proc -> effs[i]);
861       break;
862     default:
863       assert(0 && "try to free an unknown effect");
864       break;
865     }
866   }
867   free(proc -> effs);
868   proc -> effs = NULL;
869 }
870
871 static
872 void freeModuleProcs(module_t *module)
873 {
874   proc_t *next_proc, *proc;
875
876   VERBOSE_PRINT ((stdout, "free procs for module \"%s\"\n",
877                   get_id_str(module -> id)));
878
879   proc = module -> procs;
880   while(proc) {
881     next_proc = proc -> next;
882     freeProcEffs(proc);
883     free(proc);
884     proc = next_proc;
885   }
886 }
887
888 static
889 void free_data(void)
890 {
891   module_t *module, *next_module;
892
893   module = modules;
894   while(module) {
895     freeModuleProcs(module);
896     next_module = module -> next;
897     free(module);
898     module = next_module;
899   }
900 }
901
902 /********************************************************************/
903
904 static
905 type_t *find_type_in_module(module_t *module, const ident *typeid)
906 {
907   type_t *type;
908
909   for(type = module -> types; type; type = type -> prev) {
910     VERBOSE_PRINT((stdout, "test typeid %s\n", get_id_str(type -> id)));
911     if(type -> id == typeid) {
912       VERBOSE_PRINT((stdout, "found\n"));
913       return(type);
914     }
915   }
916   VERBOSE_PRINT((stdout, "did not find type id %s\n", get_id_str(typeid)));
917   return(NULL);
918 }
919
920 /********************************************************************/
921
922 static void add_value_to_proc(proc_t *proc, eff_t *eff)
923 {
924   eff -> next = proc -> values;
925   proc -> values = eff;
926 }
927
928
929 eff_t *find_valueid_in_proc_effects(const ident *id, proc_t *proc)
930 {
931   eff_t *val;
932
933   val = proc -> values;
934   while(val) {
935     if(id == val -> id) {
936       return(val);
937     }
938     val = val -> next;
939   }
940   return(NULL);
941 }
942
943 static void create_abstract_return(ir_graph *irg, proc_t *proc, eff_t *eff)
944 {
945   ir_node *x;
946   eff_t *eff_res;
947
948   VERBOSE_PRINT((stdout, "create effect:return in %s\n",
949                  get_id_str(proc -> proc_ident)));
950   if(NO_ID == eff -> effect.ret.ret_id) {
951     /* return void */
952     x = new_Return (get_store(), 0, NULL);
953   }
954   else {
955     ir_node *in[1];
956
957     /* return one value */
958     eff_res = find_valueid_in_proc_effects(eff -> effect.ret.ret_id, proc);
959     assert(eff_res -> firmnode && "firm in effect not set");
960     in[0] = eff_res -> firmnode;
961     x = new_Return (get_store(), 1, in);
962   }
963   eff -> firmnode = x;
964
965   /* Now we generated all instructions for this block and all its predecessor
966    * blocks so we can mature it.  (There are not too much.) */
967   mature_immBlock (get_irg_current_block(irg));
968
969   /* This adds the in edge of the end block which originates at the return statement.
970    * The return node passes controlflow to the end block.  */
971   add_immBlock_pred (get_irg_end_block(irg), x);
972 }
973
974
975 static void create_abstract_arg(ir_graph *irg, proc_t *proc, eff_t *eff)
976 {
977   ir_node *arg;
978   entity *ent;
979   ir_mode *mode;
980   type *typ;
981   int num;
982
983   VERBOSE_PRINT((stdout, "create effect:arg %d in %s\n",
984                  eff -> effect.arg.num, get_id_str(proc -> proc_ident)));
985   ent = get_irg_entity(irg);
986   typ = get_entity_type(ent);
987
988   /* read argument eff -> effect.arg.num and place in values list */
989   num = get_method_n_params(typ);
990   assert((num >= eff -> effect.arg.num) && "number too big");
991   typ = get_method_param_type(typ, eff -> effect.arg.num);
992   mode = get_type_mode(typ);
993
994   arg = new_Proj(get_irg_args(irg), mode, eff -> effect.arg.num);
995   eff -> firmnode = arg;
996
997   add_value_to_proc(proc, eff);
998 }
999
1000
1001 static void create_abstract_load(ir_graph *irg, proc_t *proc, eff_t *eff)
1002 {
1003   ir_node *sel, *load;
1004   entity *ent;
1005   ir_mode *mode;
1006   eff_t *addr;
1007
1008   VERBOSE_PRINT((stdout, "create load in %s\n",
1009                  get_id_str(proc -> proc_ident)));
1010
1011   ent = eff -> effect.load.ent -> f_ent;
1012   VERBOSE_PRINT((stdout, "load from %s\n", get_entity_name(ent)));
1013
1014   addr = find_valueid_in_proc_effects(eff -> effect.load.ptrrefid, proc);
1015   assert(addr && "no address for load");
1016   /* if addr is Unknown, set propper mode */
1017   if(iro_Unknown == get_irn_opcode(addr -> firmnode)) {
1018     set_irn_mode(addr -> firmnode, mode_P);
1019   }
1020
1021   sel = new_simpleSel(get_store(), addr -> firmnode, ent);
1022   mode = get_type_mode(get_entity_type(ent));
1023   load = new_Load(get_store(), sel, mode);
1024   set_store(new_Proj(load, mode_M, 0));
1025   eff -> firmnode = new_Proj(load, mode, 2);
1026
1027   add_value_to_proc(proc, eff);
1028 }
1029
1030
1031 static void create_abstract_store(ir_graph *irg, proc_t *proc, eff_t *eff)
1032 {
1033   ir_node *sel, *store;
1034   entity *ent;
1035   eff_t *addr, *val;
1036
1037   VERBOSE_PRINT((stdout, "create store in %s\n",
1038                  get_id_str(proc -> proc_ident)));
1039
1040   ent = eff -> effect.store.ent -> f_ent;
1041   VERBOSE_PRINT((stdout, "store to %s\n", get_entity_name(ent)));
1042
1043   addr = find_valueid_in_proc_effects(eff -> effect.store.ptrrefid, proc);
1044   assert(addr && "no address for store");
1045   /* if addr is Unknown, set propper mode */
1046   if(iro_Unknown == get_irn_opcode(addr -> firmnode)) {
1047     set_irn_mode(addr -> firmnode, mode_P);
1048   }
1049
1050   val = find_valueid_in_proc_effects(eff -> effect.store.valrefid, proc);
1051   assert(val && "no address for store");
1052   /* if addr is Unknown, set propper mode */
1053   if(iro_Unknown == get_irn_opcode(val -> firmnode)) {
1054     set_irn_mode(val -> firmnode, get_type_mode(get_entity_type(ent)));
1055   }
1056
1057   sel = new_simpleSel(get_store(), addr -> firmnode, ent);
1058   store = new_Store(get_store(), sel, val -> firmnode);
1059   set_store(new_Proj(store, mode_M, 0));
1060   eff -> firmnode = store;
1061 }
1062
1063
1064 static void create_abstract_alloc(ir_graph *irg, proc_t *proc, eff_t *eff)
1065 {
1066   type *ftype;
1067   ir_node *alloc;
1068   type_t *xtype;
1069   symconst_symbol sym;
1070
1071   VERBOSE_PRINT((stdout, "create alloc in %s\n",
1072                  get_id_str(proc -> proc_ident)));
1073
1074   xtype = find_type_in_module(current_module, eff -> effect.alloc.tp_id);
1075   assert(xtype && "type not found");
1076   ftype = xtype -> f_tp;
1077
1078   sym.type_p = ftype;
1079   alloc = new_Alloc(get_store(), new_SymConst(sym, symconst_size), ftype,
1080                     heap_alloc);
1081   set_store(new_Proj(alloc, mode_M, 0));
1082   eff -> firmnode = new_Proj(alloc, mode_P, 2);
1083
1084   add_value_to_proc(proc, eff);
1085 }
1086
1087
1088 static void create_abstract_unknown(ir_graph *irg, proc_t *proc, eff_t *eff)
1089 {
1090   ir_node *unknown;
1091
1092   VERBOSE_PRINT((stdout, "create unknown in %s\n",
1093                  get_id_str(proc -> proc_ident)));
1094
1095   unknown = new_Unknown(mode_ANY);
1096   eff -> firmnode = unknown;
1097
1098   add_value_to_proc(proc, eff);
1099 }
1100
1101
1102 static void create_abstract_call(ir_graph *irg, proc_t *proc, eff_t *eff)
1103 {
1104   ir_node *sel, *call;
1105   entity *ent;
1106   eff_t *addr;
1107   ir_node **irns;
1108   int i, num;
1109   type *mtype;
1110
1111   VERBOSE_PRINT((stdout, "create call in %s\n",
1112                  get_id_str(proc -> proc_ident)));
1113
1114   ent = eff -> effect.call.ent -> f_ent;
1115   VERBOSE_PRINT((stdout, "call %s\n", get_entity_name(ent)));
1116
1117   addr = find_valueid_in_proc_effects(eff -> effect.call.valrefid, proc);
1118   assert(addr && "no address for load");
1119   /* if addr is Unknown, set propper mode */
1120   if(iro_Unknown == get_irn_opcode(addr -> firmnode)) {
1121     set_irn_mode(addr -> firmnode, mode_P);
1122   }
1123
1124   /* the address */
1125   sel = new_simpleSel(get_store(), addr -> firmnode, ent);
1126   /* mthod type */
1127   mtype = get_entity_type(ent);
1128   /* the args */
1129   num = eff -> effect.call.n_args;
1130   VERBOSE_PRINT((stdout, "number of args given: %d\n", num));
1131   VERBOSE_PRINT((stdout, "number of args expected: %d\n",
1132                  get_method_n_params(mtype)));
1133   irns = alloca(num * sizeof(ir_node*));
1134   for(i = 0; i < num; i++) {
1135     irns[i] = find_valueid_in_proc_effects(eff -> effect.call.args[i], proc)
1136       -> firmnode;
1137     if(iro_Unknown == get_irn_opcode(irns[i])) {
1138       set_irn_mode(irns[i], get_type_mode(get_method_param_type(mtype, i)));
1139     }
1140   }
1141   call = new_Call(get_store(), sel, num, irns, get_entity_type(ent));
1142   set_store(new_Proj(call, mode_M, 0));
1143   if(0 != get_method_n_ress(mtype)) {
1144     eff -> firmnode = new_Proj(call,
1145                                get_type_mode(get_method_res_type(mtype, 0)),
1146                                0);
1147     add_value_to_proc(proc, eff); /* result can be accessed */
1148   }
1149   else {
1150     eff -> firmnode = NULL; /* result can not be accessed */
1151   }
1152 }
1153
1154
1155 static void create_abstract_firm(module_t *module, proc_t *proc, entity *fent)
1156 {
1157   eff_t *eff;
1158   ir_graph *irg;
1159   int i, num;
1160
1161   /* test entity */
1162   assert(visibility_external_allocated == get_entity_visibility(fent)
1163          && peculiarity_existent == get_entity_peculiarity(fent)
1164          && "not an abstract entity");
1165   /* create irg in entity */
1166   irg = new_ir_graph(fent, 0);
1167
1168   VERBOSE_PRINT((stdout, "create effects for %s\n",
1169                  get_id_str(proc -> proc_ident)));
1170
1171   /* create effects in irg */
1172   num = proc -> n_effs;
1173   for(i = 0; i < num; i++) {
1174     eff = proc -> effs[i];
1175     VERBOSE_PRINT((stdout,
1176                    "create effect \"%s\"\n", effect_string[(int)eff -> kind]));
1177     switch(eff -> kind) {
1178     case eff_ret:
1179       create_abstract_return(irg, proc, eff);
1180       break;
1181     case eff_arg:
1182       create_abstract_arg(irg, proc, eff);
1183       break;
1184     case eff_load:
1185       create_abstract_load(irg, proc, eff);
1186       break;
1187     case eff_store:
1188       create_abstract_store(irg, proc, eff);
1189       break;
1190     case eff_unknown:
1191       create_abstract_unknown(irg, proc, eff);
1192       break;
1193     case eff_alloc:
1194       create_abstract_alloc(irg, proc, eff);
1195       break;
1196     case eff_call:
1197       create_abstract_call(irg, proc, eff);
1198       break;
1199     default:
1200       assert(0 && "effect not implemented");
1201       break;
1202     }
1203   }
1204
1205   /* close irg in entity */
1206   /* Now we can mature the end block as all it's predecessors are known. */
1207   mature_immBlock (get_irg_end_block(irg));
1208
1209   /* Verify the graph.  Finds some very bad errors in the graph. */
1210   VERBOSE_PRINT((stdout, "verify graph\n"));
1211   irg_vrfy(irg);
1212   VERBOSE_PRINT((stdout, "finalize construction\n"));
1213   finalize_cons (irg);
1214 }
1215
1216 /********************************************************************/
1217
1218 static void assign_firm_entity(module_t *module, entity_t *xmlent)
1219 {
1220   int i, num;
1221   type_t *typ;
1222   type *type;
1223   entity *ent;
1224
1225   VERBOSE_PRINT((stdout, "assign entity %s to typeid %s\n",
1226                  get_id_str(xmlent -> ent_ident),
1227                  get_id_str(xmlent -> owner)));
1228
1229   typ = find_type_in_module(module, xmlent -> owner);
1230   assert(typ && "class not found in module");
1231   type = typ -> f_tp;
1232   assert(is_class_type(type));
1233
1234   num = get_class_n_members(type);
1235   ent = NULL;
1236   for(i = 0; i < num; i++) {
1237     ent = get_class_member(type, i);
1238     VERBOSE_PRINT((stdout, "compare entity %s and %s\n",
1239                    get_id_str(xmlent -> ent_ident), get_entity_name(ent)));
1240
1241     if(get_entity_ident(ent) == xmlent -> ent_ident) {
1242       break;
1243     }
1244     ent = NULL;
1245   }
1246   assert(ent && "did not find a entity");
1247
1248   xmlent -> f_ent = ent;
1249 }
1250
1251 /********************************************************************/
1252 /* must be primitive type or class type */
1253 static void assign_firm_type(type_t *xmltype)
1254 {
1255   int i;
1256   type *typ = NULL;
1257   int num;
1258
1259   VERBOSE_PRINT((stdout, "assign firm type to type %s\n",
1260                  get_id_str(xmltype -> type_ident)));
1261
1262   /* is it global type? */
1263   typ = get_glob_type();
1264   if(xmltype -> type_ident == get_type_ident(typ)) {
1265     /* yes */
1266     xmltype -> f_tp = typ;
1267     VERBOSE_PRINT((stdout, "is global type %s\n", get_type_name(typ)));
1268   }
1269   else {
1270     num = get_irp_n_types();
1271     for(i = 0; i < num; i++) {
1272       typ = get_irp_type(i);
1273       VERBOSE_PRINT((stdout, "test type %s\n", get_type_name(typ)));
1274       if(xmltype -> type_ident == get_type_ident(typ)) {
1275         VERBOSE_PRINT((stdout, "found type %s\n", get_type_name(typ)));
1276         xmltype -> f_tp = typ;
1277         break;
1278       }
1279       typ = NULL;
1280     }
1281   }
1282   assert(typ && "did not find a type");
1283 }
1284
1285 /********************************************************************/
1286 static
1287 void create_abstract_proc_effect(module_t *module, proc_t *proc)
1288 {
1289   int i, num;
1290   type *class_typ = NULL;
1291   type_t *type;
1292   entity *fent;
1293
1294   /* find the class of a procedure */
1295   VERBOSE_PRINT((stdout, "do find typeid %s\n", get_id_str(proc -> typeid)));
1296   type = find_type_in_module(module, proc -> typeid);
1297   assert(type && "class not found in module");
1298
1299   class_typ = get_glob_type();
1300   VERBOSE_PRINT((stdout, "test type %s\n", get_type_name(class_typ)));
1301   if(type -> type_ident != get_type_ident(class_typ)) {
1302     /* find module as class */
1303     num = get_irp_n_types();
1304     for(i = 0; i < num; i++) {
1305       class_typ = get_irp_type(i);
1306       VERBOSE_PRINT((stdout, "test type %s\n", get_type_name(class_typ)));
1307       if(is_class_type(class_typ)
1308          && (type -> type_ident == get_type_ident(class_typ))) {
1309         /* found class type */
1310         VERBOSE_PRINT((stdout, "found type %s\n", get_type_name(class_typ)));
1311         break;
1312       }
1313       class_typ = NULL;
1314     }
1315   }
1316   else {
1317     VERBOSE_PRINT((stdout, "found global type %s\n", get_type_name(class_typ)));
1318   }
1319   assert(class_typ && "type not found");
1320   assert(is_class_type(class_typ) && "is not a class type");
1321   type -> f_tp = class_typ;
1322
1323   /* find entity for procedure in class */
1324   VERBOSE_PRINT((stdout, "find method %s\n",
1325                  get_id_str(proc -> proc_ident)));
1326
1327   num = get_class_n_members(class_typ);
1328   fent = NULL;
1329   for(i = 0; i < num; i++) {
1330     fent = get_class_member(class_typ, i);
1331     VERBOSE_PRINT((stdout, "test proc %s\n", get_entity_name(fent)));
1332     if(proc -> proc_ident == get_entity_ident(fent)) {
1333       VERBOSE_PRINT((stdout, "found proc %s\n",
1334                      get_id_str(proc -> proc_ident)));
1335       /* @@@ TODO check args types - not in xml yet */
1336       /* create Firm stuff */
1337       create_abstract_firm(module, proc, fent);
1338       break;
1339     }
1340     else {
1341       fent = NULL;
1342     }
1343   }
1344   assert(fent && "procedure not found in class");
1345 }
1346
1347 static
1348 void create_abstract_module(module_t *module)
1349 {
1350   proc_t *proc;
1351   type_t *type;
1352   entity_t *ent;
1353
1354   VERBOSE_PRINT((stdout, "create an abstraction for module %s\n",
1355                  get_id_str(module -> id)));
1356
1357   VERBOSE_PRINT((stdout, "--handle types for module\n"));
1358   for(type = module -> types; type; type = type -> prev) {
1359     assign_firm_type(type);
1360   }
1361
1362   VERBOSE_PRINT((stdout, "--handle entities for module\n"));
1363   /* @@@ TODO */
1364   for(ent = module -> entities; ent; ent = ent -> prev) {
1365     assign_firm_entity(module, ent);
1366   }
1367
1368   VERBOSE_PRINT((stdout, "--handle procs for module\n"));
1369   for(proc = module -> procs; proc; proc = proc -> next) {
1370     create_abstract_proc_effect(module, proc);
1371   }
1372 }
1373
1374
1375 void create_abstraction(const char *filename)
1376 {
1377   module_t *module;
1378
1379   /* read and parse XML file */
1380   read_extern(filename);
1381
1382   /* finished reading and parsing here */
1383   /* build FIRM graphs */
1384   module = modules;
1385   while(module) {
1386     current_module = module;
1387     create_abstract_module(module);
1388     module = module -> next;
1389   }
1390   current_module = NULL;
1391
1392   /* free data structures */
1393   free_data();
1394 }
1395
1396 /********************************************************************/
1397
1398 \f
1399 /*
1400  * $Log$
1401  * Revision 1.8  2004/10/22 13:13:27  boesler
1402  * replaced char* by idents, minor fix in Firm codegen for call
1403  *
1404  * Revision 1.7  2004/10/21 15:31:55  boesler
1405  * added lots of stuff:
1406  * - build abstract syntax trees
1407  * - build Firm graphs for many effects, still todos
1408  *
1409  * Revision 1.5  2004/10/18 12:48:20  liekweg
1410  * avoid warning
1411  *
1412  * Revision 1.4  2004/10/14 11:31:53  liekweg
1413  * ...
1414  *
1415  * Revision 1.3  2004/10/13 13:36:28  rubino
1416  * fix for strdup
1417  *
1418  * Revision 1.2  2004/10/11 15:56:09  liekweg
1419  * Cleanup, comments ...
1420  * Added init func --flo
1421  *
1422  * Revision 1.1  2004/10/11 09:31:06  liekweg
1423  * First Import of XML reading procs --flo
1424  *
1425  */