2
* $Id: pircompiler.c 45130 2010-03-23 14:32:56Z petdance $
3
* Copyright (C) 2007-2009, Parrot Foundation.
11
#include "pircompiler.h"
12
#include "parrot/parrot.h"
15
#include "pirregalloc.h"
18
/* HEADERIZER HFILE: compilers/pirc/src/pircompiler.h */
20
/* HEADERIZER BEGIN: static */
21
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
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);
32
PARROT_CANNOT_RETURN_NULL
33
PARROT_WARN_UNUSED_RESULT
34
static allocated_mem_ptrs * new_mem_ptrs_block(void);
36
static void register_ptr(ARGMOD(lexer_state *lexer), ARGIN(void *ptr))
37
__attribute__nonnull__(1)
38
__attribute__nonnull__(2)
39
FUNC_MODIFIES(*lexer);
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);
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 */
60
/* XXX count memory, so we can check out mem. savings of string reuse
61
* Only temporarily used, so no need to "fix" this.
63
static int totalmem = 0;
71
=item C<static allocated_mem_ptrs * new_mem_ptrs_block(void)>
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
82
PARROT_CANNOT_RETURN_NULL
83
PARROT_WARN_UNUSED_RESULT
84
static allocated_mem_ptrs *
85
new_mem_ptrs_block(void)
87
ASSERT_ARGS(new_mem_ptrs_block)
88
return mem_allocate_zeroed_typed(allocated_mem_ptrs);
93
=item C<static void register_ptr(lexer_state *lexer, void *ptr)>
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()>.
102
register_ptr(ARGMOD(lexer_state *lexer), ARGIN(void *ptr))
104
ASSERT_ARGS(register_ptr)
105
allocated_mem_ptrs *ptrs = lexer->mem_allocations;
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;
116
/* store the pointer in the current block */
117
ptrs->ptrs[ptrs->allocs_in_this_block++] = ptr;
122
=item C<void * pir_mem_allocate_zeroed(lexer_state *lexer, size_t numbytes)>
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.
129
Memory allocated through this function is all set to zero.
135
PARROT_WARN_UNUSED_RESULT
136
PARROT_CANNOT_RETURN_NULL
138
pir_mem_allocate_zeroed(ARGMOD(lexer_state *lexer), size_t numbytes)
140
void * const ptr = mem_sys_allocate_zeroed(numbytes);
142
totalmem += numbytes;
144
register_ptr(lexer, ptr);
150
=item C<void * pir_mem_allocate(lexer_state * const lexer, size_t numbytes)>
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.)
160
PARROT_WARN_UNUSED_RESULT
161
PARROT_CANNOT_RETURN_NULL
163
pir_mem_allocate(ARGIN(lexer_state * const lexer), size_t numbytes)
165
void *ptr = mem_sys_allocate(numbytes);
167
totalmem += numbytes;
169
register_ptr(lexer, ptr);
176
=item C<void init_hashtable(lexer_state * const lexer, hashtable * const table,
179
Initialize the hashtable C<table> with space for C<size> buckets.
185
init_hashtable(ARGIN(lexer_state * const lexer), ARGIN(hashtable * const table),
188
table->contents = (bucket **)pir_mem_allocate_zeroed(lexer, size * sizeof (bucket *));
190
table->obj_count = 0;
195
=item C<lexer_state * new_lexer(PARROT_INTERP, char * const filename, int
198
Constructor for a lexer structure. Initializes all fields, creates
199
a Parrot interpreter structure.
205
PARROT_CANNOT_RETURN_NULL
206
PARROT_WARN_UNUSED_RESULT
208
new_lexer(PARROT_INTERP, ARGIN_NULLOK(char * const filename), int flags)
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();
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
221
lexer->pir_reg_generator = -1;
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.
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);
237
/* create a new symbol table for macros. */
238
lexer->macros = new_macro_table(NULL);
239
lexer->macro_size = INIT_MACRO_SIZE;
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);
245
/* create a bytecode object for bytecode generation */
246
lexer->bc = new_bytecode(lexer->interp, filename);
255
=item C<bucket * new_bucket(lexer_state * const lexer)>
257
Constructor for a bucket object.
262
PARROT_CANNOT_RETURN_NULL
263
PARROT_WARN_UNUSED_RESULT
265
new_bucket(ARGIN(lexer_state * const lexer))
267
return pir_mem_allocate_zeroed_typed(lexer, bucket);
272
=item C<static void store_string(lexer_state * const lexer, char const * const
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.
284
store_string(ARGIN(lexer_state * const lexer), ARGIN(char const * const str))
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);
296
=item C<static char const * find_string(lexer_state * const lexer, char const *
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.
307
PARROT_WARN_UNUSED_RESULT
308
PARROT_CAN_RETURN_NULL
310
find_string(ARGIN(lexer_state * const lexer), ARGIN(char const * const str))
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);
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. */
330
=item C<char const * dupstrn(lexer_state * const lexer, char * const source,
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.
336
XXX maybe make this a runtime (commandline) option? Might be slightly slower.
337
XXX Otherwise maybe a build option using #defines.
342
PARROT_WARN_UNUSED_RESULT
343
PARROT_CANNOT_RETURN_NULL
345
dupstrn(ARGIN(lexer_state * const lexer), ARGIN(char * const source), size_t slen)
347
char const * result = find_string(lexer, source);
348
/* make sure the string is terminated in time */
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);
366
=item C<char const * dupstr(lexer_state * const lexer, char * const source)>
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.
376
PARROT_WARN_UNUSED_RESULT
377
PARROT_CANNOT_RETURN_NULL
379
dupstr(ARGIN(lexer_state * const lexer), ARGIN(char * const source))
381
return dupstrn(lexer, source, strlen(source));
386
=item C<void release_resources(lexer_state *lexer)>
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.
396
release_resources(ARGIN(lexer_state *lexer))
398
allocated_mem_ptrs *iter;
400
if (TEST_FLAG(lexer->flags, LEXER_FLAG_VERBOSE))
401
fprintf(stderr, "Total nr of bytes allocated: %d\n", totalmem);
404
iter = lexer->mem_allocations;
407
allocated_mem_ptrs *temp = iter;
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]);
415
/* free the current pointer block itself */
419
/* finally, free the lexer itself */
428
=item C<void pirwarning(lexer_state * const lexer, int lineno, char const *
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
440
pirwarning(ARGIN(lexer_state * const lexer),
442
ARGIN(char const * const message),
446
fprintf(stderr, "warning (line %d): ", lineno);
447
va_start(arg_ptr, message);
448
vfprintf(stderr, message, arg_ptr);
450
fprintf(stderr, "\n");
467
* c-file-style: "parrot"
469
* vim: expandtab shiftwidth=4: