~dexter/parrot-pkg/maverick

« back to all changes in this revision

Viewing changes to compilers/pirc/src/pircompiler.c

  • Committer: Piotr Roszatycki
  • Date: 2011-01-11 14:34:28 UTC
  • mfrom: (1.1.13 upstream)
  • Revision ID: piotr.roszatycki@gmail.com-20110111143428-s7pa7qz38m61o4tw
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * $Id: pircompiler.c 45130 2010-03-23 14:32:56Z petdance $
3
 
 * Copyright (C) 2007-2009, Parrot Foundation.
4
 
 */
5
 
 
6
 
#include <stdlib.h>
7
 
#include <stdio.h>
8
 
#include <string.h>
9
 
#include <stdarg.h>
10
 
 
11
 
#include "pircompiler.h"
12
 
#include "parrot/parrot.h"
13
 
#include "piryy.h"
14
 
#include "pirmacro.h"
15
 
#include "pirregalloc.h"
16
 
#include "pirerr.h"
17
 
 
18
 
/* HEADERIZER HFILE: compilers/pirc/src/pircompiler.h */
19
 
 
20
 
/* HEADERIZER BEGIN: static */
21
 
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
22
 
 
23
 
PARROT_WARN_UNUSED_RESULT
24
 
PARROT_CAN_RETURN_NULL
25
 
static char const * find_string(
26
 
    ARGIN(lexer_state * const lexer),
27
 
    ARGIN(char const * const str))
28
 
        __attribute__nonnull__(1)
29
 
        __attribute__nonnull__(2);
30
 
 
31
 
PARROT_MALLOC
32
 
PARROT_CANNOT_RETURN_NULL
33
 
PARROT_WARN_UNUSED_RESULT
34
 
static allocated_mem_ptrs * new_mem_ptrs_block(void);
35
 
 
36
 
static void register_ptr(ARGMOD(lexer_state *lexer), ARGIN(void *ptr))
37
 
        __attribute__nonnull__(1)
38
 
        __attribute__nonnull__(2)
39
 
        FUNC_MODIFIES(*lexer);
40
 
 
41
 
static void store_string(
42
 
    ARGIN(lexer_state * const lexer),
43
 
    ARGIN(char const * const str))
44
 
        __attribute__nonnull__(1)
45
 
        __attribute__nonnull__(2);
46
 
 
47
 
#define ASSERT_ARGS_find_string __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
48
 
       PARROT_ASSERT_ARG(lexer) \
49
 
    , PARROT_ASSERT_ARG(str))
50
 
#define ASSERT_ARGS_new_mem_ptrs_block __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
51
 
#define ASSERT_ARGS_register_ptr __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
52
 
       PARROT_ASSERT_ARG(lexer) \
53
 
    , PARROT_ASSERT_ARG(ptr))
54
 
#define ASSERT_ARGS_store_string __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
55
 
       PARROT_ASSERT_ARG(lexer) \
56
 
    , PARROT_ASSERT_ARG(str))
57
 
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
58
 
/* HEADERIZER END: static */
59
 
 
60
 
/* XXX count memory, so we can check out mem. savings of string reuse
61
 
 * Only temporarily used, so no need to "fix" this.
62
 
 */
63
 
static int totalmem = 0;
64
 
 
65
 
 
66
 
 
67
 
/*
68
 
 
69
 
=over 4
70
 
 
71
 
=item C<static allocated_mem_ptrs * new_mem_ptrs_block(void)>
72
 
 
73
 
Create a new C<allocated_mem_ptrs> block; all pointers to allocated memory
74
 
within pirc are stored in such blocks. One block has space for a number of
75
 
pointers; if the block is full, a new block must be created and linked into
76
 
the list of blocks.
77
 
 
78
 
=cut
79
 
 
80
 
*/
81
 
PARROT_MALLOC
82
 
PARROT_CANNOT_RETURN_NULL
83
 
PARROT_WARN_UNUSED_RESULT
84
 
static allocated_mem_ptrs *
85
 
new_mem_ptrs_block(void)
86
 
{
87
 
    ASSERT_ARGS(new_mem_ptrs_block)
88
 
    return mem_allocate_zeroed_typed(allocated_mem_ptrs);
89
 
}
90
 
 
91
 
/*
92
 
 
93
 
=item C<static void register_ptr(lexer_state *lexer, void *ptr)>
94
 
 
95
 
Store the pointer C<ptr> in a datastructure; whenever C<release_resources()>
96
 
is invoked, C<ptr> will be freed through C<mem_sys_free()>.
97
 
 
98
 
=cut
99
 
 
100
 
*/
101
 
static void
102
 
register_ptr(ARGMOD(lexer_state *lexer), ARGIN(void *ptr))
103
 
