2 * Copyright (C) 2002-2008, The Perl Foundation.
10 compilers/imcc/symreg.c
16 XXX: SymReg stuff has become overused. SymReg should be for symbolic
17 registers, reg allocation, etc. but we are now using it for extensive
18 symbol table management. Need to convert much of this over the use Symbol
19 and SymbolTable (see symbol.h and symbol.c)
35 /* HEADERIZER HFILE: compilers/imcc/symreg.h */
37 /* HEADERIZER BEGIN: static */
38 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
40 PARROT_WARN_UNUSED_RESULT
41 PARROT_CAN_RETURN_NULL
42 static SymReg
* _get_sym_typed(
43 ARGIN(const SymHash
*hsh
),
44 ARGIN(const char *name
),
46 __attribute__nonnull__(1)
47 __attribute__nonnull__(2);
49 PARROT_WARN_UNUSED_RESULT
50 PARROT_CANNOT_RETURN_NULL
52 static char * _mk_fullname(
53 ARGIN_NULLOK(const Namespace
*ns
),
54 ARGIN(const char *name
))
55 __attribute__nonnull__(2);
57 PARROT_WARN_UNUSED_RESULT
58 PARROT_CANNOT_RETURN_NULL
59 static SymReg
* _mk_symreg(
61 ARGIN(const char *name
),
63 __attribute__nonnull__(1)
64 __attribute__nonnull__(2)
67 PARROT_WARN_UNUSED_RESULT
68 PARROT_CANNOT_RETURN_NULL
70 static char * add_ns(PARROT_INTERP
, ARGIN(const char *name
))
71 __attribute__nonnull__(1)
72 __attribute__nonnull__(2);
74 PARROT_CANNOT_RETURN_NULL
75 PARROT_WARN_UNUSED_RESULT
76 static SymReg
* mk_pmc_const_2(PARROT_INTERP
,
77 ARGMOD(IMC_Unit
*unit
),
80 __attribute__nonnull__(1)
81 __attribute__nonnull__(2)
82 __attribute__nonnull__(3)
83 __attribute__nonnull__(4)
87 static void resize_symhash(ARGMOD(SymHash
*hsh
))
88 __attribute__nonnull__(1)
91 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
92 /* HEADERIZER END: static */
96 =item C<void push_namespace>
98 Begins a new namespace in PASM/PIR, named after the given C<name>.
105 push_namespace(SHIM_INTERP
, ARGIN(const char *name
))
107 Namespace
* const ns
= mem_allocate_zeroed_typed(Namespace
);
109 ns
->parent
= _namespace
;
110 ns
->name
= str_dup(name
);
117 =item C<void pop_namespace>
119 Ends the current namespace, popping back to the previous. If the namespace
120 stack is empty, throws a syntax error.
127 pop_namespace(PARROT_INTERP
, ARGIN(const char *name
))
129 Namespace
* const ns
= _namespace
;
132 IMCC_fataly(interp
, EXCEPTION_SYNTAX_ERROR
, "pop() on empty namespace stack\n");
134 if (name
&& !STREQ(name
, ns
->name
))
135 IMCC_fataly(interp
, EXCEPTION_SYNTAX_ERROR
, "tried to pop namespace(%s), "
136 "but top of stack is namespace(%s)\n", name
, ns
->name
);
139 Identifier
* const ident
= ns
->idents
;
140 ns
->idents
= ident
->next
;
144 _namespace
= ns
->parent
;
151 =item C<static SymReg * _get_sym_typed>
153 Gets a symbol from the hash, with the given C<name> of the specific type C<t>.
159 PARROT_WARN_UNUSED_RESULT
160 PARROT_CAN_RETURN_NULL
162 _get_sym_typed(ARGIN(const SymHash
*hsh
), ARGIN(const char *name
), int t
)
165 const unsigned int i
= hash_str(name
) % hsh
->size
;
167 for (p
= hsh
->data
[i
]; p
; p
= p
->next
) {
168 if ((t
== p
->set
) && STREQ(name
, p
->name
))
176 /* symbolic registers */
180 =item C<static SymReg * _mk_symreg>
182 Makes a new SymReg in the given SymHash from a varname and type.
188 PARROT_WARN_UNUSED_RESULT
189 PARROT_CANNOT_RETURN_NULL
191 _mk_symreg(ARGMOD(SymHash
*hsh
), ARGIN(const char *name
), int t
)
193 SymReg
* r
= _get_sym_typed(hsh
, name
, t
);
196 r
= mem_allocate_zeroed_typed(SymReg
);
199 r
->name
= str_dup(name
);
203 _store_symreg(hsh
, r
);
212 =item C<SymReg * mk_symreg>
214 Makes a new SymReg in the current unit, given a varname and type.
220 PARROT_WARN_UNUSED_RESULT
221 PARROT_CANNOT_RETURN_NULL
223 mk_symreg(PARROT_INTERP
, ARGIN(const char *name
), int t
)
225 IMC_Unit
* const unit
= IMCC_INFO(interp
)->last_unit
;
226 return _mk_symreg(&unit
->hash
, name
, t
);
232 =item C<char * symreg_to_str>
234 Dumps a SymReg to a printable format.
241 PARROT_WARN_UNUSED_RESULT
242 PARROT_CANNOT_RETURN_NULL
244 symreg_to_str(ARGIN(const SymReg
*s
))
246 /* NOTE: the below magic number encompasses all the quoted strings which
247 * may be included in the sprintf output (for now) */
248 char * const buf
= (char *)mem_sys_allocate(250 + strlen(s
->name
));
249 const int t
= s
->type
;
251 sprintf(buf
, "symbol [%s] set [%c] color [" INTVAL_FMT
"] type [",
252 s
->name
, s
->set
, s
->color
);
254 if (t
& VTCONST
) { strcat(buf
, "VTCONST "); }
255 if (t
& VTREG
) { strcat(buf
, "VTREG "); }
256 if (t
& VTIDENTIFIER
) { strcat(buf
, "VTIDENTIFIER "); }
257 if (t
& VTADDRESS
) { strcat(buf
, "VTADDRESS "); }
258 if (t
& VTREGKEY
) { strcat(buf
, "VTREGKEY "); }
259 if (t
& VTPASM
) { strcat(buf
, "VTPASM "); }
260 if (t
& VT_CONSTP
) { strcat(buf
, "VT_CONSTP "); }
261 if (t
& VT_PCC_SUB
) { strcat(buf
, "VT_PCC_SUB "); }
262 if (t
& VT_FLAT
) { strcat(buf
, "VT_FLAT "); }
263 if (t
& VT_OPTIONAL
) { strcat(buf
, "VT_OPTIONAL "); }
264 if (t
& VT_NAMED
) { strcat(buf
, "VT_NAMED "); }
274 =item C<SymReg * mk_temp_reg>
276 Makes a new unique and temporary SymReg of the specified type C<t>.
282 PARROT_WARN_UNUSED_RESULT
283 PARROT_CANNOT_RETURN_NULL
285 mk_temp_reg(PARROT_INTERP
, int t
)
290 snprintf(buf
, sizeof (buf
), "__imcc_temp_%d", ++temp
);
291 return mk_symreg(interp
, buf
, t
);
297 =item C<SymReg * mk_pcc_sub>
299 Makes a SymReg representing a PCC sub of the given C<name> with the specified
306 PARROT_WARN_UNUSED_RESULT
307 PARROT_CANNOT_RETURN_NULL
309 mk_pcc_sub(PARROT_INTERP
, ARGIN(const char *name
), int proto
)
311 IMC_Unit
* const unit
= IMCC_INFO(interp
)->last_unit
;
312 SymReg
* const r
= _mk_symreg(&unit
->hash
, name
, proto
);
314 r
->type
= VT_PCC_SUB
;
315 r
->pcc_sub
= mem_allocate_zeroed_typed(pcc_sub_t
);
323 =item C<void add_namespace>
325 Add the current namespace to a sub declaration.
332 add_namespace(PARROT_INTERP
, ARGMOD(IMC_Unit
*unit
))
334 SymReg
* const ns
= IMCC_INFO(interp
)->cur_namespace
;
339 if (unit
->_namespace
)
342 if (unit
->prev
&& unit
->prev
->_namespace
== ns
)
343 unit
->_namespace
= ns
;
345 SymReg
* const g
= dup_sym(ns
);
346 SymReg
* const r
= _get_sym(&IMCC_INFO(interp
)->ghash
, g
->name
);
348 unit
->_namespace
= g
;
352 if (!r
|| r
->type
!= VT_CONSTP
)
353 _store_symreg(&IMCC_INFO(interp
)->ghash
, g
);
360 =item C<void add_pcc_arg>
362 Adds a register or constant to the function arg list.
369 add_pcc_arg(ARGMOD(SymReg
*r
), ARGMOD(SymReg
*arg
))
371 pcc_sub_t
* const sub
= r
->pcc_sub
;
372 const int n
= sub
->nargs
;
374 mem_realloc_n_typed(sub
->args
, n
+ 1, SymReg
*);
375 mem_realloc_n_typed(sub
->arg_flags
, n
+ 1, int);
378 sub
->arg_flags
[n
] = arg
->type
;
380 arg
->type
&= ~(VT_FLAT
|VT_OPTIONAL
|VT_OPT_FLAG
|VT_NAMED
);
388 =item C<void add_pcc_result>
390 Adds a register or constant to the function's return list.
397 add_pcc_result(ARGMOD(SymReg
*r
), ARGMOD(SymReg
*arg
))
399 pcc_sub_t
* const sub
= r
->pcc_sub
;
400 const int n
= sub
->nret
;
402 mem_realloc_n_typed(sub
->ret
, n
+ 1, SymReg
*);
403 mem_realloc_n_typed(sub
->ret_flags
, n
+ 1, int);
405 /* we can't keep the flags in the SymReg as the SymReg
406 * maybe used with different flags for different calls */
408 sub
->ret_flags
[n
] = arg
->type
;
410 arg
->type
&= ~(VT_FLAT
|VT_OPTIONAL
|VT_OPT_FLAG
|VT_NAMED
);
418 =item C<void add_pcc_multi>
420 Adds a :multi signature to the sub.
427 add_pcc_multi(ARGMOD(SymReg
*r
), ARGIN_NULLOK(SymReg
*arg
))
429 pcc_sub_t
* const sub
= r
->pcc_sub
;
430 const int n
= sub
->nmulti
;
432 mem_realloc_n_typed(sub
->multi
, n
+ 1, SymReg
*);
440 =item C<void add_pcc_sub>
442 Sets the current sub in the given SymReg to the second SymReg.
449 add_pcc_sub(ARGMOD(SymReg
*r
), ARGIN(SymReg
*arg
))
451 r
->pcc_sub
->sub
= arg
;
457 =item C<void add_pcc_cc>
459 Adds a continuation (?) to the current sub.
466 add_pcc_cc(ARGMOD(SymReg
*r
), ARGIN(SymReg
*arg
))
468 r
->pcc_sub
->cc
= arg
;
474 =item C<SymReg * mk_pasm_reg>
476 Makes a SymReg representing a PASM register.
482 PARROT_WARN_UNUSED_RESULT
483 PARROT_CANNOT_RETURN_NULL
485 mk_pasm_reg(PARROT_INTERP
, ARGIN(const char *name
))
487 SymReg
*r
= _get_sym(&IMCC_INFO(interp
)->cur_unit
->hash
, name
);
490 r
= mk_symreg(interp
, name
, *name
);
492 r
->color
= atoi(name
+ 1);
495 IMCC_fataly(interp
, EXCEPTION_SYNTAX_ERROR
,
496 "register number out of range '%s'\n", name
);
505 =item C<static char * _mk_fullname>
507 Combines the namespace and name together, separated by a C<::>. If there's no
508 namespace, the name is returned on its own.
510 The returned string must be free()d.
516 PARROT_WARN_UNUSED_RESULT
517 PARROT_CANNOT_RETURN_NULL
520 _mk_fullname(ARGIN_NULLOK(const Namespace
*ns
), ARGIN(const char *name
))
523 const size_t len
= strlen(name
) + strlen(ns
->name
) + 3;
524 char *result
= (char *) mem_sys_allocate(len
);
525 snprintf(result
, len
, "%s::%s", ns
->name
, name
);
529 return str_dup(name
);
535 =item C<SymReg * mk_ident>
537 Makes a new identifier.
543 PARROT_CANNOT_RETURN_NULL
544 PARROT_IGNORABLE_RESULT
546 mk_ident(PARROT_INTERP
, ARGIN(const char *name
), int t
)
548 char * const fullname
= _mk_fullname(_namespace
, name
);
549 SymReg
*r
= mk_symreg(interp
, fullname
, t
);
551 r
->type
= VTIDENTIFIER
;
554 Identifier
* const ident
= mem_allocate_zeroed_typed(Identifier
);
556 ident
->name
= fullname
;
557 ident
->next
= _namespace
->idents
;
558 _namespace
->idents
= ident
;
561 mem_sys_free(fullname
);
564 r
->pmc_type
= IMCC_INFO(interp
)->cur_pmc_type
;
565 IMCC_INFO(interp
)->cur_pmc_type
= 0;
574 =item C<SymReg* mk_ident_ur>
576 Creates and returns a SymReg representing a unique (non-volatile) register.
582 PARROT_CANNOT_RETURN_NULL
583 PARROT_IGNORABLE_RESULT
585 mk_ident_ur(PARROT_INTERP
, ARGIN(const char *name
), int t
)
587 SymReg
* const r
= mk_ident(interp
, name
, t
);
588 r
->usage
|= U_NON_VOLATILE
;
596 =item C<static SymReg * mk_pmc_const_2>
598 Makes a constant PMC and inserts instructions to access it.
604 PARROT_CANNOT_RETURN_NULL
605 PARROT_WARN_UNUSED_RESULT
607 mk_pmc_const_2(PARROT_INTERP
, ARGMOD(IMC_Unit
*unit
), ARGIN(SymReg
*left
),
610 /* XXX This always returns NULL. Probably shouldn't return anything then. */
615 if (IMCC_INFO(interp
)->state
->pasm_file
)
616 IMCC_fataly(interp
, EXCEPTION_SYNTAX_ERROR
,
617 "Ident as PMC constant %s\n", left
->name
);
621 /* strip delimiters */
622 name
= str_dup(rhs
->name
+ 1);
624 name
[len
- 1] = '\0';
626 mem_sys_free(rhs
->name
);
630 rhs
->pmc_type
= left
->pmc_type
;
632 switch (rhs
->pmc_type
) {
634 case enum_class_Coroutine
:
636 rhs
->usage
= U_FIXUP
;
637 INS(interp
, unit
, "set_p_pc", "", r
, 2, 0, 1);
644 INS(interp
, unit
, "set_p_pc", "", r
, 2, 0, 1);
652 =item C<SymReg * mk_const_ident>
654 Makes a new identifier constant with value val.
660 PARROT_CANNOT_RETURN_NULL
661 PARROT_IGNORABLE_RESULT
663 mk_const_ident(PARROT_INTERP
, ARGIN(const char *name
), int t
,
664 ARGMOD(SymReg
*val
), int global
)
669 * Forbid assigning a string to anything other than a string
672 if (t
== 'N' || t
== 'I') {
674 IMCC_fataly(interp
, EXCEPTION_SYNTAX_ERROR
, "bad const initialisation");
676 /* Cast value to const type */
682 IMCC_fataly(interp
, EXCEPTION_SYNTAX_ERROR
,
683 "global PMC constant not allowed");
685 r
= _mk_symreg(&IMCC_INFO(interp
)->ghash
, name
, t
);
688 r
= mk_ident(interp
, name
, t
);
691 return mk_pmc_const_2(interp
, IMCC_INFO(interp
)->cur_unit
, r
, val
);
703 =item C<SymReg * _mk_const>
705 Makes a new constant (internal use only).
711 PARROT_WARN_UNUSED_RESULT
712 PARROT_CANNOT_RETURN_NULL
714 _mk_const(ARGMOD(SymHash
*hsh
), ARGIN(const char *name
), int t
)
716 SymReg
* const r
= _mk_symreg(hsh
, name
, t
);
720 /* charset:"string" */
722 r
->type
|= VT_ENCODED
;
733 =item C<SymReg * mk_const>
735 Makes a new constant (and populates the cache of global symbols).
741 PARROT_WARN_UNUSED_RESULT
742 PARROT_CANNOT_RETURN_NULL
744 mk_const(PARROT_INTERP
, ARGIN(const char *name
), int t
)
746 SymHash
* const h
= &IMCC_INFO(interp
)->ghash
;
751 return _mk_const(h
, name
, t
);
757 =item C<static char * add_ns>
759 Adds a namespace to the current sub.
765 PARROT_WARN_UNUSED_RESULT
766 PARROT_CANNOT_RETURN_NULL
769 add_ns(PARROT_INTERP
, ARGIN(const char *name
))
774 if (!IMCC_INFO(interp
)->cur_namespace
775 || (l
= strlen(IMCC_INFO(interp
)->cur_namespace
->name
)) <= 2)
776 return str_dup(name
);
778 /* TODO keyed syntax */
779 len
= strlen(name
) + l
+ 4;
780 ns_name
= (char*)mem_sys_allocate(len
);
782 strcpy(ns_name
, IMCC_INFO(interp
)->cur_namespace
->name
);
784 ns_name
[l
- 1] = '\0';
785 strcat(ns_name
, "@@@");
786 strcat(ns_name
, name
);
788 p
= strstr(ns_name
, "\";\""); /* Foo";"Bar -> Foo@@@Bar */
794 p
= strstr(ns_name
, "\";\")");
803 =item C<SymReg * _mk_address>
805 Makes a new address (internal use only).
811 PARROT_WARN_UNUSED_RESULT
812 PARROT_CANNOT_RETURN_NULL
814 _mk_address(PARROT_INTERP
, ARGMOD(SymHash
*hsh
), ARGIN(const char *name
), int uniq
)
818 if (uniq
== U_add_all
) {
819 r
= mem_allocate_zeroed_typed(SymReg
);
821 r
->name
= str_dup(name
);
822 _store_symreg(hsh
, r
);
825 if (uniq
== U_add_uniq_sub
)
826 name
= add_ns(interp
, name
);
828 r
= _get_sym(hsh
, name
);
830 /* we use this for labels/subs */
831 if (uniq
&& r
&& r
->type
== VTADDRESS
&& r
->lhs_use_count
) {
832 if (uniq
== U_add_uniq_label
)
833 IMCC_fataly(interp
, EXCEPTION_SYNTAX_ERROR
,
834 "Label '%s' already defined\n", name
);
835 else if (uniq
== U_add_uniq_sub
)
836 IMCC_fataly(interp
, EXCEPTION_SYNTAX_ERROR
,
837 "Subroutine '%s' already defined\n", name
);
840 r
= _mk_symreg(hsh
, name
, 0);
853 =item C<SymReg * mk_sub_label>
855 Makes and stores a new address label for a sub. The label gets a fixup entry.
861 PARROT_WARN_UNUSED_RESULT
862 PARROT_CANNOT_RETURN_NULL
864 mk_sub_label(PARROT_INTERP
, ARGIN(const char *name
))
866 SymReg
* const s
= _mk_address(interp
, &IMCC_INFO(interp
)->ghash
,
867 name
, U_add_uniq_sub
);
877 =item C<SymReg * mk_sub_address>
879 Makes a symbol for a label. The symbol gets a fixup entry.
885 PARROT_WARN_UNUSED_RESULT
886 PARROT_CANNOT_RETURN_NULL
888 mk_sub_address(PARROT_INTERP
, ARGIN(const char *name
))
890 SymReg
* const s
= _mk_address(interp
, &IMCC_INFO(interp
)->ghash
,
901 =item C<SymReg * mk_local_label>
903 Makes a local symbol, giving it I<no> fixup entry.
909 PARROT_WARN_UNUSED_RESULT
910 PARROT_CANNOT_RETURN_NULL
912 mk_local_label(PARROT_INTERP
, ARGIN(const char *name
))
914 IMC_Unit
* const unit
= IMCC_INFO(interp
)->last_unit
;
915 return _mk_address(interp
, &unit
->hash
, name
, U_add_uniq_label
);
921 =item C<SymReg * mk_label_address>
923 Makes a new label address.
929 PARROT_WARN_UNUSED_RESULT
930 PARROT_CANNOT_RETURN_NULL
932 mk_label_address(PARROT_INTERP
, ARGIN(const char *name
))
934 IMC_Unit
* const unit
= IMCC_INFO(interp
)->last_unit
;
935 return _mk_address(interp
, &unit
->hash
, name
, U_add_once
);
941 =item C<SymReg * dup_sym>
943 Links keys to a keys structure = SymReg
947 what op type pbc.c:build_key()
948 --------------------------------------------------
949 int const _kic VTCONST no
951 str const _kc VTCONST yes
952 str reg _kc VTREG yes
954 "key" ';' "key" _kc -> (list of above) yes
955 "key" ';' $I0 _kc VTREGKEY -> (list of above) yes
957 The information about which reg should be passed to build_key() is
960 A key containing a variable has a special flag VTREGKEY
961 because this key must be considered for life analysis for
962 all the chain members, that are variables.
964 An instruction with a keychain looks like this
966 e.h. set I0, P["abc";0;I1]
968 ins->r[2] = keychain 'K'
969 keychain->nextkey = SymReg(VTCONST) "abc"
970 ->nextkey = SymReg(VTCONST) 0
971 ->nextkey = SymReg(VTREG), ...->reg = VTVAR I1
974 We can't use the consts or keys in the chain directly,
975 because a different usage would destroy the ->nextkey pointers
976 so these are all copies.
977 XXX and currently not freed
984 PARROT_CANNOT_RETURN_NULL
986 dup_sym(ARGIN(const SymReg
*r
))
988 SymReg
* const new_sym
= mem_allocate_zeroed_typed(SymReg
);
989 STRUCT_COPY(new_sym
, r
);
990 new_sym
->name
= str_dup(r
->name
);
993 new_sym
->nextkey
= dup_sym(r
->nextkey
);
1001 =item C<SymReg * link_keys>
1003 Links keys together in a keychain.
1010 PARROT_CANNOT_RETURN_NULL
1012 link_keys(PARROT_INTERP
, int nargs
, ARGMOD(SymReg
**keys
), int force
)
1021 /* namespace keys are global consts - no cur_unit */
1022 SymHash
* const h
= IMCC_INFO(interp
)->cur_unit
1023 ? &IMCC_INFO(interp
)->cur_unit
->hash
1024 : &IMCC_INFO(interp
)->ghash
;
1027 IMCC_fataly(interp
, EXCEPTION_SYNTAX_ERROR
, "link_keys: huh? no keys\n");
1029 /* short-circuit simple key unless we've been told not to */
1030 if (nargs
== 1 && !force
&& !(keys
[0]->type
& VT_SLICE_BITS
))
1033 /* calc len of key_str
1034 * also check if this is a slice - the first key might not
1035 * have the slice flag set */
1036 for (i
= 0; i
< nargs
; i
++) {
1037 len
+= 1 + strlen(keys
[i
]->name
);
1038 if (keys
[i
]->type
& VT_SLICE_BITS
)
1042 if (any_slice
&& !(keys
[0]->type
& VT_SLICE_BITS
))
1043 keys
[0]->type
|= (VT_START_SLICE
|VT_END_SLICE
);
1045 key_str
= (char *)mem_sys_allocate(len
);
1048 /* first look, if we already have this exact key chain */
1049 for (i
= 0; i
< nargs
; i
++) {
1050 strcat(key_str
, keys
[i
]->name
);
1051 /* TODO insert : to compare slices */
1053 strcat(key_str
, ";");
1056 if (!any_slice
&& ((keychain
= _get_sym(h
, key_str
)) != NULL
)) {
1057 mem_sys_free(key_str
);
1061 /* no, need a new one */
1062 keychain
= mem_allocate_zeroed_typed(SymReg
);
1063 keychain
->type
= VTCONST
;
1065 ++keychain
->use_count
;
1069 for (i
= 0; i
< nargs
; i
++) {
1070 /* if any component is a variable, we need to track it in
1072 if (REG_NEEDS_ALLOC(keys
[i
]))
1073 keychain
->type
|= VTREGKEY
;
1075 key
->nextkey
= dup_sym(keys
[i
]);
1078 /* for registers, point ->reg to the original, needed by
1079 * life analyses & coloring */
1080 if (REG_NEEDS_ALLOC(keys
[i
]))
1084 keychain
->name
= key_str
;
1085 keychain
->set
= 'K';
1086 keychain
->color
= -1;
1088 _store_symreg(h
, keychain
);
1096 =item C<void free_sym>
1098 Frees all memory of the specified SymReg. If it has a pcc_sub_t entry, frees
1099 all memory of that structure as well.
1106 free_sym(ARGMOD(SymReg
*r
))
1108 pcc_sub_t
* const sub
= r
->pcc_sub
;
1111 mem_sys_free(sub
->multi
);
1112 mem_sys_free(sub
->args
);
1113 mem_sys_free(sub
->arg_flags
);
1114 mem_sys_free(sub
->ret
);
1115 mem_sys_free(sub
->ret_flags
);
1119 if (r
->set
== 'K') {
1120 SymReg
*key
= r
->nextkey
;
1122 SymReg
*nextkey
= key
->nextkey
;
1128 mem_sys_free(r
->name
);
1133 * This functions manipulate the hash of symbols.
1134 * XXX: Migrate to use Symbol and SymbolTable
1140 =item C<void create_symhash>
1142 Creates a symbol hash table with space for 16 entries.
1149 create_symhash(ARGOUT(SymHash
*hash
))
1151 hash
->data
= mem_allocate_n_zeroed_typed(16, SymReg
*);
1159 =item C<static void resize_symhash>
1161 Resizes a symbol hash table.
1168 resize_symhash(ARGMOD(SymHash
*hsh
))
1170 const int new_size
= hsh
->size
<< 1; /* new size is twice as large */
1172 SymReg
**next_r
= mem_allocate_n_zeroed_typed(n_next
, SymReg
*);
1173 SymHash nh
; /* new symbol table */
1176 nh
.data
= mem_allocate_n_zeroed_typed(new_size
, SymReg
*);
1178 for (i
= 0; i
< hsh
->size
; i
++) {
1183 for (r
= hsh
->data
[i
]; r
; r
= next
) {
1186 /* remember all the chained next pointers and clear r->next */
1189 mem_realloc_n_typed(next_r
, n_next
, SymReg
*);
1196 for (k
= 0; k
< j
; ++k
) {
1199 /* recompute hash for this symbol: */
1200 new_i
= hash_str(r
->name
) % new_size
;
1201 r
->next
= nh
.data
[new_i
];
1206 /* free memory of old hash table */
1207 mem_sys_free(hsh
->data
);
1208 mem_sys_free(next_r
);
1210 /* let the hashtable's data pointers point to the new data */
1211 hsh
->data
= nh
.data
;
1212 hsh
->size
= new_size
;
1218 =item C<void _store_symreg>
1220 Stores a symbol in the hash (internal use only).
1227 _store_symreg(ARGMOD(SymHash
*hsh
), ARGMOD(SymReg
*r
))
1229 const int i
= hash_str(r
->name
) % hsh
->size
;
1231 printf(" store [%s]\n", r
->name
);
1233 r
->next
= hsh
->data
[i
];
1238 if (hsh
->entries
>= hsh
->size
)
1239 resize_symhash(hsh
);
1245 =item C<void store_symreg>
1247 Stores a symbol in the hash.
1254 store_symreg(PARROT_INTERP
, ARGMOD(SymReg
*r
))
1256 _store_symreg(&IMCC_INFO(interp
)->cur_unit
->hash
, r
);
1262 =item C<SymReg * _get_sym>
1264 Fetches a symbol from the hash (internal use only).
1270 PARROT_CAN_RETURN_NULL
1271 PARROT_WARN_UNUSED_RESULT
1273 _get_sym(ARGIN(const SymHash
*hsh
), ARGIN(const char *name
))
1276 const unsigned int i
= hash_str(name
) % hsh
->size
;
1278 for (p
= hsh
->data
[i
]; p
; p
= p
->next
) {
1280 printf(" [%s]\n", p
->name
);
1282 if (STREQ(name
, p
->name
))
1291 =item C<SymReg * get_sym>
1293 Gets a symbol from the current unit's symbol table.
1299 PARROT_CAN_RETURN_NULL
1300 PARROT_WARN_UNUSED_RESULT
1302 get_sym(PARROT_INTERP
, ARGIN(const char *name
))
1304 return _get_sym(&IMCC_INFO(interp
)->cur_unit
->hash
, name
);
1310 =item C<SymReg * _find_sym>
1312 Find a symbol hash or ghash (internal use only);
1318 PARROT_CAN_RETURN_NULL
1319 PARROT_WARN_UNUSED_RESULT
1321 _find_sym(PARROT_INTERP
, ARGIN_NULLOK(const Namespace
*nspace
),
1322 ARGIN(const SymHash
*hsh
), ARGIN(const char *name
))
1324 const Namespace
*ns
;
1327 for (ns
= nspace
; ns
; ns
= ns
->parent
) {
1328 char * const fullname
= _mk_fullname(ns
, name
);
1329 p
= _get_sym(hsh
, fullname
);
1331 mem_sys_free(fullname
);
1337 p
= _get_sym(hsh
, name
);
1342 p
= _get_sym(&IMCC_INFO(interp
)->ghash
, name
);
1353 =item C<SymReg * find_sym>
1355 Finds a symbol hash or ghash in the current unit, if it exists. Otherwise
1362 PARROT_CAN_RETURN_NULL
1363 PARROT_WARN_UNUSED_RESULT
1365 find_sym(PARROT_INTERP
, ARGIN(const char *name
))
1367 if (IMCC_INFO(interp
)->cur_unit
)
1368 return _find_sym(interp
, _namespace
,
1369 &IMCC_INFO(interp
)->cur_unit
->hash
, name
);
1377 =item C<void clear_sym_hash>
1379 Frees all memory of the symbols in the specified hash table.
1386 clear_sym_hash(ARGMOD(SymHash
*hsh
))
1393 for (i
= 0; i
< hsh
->size
; i
++) {
1395 for (p
= hsh
->data
[i
]; p
;) {
1396 SymReg
* const next
= p
->next
;
1401 hsh
->data
[i
] = NULL
;
1404 mem_sys_free(hsh
->data
);
1414 =item C<void debug_dump_sym_hash>
1416 Prints all identifiers in the specified hash table to stderr.
1423 debug_dump_sym_hash(ARGIN(const SymHash
*hsh
))
1427 for (i
= 0; i
< hsh
->size
; i
++) {
1428 const SymReg
*p
= hsh
->data
[i
];
1430 fprintf(stderr
, "%s ", p
->name
);
1439 =item C<void clear_locals>
1441 Deletes all local symbols and clears life info from the given IMC_Unit.
1448 clear_locals(ARGIN_NULLOK(IMC_Unit
*unit
))
1450 SymHash
* const hsh
= &unit
->hash
;
1453 for (i
= 0; i
< hsh
->size
; i
++) {
1455 for (p
= hsh
->data
[i
]; p
;) {
1456 SymReg
* const next
= p
->next
;
1458 if (unit
&& p
->life_info
)
1459 free_life_info(unit
, p
);
1465 hsh
->data
[i
] = NULL
;
1474 =item C<void clear_globals>
1476 Clears global symbols.
1483 clear_globals(PARROT_INTERP
)
1485 SymHash
* const hsh
= &IMCC_INFO(interp
)->ghash
;
1488 clear_sym_hash(hsh
);
1492 /* utility functions: */
1496 =item C<unsigned int hash_str>
1498 Computes the hash value for the string argument.
1504 PARROT_PURE_FUNCTION
1506 hash_str(ARGIN(const char *str
))
1508 unsigned long key
= 0;
1511 for (s
= str
; *s
; s
++)
1512 key
= key
* 65599 + *s
;
1528 * c-file-style: "parrot"
1530 * vim: expandtab shiftwidth=4: