Initial revision
[cacao.git] / comp / stack.c
1 /***************************** alpha/gen.c *************************************
2
3         Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
4
5         See file COPYRIGHT for information on usage and disclaimer of warranties
6
7         behandeln des Java-Stacks
8
9         Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
10
11         Last Change: 1996/11/14
12
13 *******************************************************************************/
14
15
16 static stackinfo *tos;       /* Top of Stack */
17
18
19
20 /********************* Verwaltungsfunktionen *********************************/
21
22 static void stack_init() { tos = NULL; }
23
24 static stackinfo *stack_get () { return tos; }
25
26 static void stack_restore (stackinfo *s)  { tos = s; }
27
28 static bool stack_isempty () { return tos == NULL; }
29
30
31
32 /********************** Funktion: stack_topslots ******************************
33
34         liefert die Anzahl der JavaVM-slots, die die oberste Pseudovariable am
35         Stack belegt (entweder 2 bei LONG und DOUBLE, oder 1 sonst)
36
37 ******************************************************************************/
38
39 static u2 stack_topslots ()
40 {
41         u2 t;
42         if (!tos) panic ("Stack is empty on attempt to determine top slots");
43
44         t = var_type (tos->var);
45         return ( (t==TYPE_LONG) || (t==TYPE_DOUBLE) ) ? 2 : 1;
46 }
47
48
49 /********************* Funktion: stack_push ***********************************
50
51         erzeugt eine neues Pseudoregister eines gew"unschten Typs und gibt
52         es oben auf den Stack.  
53         Ausserdem liefert die Funktion den Zeiger auf dieses Pseudoregister
54         
55 ******************************************************************************/
56
57 static varinfo *stack_push (u2 type)
58 {
59         stackinfo *s = DNEW (stackinfo);
60
61         s -> prev = tos;
62         s -> var = var_create (type);
63
64         tos = s;
65         return s -> var;
66 }
67
68
69 /********************** Funktion: stack_repush ********************************
70
71         Gibt ein bereits vorhandenen Pseudoregister auf den Stack
72         
73 ******************************************************************************/
74
75 static void stack_repush (varinfo *v) 
76 {
77         stackinfo *s = DNEW (stackinfo);
78
79         s -> prev = tos;
80         s -> var = v;
81
82         tos = s;
83 }
84
85
86 /********************** Funktion: stack_pop ***********************************
87
88         nimmt das oberste Pseudoregister vom Stack, dabei wird aber 
89         "uberpr"uft, ob der Typ stimmt.
90
91 ******************************************************************************/
92
93 static varinfo *stack_pop (u2 type)
94 {
95         varinfo *v;
96         
97         if (!tos) panic ("Stack is empty on attempt to pop");
98
99         v = tos -> var;
100         tos = tos -> prev;
101
102         if (var_type (v) != type) panic ("Popped invalid element from stack");
103         return v;
104 }
105
106
107 /********************* Funktion: stack_popany ********************************
108
109         nimmt das oberste Pseudoregister vom stack, ohne Typ"uberpr"ufung
110         durchzuf"uhren, wobei aber zumindest die Anzahl der notwendigen
111         Slots "ubereinstimmen muss.
112
113 ******************************************************************************/
114
115 static varinfo *stack_popany (u2 slots)
116 {
117         varinfo *v;
118         
119         if (!tos) panic ("Stack is empty on attempt to pop");
120         if (slots != stack_topslots() ) 
121                 panic ("Pop would tear LONG/DOUBLE-Datatype apart");
122
123         v = tos -> var;
124         tos = tos -> prev;
125
126         return v;
127 }
128
129
130
131 /********************** Funktion: stack_popmany *******************************
132
133         nimmt vom Stack soviele Pseudoregister, dass die Anzahl der von
134         ihnen belegten Slots die gew"unschte Menge ergeben.
135         Zeiger auf dieses Pseudoregister werden im Array vars gespeichert, und
136         deren tats"achliche Anzahl als Funktionswert zur"uckgeliefert.
137         (Haupts"achlich f"ur die Typneutralen DUP/POP.. Operationen)
138
139 ******************************************************************************/
140
141 static u2 stack_popmany (varid *vars, u2 slots)
142 {
143         u2 ts;
144         u2 varcount=0;
145         
146         while (slots>0) {
147                 ts=stack_topslots();
148                 if (ts > slots) panic ("POP would tear LONG/DOUBLE-Datatype apart");
149                 vars[(varcount)++] = stack_popany(ts);
150                 slots -= ts;                            
151                 }
152         return varcount;
153 }
154
155
156 /********************** Funktion: stack_pushmany ******************************
157
158         Gibt eine Anzahl von Pseudoregister auf den Stack.
159
160 ******************************************************************************/
161
162 static void stack_repushmany (u2 varcount, varid *vars)
163 {
164         u2 i;
165         for (i=0; i<varcount; i++) stack_repush(vars[(varcount-1)-i]);
166 }
167
168
169 /***************** Funktion: stack_addjoincode ********************************
170
171         erzeugt die passenden MOVE-Commandos, sodass alle Pseudoregisterinhalte
172         eines Stacks auf die Pseudoregister eines anderen Stacks kopiert
173         werden.
174         Dann wird der Zielstack als neuer aktueller Stack verwendet.
175         (F"ur allem f"ur Verzweigungs- und Sprungbefehle)
176         
177 *******************************************************************************/ 
178
179 static void stack_jointail (stackinfo *now, stackinfo *then)
180 {
181         varinfo *v1,*v2;
182         u2 t;
183
184         if (now==then) return;
185         if ( (now==NULL) || (then==NULL) ) 
186                 panic ("Stacks of different length on join");
187
188         v1 = now->var;
189         v2 = then->var;
190         if (v1 != v2) {
191                 t = var_type (v1);
192                 if (t != var_type (v2)) 
193                     panic ("Mismatching stack types on join of control flow");
194
195                 pcmd_move_n_drop (t, v1,v2);
196         }
197
198         stack_jointail (now -> prev, then -> prev);
199         return;
200 }
201
202 static void stack_addjoincode (stackinfo *targetstack)
203 {
204         stack_jointail (tos, targetstack);
205         tos = targetstack;
206 }       
207
208
209 /******************* Funktion: stack_makesaved ********************************
210
211         Kennzeichnet alle am Stack befindlichen Pseudoregister als
212         zu sichernde Register.
213
214 *******************************************************************************/
215
216 static void stack_makesaved ()
217 {
218         stackinfo *s = tos;
219         while (s) {
220                 var_makesaved (s->var);
221                 s = s->prev;
222                 }
223 }
224
225
226 /******************* Funktion: stack_display **********************************
227
228         Gibt den Inhalt des Stacks aus (also die Pseudoregister, die am 
229         Stack liegen)
230         (Nur zu Debug-Zwecken)
231         
232 ******************************************************************************/
233
234 static void stack_display (stackinfo *s)
235 {
236         if (s) {
237                 stack_display (s->prev);
238                 var_display (s->var);
239                 }
240 }
241