{
104
 
    ASSERT_ARGS(register_ptr)
105
 
    allocated_mem_ptrs *ptrs = lexer->mem_allocations;
106
 
 
107
 
    PARROT_ASSERT(ptrs);
108
 
 
109
 
    if (ptrs->allocs_in_this_block == NUM_MEM_ALLOCS_PER_BLOCK) {
110
 
        allocated_mem_ptrs * const newblock = new_mem_ptrs_block();
111
 
        newblock->next               = ptrs;
112
 
        lexer->mem_allocations       = newblock;
113
 
        ptrs                         = newblock;
114
 
    }
115
 
 
116
 
    /* store the pointer in the current block */
117
 
    ptrs->ptrs[ptrs->allocs_in_this_block++] = ptr;
118
 
}
119
 
 
120
 
/*
121
 
 
122
 
=item C<void * pir_mem_allocate_zeroed(lexer_state *lexer, size_t numbytes)>
123
 
 
124
 
Memory allocation function for all PIR internal functions. Memory is allocated
125
 
through Parrot's allocation functions, but the pointer to the allocated memory
126
 
is stored in a data structure; this way, freeing all memory can be done by just
127
 
iterating over these pointers and freeing them.
128
 
 
129
 
Memory allocated through this function is all set to zero.
130
 
 
131
 
=cut
132
 
 
133
 
*/
134
 
PARROT_MALLOC
135
 
PARROT_WARN_UNUSED_RESULT
136
 
PARROT_CANNOT_RETURN_NULL
137
 
void *
138
 
pir_mem_allocate_zeroed(ARGMOD(lexer_state *lexer), size_t numbytes)
139
 
{
140
 
    void * const ptr = mem_sys_allocate_zeroed(numbytes);
141
 
 
142
 
    totalmem += numbytes;
143
 
 
144
 
    register_ptr(lexer, ptr);
145
 
    return ptr;
146
 
}
147
 
 
148
 
/*
149
 
 
150
 
=item C<void * pir_mem_allocate(lexer_state * const lexer, size_t numbytes)>
151
 
 
152
 
See C<pir_mem_allocate_zeroed()>. Memory is C<not> guaranteed to be zeroed.
153
 
(It might, it might not, depending on what your system finds appropriate.
154
 
Don't count on it anyway.)
155
 
 
156
 
=cut
157
 
 
158
 
*/
159
 
PARROT_MALLOC
160
 
PARROT_WARN_UNUSED_RESULT
161
 
PARROT_CANNOT_RETURN_NULL
162
 
void *
163
 
pir_mem_allocate(ARGIN(lexer_state * const lexer), size_t numbytes)
164
 
{
165
 
    void *ptr = mem_sys_allocate(numbytes);
166
 
 
167
 
    totalmem += numbytes;
168
 
 
169
 
    register_ptr(lexer, ptr);
170
 
    return ptr;
171
 
}
172
 
 
173
 
 
174
 
/*
175
 
 
176
 
=item C<void init_hashtable(lexer_state * const lexer, hashtable * const table,
177
 
unsigned size)>
178
 
 
179
 
Initialize the hashtable C<table> with space for C<size> buckets.
180
 
 
181
 
=cut
182
 
 
183
 
*/
184
 
void
185
 
init_hashtable(ARGIN(lexer_state * const lexer), ARGIN(hashtable * const table),
186
 
               unsigned size)
187
 
{
188
 
    table->contents  = (bucket **)pir_mem_allocate_zeroed(lexer, size * sizeof (bucket *));
189
 
    table->size      = size;
190
 
    table->obj_count = 0;
191
 
}
192
 
 
193
 
/*
194
 
 
195
 
=item C<lexer_state * new_lexer(PARROT_INTERP, char * const filename, int
196
 
flags)>
197
 
 
198
 
Constructor for a lexer structure. Initializes all fields, creates
199
 
a Parrot interpreter structure.
200
 
 
201
 
=cut
202
 
 
203
 
*/
204
 
PARROT_MALLOC
205
 
PARROT_CANNOT_RETURN_NULL
206
 
PARROT_WARN_UNUSED_RESULT
207
 
lexer_state *
208
 
new_lexer(PARROT_INTERP, ARGIN_NULLOK(char * const filename), int flags)
209
 
