blob: f6a5919dbcd05f08b032f45a830fbbd2bd088c6d [file] [log] [blame]
sewardjec6ad592004-06-20 12:26:53 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (storage.c) is ---*/
5/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
7/*---------------------------------------------------------------*/
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <assert.h>
12#include "storage.h"
13#include "storage_private.h"
14
15
16static Cell heap[N_HEAP_CELLS];
17static Int heap_used = 1; /* cell==0 is not allowed */
18
19static Char* tag_name[N_TAGS];
20static UChar tag_arity[N_TAGS]; /* 0xFF indicates unregistered. */
21
22static Bool init_done = False;
23
24#define IS_VALID_CELL(cc) ((cc) < 0 && (cc) > -heap_used)
25#define IS_VALID_TAG(tt) ((tt) > 0 && (tt) < N_TAGS)
26
27
28void panic ( Char* who )
29{
30 fprintf(stderr, "panic: %s\n", who);
31 exit(1);
32}
33
34
35/* Initialise the storage subsystem. */
36void storage_init ( void )
37{
38 Int i;
39 assert(!init_done);
40 init_done = True;
41 for (i = 0; i < N_TAGS; i++) {
42 tag_name[i] = NULL;
43 tag_arity[i] = 0xFF; /* unregistered */
44 }
45 heap_used = 1;
46 storage_register_tag ( TagCONS, 2, "cons" );
47 storage_register_tag ( TagPAIR, 2, "pair" );
48 storage_register_tag ( TagTRIPLE, 3, "triple" );
49 storage_register_tag ( TagWord8, 1, "word8" );
50 storage_register_tag ( TagWord16, 1, "word16" );
51 storage_register_tag ( TagWord32, 1, "word32" );
52 storage_register_tag ( TagWord64, 1, "word64" );
53}
54
55void storage_done ( void )
56{
57 printf ("storage_done: used %d cells\n", heap_used-1 );
58}
59
60void storage_register_tag ( Tag tag, Int arity, Char* name )
61{
62 assert(init_done);
63 assert(IS_VALID_TAG(tag));
64 assert(tag_arity[tag] == 0xFF); /* check not already registered */
65 assert(name != NULL);
66 assert(arity >= 0 && arity <= 5);
67 tag_name[tag] = name;
68 tag_arity[tag] = arity;
69}
70
71
72Tag getTag ( Cell c )
73{
74 Tag t;
75 assert(IS_VALID_CELL(c));
76 t = heap[-c];
77 assert(IS_VALID_TAG(t));
78 assert(tag_arity[t] != 0xFF);
79 return t;
80}
81
82/* ------------------ Construct/query for Size = 0 --------------------- */
83
84Cell tuple0 ( Tag t )
85{
86 assert(init_done);
87 assert(heap_used <= N_HEAP_CELLS-1);
88 assert(IS_VALID_TAG(t));
89 assert(tag_arity[t] == 0);
90 heap[heap_used] = t;
91 heap_used += 1;
92 return -(heap_used - 1);
93}
94
95
96/* ------------------ Construct/query for Size = 1 --------------------- */
97
98Cell tuple1 ( Tag t, Cell x )
99{
100 assert(init_done);
101 assert(heap_used <= N_HEAP_CELLS-2);
102 assert(IS_VALID_TAG(t));
103 assert(tag_arity[t] == 1);
104 heap[heap_used] = t;
105 heap[heap_used+1] = x;
106 heap_used += 2;
107 return -(heap_used - 2);
108}
109
110Cell sel11 ( Cell tup )
111{
112 Tag t;
113 assert(IS_VALID_CELL(tup));
114 t = heap[-tup];
115 assert(IS_VALID_TAG(t));
116 assert(tag_arity[t] == 1);
117 return heap[-tup+1];
118}
119
120/* ------------------ Construct/query for Size = 2 --------------------- */
121
122Cell tuple2 ( Tag t, Cell x, Cell y )
123{
124 assert(init_done);
125 assert(heap_used <= N_HEAP_CELLS-3);
126 assert(IS_VALID_TAG(t));
127 assert(tag_arity[t] == 2);
128 heap[heap_used] = t;
129 heap[heap_used+1] = x;
130 heap[heap_used+2] = y;
131 heap_used += 3;
132 return -(heap_used - 3);
133}
134
135Cell sel21 ( Cell tup )
136{
137 Tag t;
138 assert(IS_VALID_CELL(tup));
139 t = heap[-tup];
140 assert(IS_VALID_TAG(t));
141 assert(tag_arity[t] == 2);
142 return heap[-tup+1];
143}
144
145Cell sel22 ( Cell tup )
146{
147 Tag t;
148 assert(IS_VALID_CELL(tup));
149 t = heap[-tup];
150 assert(IS_VALID_TAG(t));
151 assert(tag_arity[t] == 2);
152 return heap[-tup+2];
153}
154
155
156/* ------------------ Construct/query for Size = 3 --------------------- */
157
158Cell tuple3 ( Tag t, Cell x, Cell y, Cell z )
159{
160 assert(init_done);
161 assert(heap_used <= N_HEAP_CELLS-4);
162 assert(IS_VALID_TAG(t));
163 assert(tag_arity[t] == 3);
164 heap[heap_used] = t;
165 heap[heap_used+1] = x;
166 heap[heap_used+2] = y;
167 heap[heap_used+3] = z;
168 heap_used += 4;
169 return -(heap_used - 4);
170}
171
172Cell sel31 ( Cell tup )
173{
174 Tag t;
175 assert(IS_VALID_CELL(tup));
176 t = heap[-tup];
177 assert(IS_VALID_TAG(t));
178 assert(tag_arity[t] == 3);
179 return heap[-tup+1];
180}
181
182Cell sel32 ( Cell tup )
183{
184 Tag t;
185 assert(IS_VALID_CELL(tup));
186 t = heap[-tup];
187 assert(IS_VALID_TAG(t));
188 assert(tag_arity[t] == 3);
189 return heap[-tup+2];
190}
191
192Cell sel33 ( Cell tup )
193{
194 Tag t;
195 assert(IS_VALID_CELL(tup));
196 t = heap[-tup];
197 assert(IS_VALID_TAG(t));
198 assert(tag_arity[t] == 3);
199 return heap[-tup+3];
200}
201
202
203/* ------------------ Helpers for lists --------------------- */
204
205Cell cons ( Cell hd, Cell tl )
206{
207 return tuple2(TagCONS, hd, tl);
208}
209
210Cell head ( Cell list )
211{
212 if (isNil(list)) panic("head(NIL)");
213 if (getTag(list) != TagCONS) panic("head(not-a-list)");
214 return sel21(list);
215}
216
217Cell tail ( Cell list )
218{
219 if (isNil(list)) panic("tail(NIL)");
220 if (getTag(list) != TagCONS) panic("tail(not-a-list)");
221 return sel22(list);
222}
223
224
225/* ------------------ Helpers for Word* --------------------- */
226
227Cell mkWord8 ( UInt w8 )
228{
229 return tuple1 ( TagWord8, w8 & 0xFF );
230}
231
232Cell mkWord16 ( UInt w16 )
233{
234 return tuple1 ( TagWord16, w16 & 0xFFFF );
235}
236
237Cell mkWord32 ( UInt w32 )
238{
239 return tuple1 ( TagWord32, w32 );
240}
241
242Cell mkWord64 ( ULong w64 )
243{
244 UInt hi = (UInt)(w64 >> 32);
245 UInt lo = (UInt)(w64 & 0x00000000FFFFFFFFLL);
246 return tuple2 ( TagWord64, hi, lo );
247}
248
249UInt getWord8 ( Cell c )
250{
251 assert(getTag(c) == TagWord8 );
252 return sel11(c);
253}
254
255UInt getWord16 ( Cell c )
256{
257 assert(getTag(c) == TagWord16 );
258 return sel11(c);
259}
260
261UInt getWord32 ( Cell c )
262{
263 assert(getTag(c) == TagWord32 );
264 return sel11(c);
265}
266
267ULong getWord64 ( Cell c )
268{
269 UInt hi, lo;
270 assert(getTag(c) == TagWord64 );
271 hi = (UInt)sel21(c);
272 lo = (UInt)sel22(c);
273 return (((ULong)hi) << 32) | ((ULong)lo);
274}
275