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