{
210
 
    lexer_state *lexer       = mem_allocate_zeroed_typed(lexer_state);
211
 
    lexer->filename          = filename;
212
 
    lexer->interp            = interp;
213
 
    lexer->flags             = flags;
214
 
    lexer->mem_allocations   = new_mem_ptrs_block();
215
 
 
216
 
 
217
 
    /* the PIR register generator must start counting at -2 (the value is pre-decremented
218
 
     * before returning, hence -1), because -1 is the value for unassigned PASM
219
 
     * registers.
220
 
     */
221
 
    lexer->pir_reg_generator = -1;
222
 
 
223
 
    /* Flex' built-in line counting mechanism doesn't work properly,
224
 
     * because PIRC handles newlines as 'logical' newlines, which is
225
 
     * one or more newlines. Therefore, PIRC keeps track of lines itself.
226
 
     */
227
 
    lexer->linenr = 1;
228
 
 
229
 
 
230
 
    /* create a hashtable to store all strings */
231
 
    init_hashtable(lexer, &lexer->strings, HASHTABLE_SIZE_INIT);
232
 
    /* create a hashtable for storing global labels */
233
 
    init_hashtable(lexer, &lexer->globals, HASHTABLE_SIZE_INIT);
234
 
    /* create a hashtable for storing .const declarations */
235
 
    init_hashtable(lexer, &lexer->constants, HASHTABLE_SIZE_INIT);
236
 
 
237
 
    /* create a new symbol table for macros. */
238
 
    lexer->macros     = new_macro_table(NULL);
239
 
    lexer->macro_size = INIT_MACRO_SIZE;
240
 
 
241
 
    /* create a new linear scan register allocator, if requested */
242
 
    if (TEST_FLAG(flags, LEXER_FLAG_REGALLOC))
243
 
        lexer->lsr = new_linear_scan_register_allocator(lexer);
244
 
 
245
 
    /* create a bytecode object for bytecode generation */
246
 
    lexer->bc = new_bytecode(lexer->interp, filename);
247
 
 
248
 
    return lexer;
249
 
}
250
 
 
251
 
 
252
 
 
253
 
/*
254
 
 
255
 
=item C<bucket * new_bucket(lexer_state * const lexer)>
256
 
 
257
 
Constructor for a bucket object.
258
 
 
259
 
=cut
260
 
 
261
 
*/
262
 
PARROT_CANNOT_RETURN_NULL
263
 
PARROT_WARN_UNUSED_RESULT
264
 
bucket *
265
 
new_bucket(ARGIN(lexer_state * const lexer))
266
 
{
267
 
    return pir_mem_allocate_zeroed_typed(lexer, bucket);
268
 
}
269
 
 
270
 
/*
271
 
 
272
 
=item C<static void store_string(lexer_state * const lexer, char const * const
273
 
str)>
274
 
 
275
 
Store the string C<str> in a hashtable; whenever this string is needed, a pointer
276
 
to the same physical string is returned, preventing allocating different buffers
277
 
for the same string. This is especially useful for ops, as most ops in a typical
278
 
program will be used many times.
279
 
 
280
 
=cut
281
 
 
282
 
*/
283
 
static void
284
 
store_string(ARGIN(lexer_state * const lexer), ARGIN(char const * const str))
285
 
{
286
 
    ASSERT_ARGS(store_string)
287
 
    hashtable    *table = &lexer->strings;
288
 
    unsigned long hash  = get_hashcode(str, table->size);
289
 
    bucket *b           = new_bucket(lexer);
290
 
    bucket_string(b)    = str;
291
 
    store_bucket(table, b, hash);
292
 
}
293
 
 
294
 
/*
295
 
 
296
 
=item C<static char const * find_string(lexer_state * const lexer, char const *
297
 
const str)>
298
 
 
299
 
Find the string C<str> in the lexer's string hashtable. If the string was found,
300
 
then a pointer to that buffer is returned. So, whenever for instance the string
301
 
"print" is used, the string will only be stored in memory once, and a pointer to
302
 
that buffer will be returned.
303
 
 
304
 
=cut
305
 
 
306
 
*/
307
 
PARROT_WARN_UNUSED_RESULT
308
 
PARROT_CAN_RETURN_NULL
309
 
static char const *
310
 
find_string(ARGIN(lexer_state * const lexer), ARGIN(char const * const str))
311
 
{
312
 
    ASSERT_ARGS(find_string)
313
 
    hashtable    *table = &lexer->strings;
314
 
    unsigned long hash  = get_hashcode(str, table->size);
315
 
    bucket *b           = get_bucket(table, hash);
316
 
 
317
 
    while (b) {
318
 
        /* loop through the buckets to see if this is the string */
319
 
        if (STREQ(bucket_string(b), str))
320
 
            return bucket_string(b); /* if so, return a pointer to the actual string. */
321
 
 
322
 
        b = b->next;
323
 
    }
324
 
 
325
 
    return NULL;
326
 
}
327
 
 
328
 
/*
329
 
 
330
 
=item C<char const * dupstrn(lexer_state * const lexer, char * const source,
331
 
size_t slen)>
332
 
 
333
 
See dupstr, except that this version takes the number of characters to be
334
 
copied. Easy for copying a string except the quotes, for instance.
335
 
 
336
 
XXX maybe make this a runtime (commandline) option? Might be slightly slower.
337
 
XXX Otherwise maybe a build option using #defines.
338
 
 
339
 
=cut
340
 
 
341
 
*/
342
 
