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