forked from parrot/parrot
/
packout.c
325 lines (255 loc) · 8.64 KB
/
packout.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
/*
** packout.c
**
** Functions for writing out packfiles.
**
** Copyright (C) 2001-2002 Gregor N. Purdy. All rights reserved.
** This program is free software. It is subject to the same
** license as Parrot itself.
**
** $Id$
** History:
** Rework by Melvin; new bytecode format, make bytecode portable.
** (Do endian conversion and wordsize transforms on the fly.)
*/
#include "parrot/parrot.h"
#include "parrot/packfile.h"
/***************************************
Determine the size of the buffer needed in order to pack the PackFile into a
contiguous region of memory.
***************************************/
opcode_t
PackFile_pack_size(struct PackFile *self)
{
opcode_t header_size;
opcode_t magic_size;
opcode_t oct_size; /* opcode_type */
opcode_t segment_length_size;
opcode_t fixup_table_size;
opcode_t const_table_size;
header_size = PACKFILE_HEADER_BYTES;
magic_size = sizeof(opcode_t);
oct_size = sizeof(opcode_t);
segment_length_size = sizeof(opcode_t);
#if TRACE_PACKFILE
printf("getting fixup table size...\n");
#endif
fixup_table_size = PackFile_FixupTable_pack_size(self->fixup_table);
#if TRACE_PACKFILE
printf(" ... it is %ld\n", fixup_table_size);
#endif
#if TRACE_PACKFILE
printf("getting const table size...\n");
#endif
const_table_size = PackFile_ConstTable_pack_size(self->const_table);
#if TRACE_PACKFILE
printf(" ... it is %ld\n", const_table_size);
#endif
return header_size + magic_size + oct_size
+ segment_length_size + fixup_table_size
+ segment_length_size + const_table_size
+ segment_length_size + self->byte_code_size;
}
/***************************************
Pack the PackFile into a contiguous region of memory. NOTE: The memory block
had better have at least the amount of memory indicated by
PackFile_pack_size()!
***************************************/
void
PackFile_pack(struct PackFile *self, opcode_t *packed)
{
opcode_t *cursor = packed;
opcode_t fixup_table_size =
PackFile_FixupTable_pack_size(self->fixup_table);
opcode_t const_table_size =
PackFile_ConstTable_pack_size(self->const_table);
self->header->wordsize = sizeof(opcode_t);
self->header->byteorder = PARROT_BIGENDIAN;
self->header->minor = PARROT_MINOR_VERSION;
self->header->major = PARROT_MAJOR_VERSION;
self->header->flags = 0;
self->header->floattype = 0;
/* Pack the header */
mem_sys_memcopy(cursor, self->header, PACKFILE_HEADER_BYTES);
cursor += PACKFILE_HEADER_BYTES / sizeof(opcode_t);
/* Pack the magic */
*cursor++ = PARROT_MAGIC;
/* Pack opcode type */
*cursor++ = OPCODE_TYPE_PERL;
/* Pack the fixup table size, followed by the packed fixup table */
*cursor++ = fixup_table_size;
PackFile_FixupTable_pack(self->fixup_table, cursor);
/* Sizes are in bytes */
cursor += fixup_table_size / sizeof(opcode_t);
/* Pack the constant table size, followed by the packed constant table */
*cursor++ = const_table_size;
PackFile_ConstTable_pack(self, self->const_table, cursor);
/* Sizes are in bytes */
cursor += const_table_size / sizeof(opcode_t);
/* Pack the byte code size, followed by the byte code */
*cursor++ = self->byte_code_size;
if (self->byte_code_size) {
mem_sys_memcopy(cursor, self->byte_code, self->byte_code_size);
}
return;
}
/***************************************
Determine the size of the buffer needed in order to pack the fixup
segment into a contiguous region of memory.
***************************************/
opcode_t
PackFile_FixupTable_pack_size(struct PackFile_FixupTable *self)
{
UNUSED(self);
return 0;
}
/***************************************
Pack the PackFile FixupTable into a contiguous region of memory.
NOTE: The memory block had better have at least the amount of memory
indicated by PackFile_FixupTable_pack_size()!
***************************************/
void
PackFile_FixupTable_pack(struct PackFile_FixupTable *self, opcode_t *packed)
{
UNUSED(self);
UNUSED(packed);
return;
}
/***************************************
Determine the size of the buffer needed in order to pack the PackFile
constant table into a contiguous region of memory.
***************************************/
opcode_t
PackFile_ConstTable_pack_size(struct PackFile_ConstTable *self)
{
opcode_t i;
opcode_t size = 0;
if (!self) {
fprintf(stderr, "PackFile_ConstTable_size: self == NULL!\n");
return -1;
}
for (i = 0; i < self->const_count; i++) {
size += PackFile_Constant_pack_size(self->constants[i]);
}
return sizeof(opcode_t) + size;
}
/***************************************
Pack the PackFile ConstTable into a contiguous region of memory.
NOTE: The memory block had better have at least the amount of memory
indicated by PackFile_ConstTable_pack_size()!
***************************************/
void
PackFile_ConstTable_pack(struct PackFile *packfile,
struct PackFile_ConstTable *self, opcode_t *packed)
{
opcode_t *cursor;
opcode_t i;
if (!self) {
fprintf(stderr, "PackFile_ConstTable_pack: self == NULL!\n");
return;
}
cursor = packed;
*cursor = self->const_count;
cursor++;
for (i = 0; i < self->const_count; i++) {
PackFile_Constant_pack(self->constants[i], cursor);
cursor +=
PackFile_Constant_pack_size(self->constants[i]) / sizeof(opcode_t);
}
return;
}
/***************************************
Pack a PackFile Constant into a contiguous region of memory. NOTE: The memory
block had better have at least the amount of memory indicated by
PackFile_Constant_pack_size()!
The data is zero-padded to an opcode_t-boundary, so pad bytes may be added.
(Note this padding is not yet implemented for FLOATVALs.)
***************************************/
void
PackFile_Constant_pack(struct PackFile_Constant *self, opcode_t *packed)
{
opcode_t *cursor;
char *charcursor;
size_t i;
opcode_t padded_size;
opcode_t packed_size;
if (!self) {
/* TODO: OK to be silent here? */
return;
}
cursor = packed;
*cursor++ = self->type;
switch (self->type) {
case PFC_NONE:
*cursor++ = 0;
/* TODO: OK to be silent here? */
break;
case PFC_NUMBER:
*cursor++ = sizeof(FLOATVAL);
/* XXX Use memcpy() to avoid alignment issues.
* Also, do we need to pad things out to an opcode_t boundary?
* Consider gcc/x86, with opcode_t = (long long) and
* FLOATVAL = (long double):
* sizeof(long long) = 8
* sizeof(long double) = 12
*/
mem_sys_memcopy(cursor, &self->number, sizeof(FLOATVAL));
cursor += sizeof(FLOATVAL) / sizeof(opcode_t); /* XXX */
/* XXX cursor is possibly wrong now (because of alignment
* issues) but isn't returned from this function anyway!
*/
break;
case PFC_STRING:
padded_size = self->string->bufused;
if (padded_size % sizeof(opcode_t)) {
padded_size += sizeof(opcode_t) - (padded_size % sizeof(opcode_t));
}
/* Include space for flags, encoding, type, and size fields. */
packed_size = 4 * sizeof(opcode_t) + padded_size;
*cursor++ = packed_size;
*cursor++ = self->string->flags;
*cursor++ = self->string->encoding->index;
*cursor++ = self->string->type->index;
*cursor++ = self->string->bufused;
/* Switch to char * since rest of string is addressed by
* characters to ensure padding. */
charcursor = (char *)cursor;
if (self->string->strstart) {
mem_sys_memcopy(charcursor, self->string->strstart,
self->string->bufused);
charcursor += self->string->bufused;
if (self->string->bufused % sizeof(opcode_t)) {
for (i = 0;
i <
(sizeof(opcode_t) -
(self->string->bufused % sizeof(opcode_t))); i++) {
charcursor[i] = 0;
}
}
}
/* If cursor is needed below, uncomment the following and
* ignore the gcc -Wcast-align warning. charcursor is
* guaranteed to be aligned correctly by the padding logic
* above.
* cursor = (opcode_t *) charcursor;
*/
break;
default:
/* TODO: OK to be silent here? */
break;
}
return;
}
/*
=back
=cut
*/
/*
* Local variables:
* c-indentation-style: bsd
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/