PARROT_WARN_UNUSED_RESULT
343
 
PARROT_CANNOT_RETURN_NULL
344
 
char const *
345
 
dupstrn(ARGIN(lexer_state * const lexer), ARGIN(char * const source), size_t slen)
346
 
{
347
 
    char const * result = find_string(lexer, source);
348
 
    /* make sure the string is terminated in time */
349
 
    source[slen] = '\0';
350
 
 
351
 
    if (result == NULL) { /* not found */
352
 
        char * newbuffer = (char *)pir_mem_allocate_zeroed(lexer, slen + 1 * sizeof (char));
353
 
        /* only copy num_chars characters */
354
 
        strncpy(newbuffer, source, slen);
355
 
        /* cache the string */
356
 
        store_string(lexer, newbuffer);
357
 
 
358
 
        result = newbuffer;
359
 
    }
360
 
 
361
 
    return result;
362
 
}
363
 
 
364
 
/*
365
 
 
366
 
=item C<char const * dupstr(lexer_state * const lexer, char * const source)>
367
 
 
368
 
The C89 standard does not define a strdup() in the C library,
369
 
so define our own strdup. Function names beginning with "str"
370
 
are reserved, so make it dupstr, as that is what it
371
 
does: duplicate a string.
372
 
 
373
 
=cut
374
 
 
375
 
*/
376
 
PARROT_WARN_UNUSED_RESULT
377
 
PARROT_CANNOT_RETURN_NULL
378
 
char const *
379
 
dupstr(ARGIN(lexer_state * const lexer), ARGIN(char * const source))
380
 
{
381
 
    return dupstrn(lexer, source, strlen(source));
382
 
}
383
 
 
384
 
/*
385
 
 
386
 
=item C<void release_resources(lexer_state *lexer)>
387
 
 
388
 
Release all resources pointed to by C<lexer>.
389
 
Free all memory that was allocated through C<pir_mem_allocate_zeroed()>.
390
 
Free C<lexer> itself.
391
 
 
392
 
=cut
393
 
 
394
 
*/
395
 
void
396
 
release_resources(ARGIN(lexer_state *lexer))
397
 
{
398
 
    allocated_mem_ptrs *iter;
399
 
 
400
 
    if (TEST_FLAG(lexer->flags, LEXER_FLAG_VERBOSE))
401
 
        fprintf(stderr, "Total nr of bytes allocated: %d\n", totalmem);
402
 
 
403
 
 
404
 
    iter = lexer->mem_allocations;
405
 
 
406
 
    while (iter) {
407
 
        allocated_mem_ptrs *temp = iter;
408
 
        unsigned i;
409
 
 
410
 
        /* free all pointers in the ppointer block */
411
 
        for (i = 0; i < iter->allocs_in_this_block; i++)
412
 
            mem_sys_free(iter->ptrs[i]);
413
 
 
414
 
        iter = iter->next;
415
 
        /* free the current pointer block itself */
416
 
        mem_sys_free(temp);
417
 
    }
418
 
 
419
 
    /* finally, free the lexer itself */
420
 
    mem_sys_free(lexer);
421
 
 
422
 
    lexer = NULL;
423
 
}
424
 
 
425
 
 
426
 
/*
427
 
 
428
 
=item C<void pirwarning(lexer_state * const lexer, int lineno, char const *
429
 
const message, ...)>
430
 
 
431
 
Emit a warning message to C<stderr>. The line number (passed in C<lineno>) is reported,
432
 
together with the message. The message can be formatted, meaning it can contain
433
 
C<printf>'s placeholders. C<message> and all variable arguments are passed to
434
 
C<vfprintf()>.
435
 
 
436
 
=cut
437
 
 
438
 
*/
439
 
void
440
 
pirwarning(ARGIN(lexer_state * const lexer),
441
 
        int lineno,
442
 
        ARGIN(char const * const message),
443
 
        ...)
444
 
{
445
 
    va_list arg_ptr;
446
 
    fprintf(stderr, "warning (line %d): ", lineno);
447
 
    va_start(arg_ptr, message);
448
 
    vfprintf(stderr, message, arg_ptr);
449
 
    va_end(arg_ptr);
450
 
    fprintf(stderr, "\n");
451
 
 
452
 
}
453
 
 
454
 
 
455
 
 
456
 
/*
457
 
 
458
 
=back
459
 
 
460
 
=cut
461
 
 
462
 
*/
463
 
 
464
 
 
465
 
/*
466
 
 * Local variables:
467
 
 *   c-file-style: "parrot"
468
 
 * End:
469
 
 * vim: expandtab shiftwidth=4:
470
 
 */
471