Skip to content

Commit 33e32e0

Browse files
committed
Implement const qualifier for global variables
This extends existing .rodata section support to handle const-qualified globals. Now, const initialized variables are placed in read-only memory section instead of writable .data section. Add const pointer type support for function param - Parse const qualifiers in function parameter declarations - Fix operator precedence for pointer dereference expressions (*a + *b) - Add safety checks for SSA subscript access to prevent crashes - Fix ARM codegen to properly set stack frame size in return insts - Add comprehensive test coverage with 15 const pointer test cases This enables functions to accept const-qualified pointer parameters (e.g., const int *ptr) following C standard semantics. Improve const qualifier support - Updated function parameters to use const where appropriate - Modified hashmap functions to accept const char* keys - Fixed string interning to handle const strings properly - Added const to arena_strdup and arena_memdup functions - Updated ELF generation functions to use const parameters
1 parent 91079e4 commit 33e32e0

File tree

8 files changed

+457
-84
lines changed

8 files changed

+457
-84
lines changed

src/defs.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ typedef enum {
179179
T_break,
180180
T_default,
181181
T_continue,
182+
T_const, /* const qualifier */
182183
/* C pre-processor directives */
183184
T_cppd_include,
184185
T_cppd_define,
@@ -353,8 +354,9 @@ struct var {
353354
int ptr_level;
354355
bool is_func;
355356
bool is_global;
356-
bool is_initialized; /* true if global variable has initialization */
357-
bool address_taken; /* true if variable address was taken (&var) */
357+
bool is_initialized; /* true if global variable has initialization */
358+
bool is_const_qualified; /* true if variable has const qualifier */
359+
bool address_taken; /* true if variable address was taken (&var) */
358360
int array_size;
359361
int array_dim1, array_dim2; /* first/second dimension size for 2D arrays */
360362
int offset; /* offset from stack or frame, index 0 is reserved */

src/elf.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
int elf_symbol_index;
1515

16-
void elf_write_str(strbuf_t *elf_array, char *vals)
16+
void elf_write_str(strbuf_t *elf_array, const char *vals)
1717
{
1818
/*
1919
* Note that strbuf_puts() does not push the null character.
@@ -391,7 +391,7 @@ void elf_align(void)
391391
elf_write_byte(elf_strtab, 0);
392392
}
393393

394-
void elf_add_symbol(char *symbol, int pc)
394+
void elf_add_symbol(const char *symbol, int pc)
395395
{
396396
/* Check for null pointers to prevent crashes */
397397
if (!symbol || !elf_symtab || !elf_strtab) {
@@ -409,7 +409,7 @@ void elf_add_symbol(char *symbol, int pc)
409409
elf_symbol_index++;
410410
}
411411

412-
void elf_generate(char *outfile)
412+
void elf_generate(const char *outfile)
413413
{
414414
elf_align();
415415
elf_generate_header();

src/globals.c

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include "defs.h"
1515

1616
/* Forward declaration for string interning */
17-
char *intern_string(char *str);
17+
char *intern_string(const char *str);
1818

1919
/* Lexer */
2020
char token_str[MAX_TOKEN_LEN];
@@ -285,7 +285,7 @@ void *arena_realloc(arena_t *arena, char *oldptr, int oldsz, int newsz)
285285
*
286286
* Return: Pointer to the duplicated string stored in the arena.
287287
*/
288-
char *arena_strdup(arena_t *arena, char *str)
288+
char *arena_strdup(arena_t *arena, const char *str)
289289
{
290290
int n = strlen(str);
291291
char *dup = arena_alloc(arena, n + 1);
@@ -303,7 +303,7 @@ char *arena_strdup(arena_t *arena, char *str)
303303
*
304304
* Return: The pointer to the duplicated memory stored in the arena.
305305
*/
306-
void *arena_memdup(arena_t *arena, void *data, int size)
306+
void *arena_memdup(arena_t *arena, const void *data, int size)
307307
{
308308
return memcpy(arena_alloc(arena, size), data, size);
309309
}
@@ -371,7 +371,7 @@ void arena_free(arena_t *arena)
371371
*
372372
* Return: The usable hashmap index.
373373
*/
374-
int hashmap_hash_index(int size, char *key)
374+
int hashmap_hash_index(int size, const char *key)
375375
{
376376
int hash = 0x811c9dc5, mask;
377377

@@ -431,7 +431,7 @@ hashmap_t *hashmap_create(int cap)
431431
*
432432
* Return: The pointer of created node.
433433
*/
434-
hashmap_node_t *hashmap_node_new(char *key, void *val)
434+
hashmap_node_t *hashmap_node_new(const char *key, void *val)
435435
{
436436
if (!key)
437437
return NULL;
@@ -506,7 +506,7 @@ void hashmap_rehash(hashmap_t *map)
506506
* @val: The value pointer. May be NULL. This value's lifetime is held by
507507
* hashmap.
508508
*/
509-
void hashmap_put(hashmap_t *map, char *key, void *val)
509+
void hashmap_put(hashmap_t *map, const char *key, void *val)
510510
{
511511
if (!map)
512512
return;
@@ -536,7 +536,7 @@ void hashmap_put(hashmap_t *map, char *key, void *val)
536536
* Return: The look up result, if the key-value pair entry exists, then returns
537537
* address of itself, NULL otherwise.
538538
*/
539-
hashmap_node_t *hashmap_get_node(hashmap_t *map, char *key)
539+
hashmap_node_t *hashmap_get_node(hashmap_t *map, const char *key)
540540
{
541541
if (!map)
542542
return NULL;
@@ -557,7 +557,7 @@ hashmap_node_t *hashmap_get_node(hashmap_t *map, char *key)
557557
* Return: The look up result, if the key-value pair entry exists, then returns
558558
* its value's address, NULL otherwise.
559559
*/
560-
void *hashmap_get(hashmap_t *map, char *key)
560+
void *hashmap_get(hashmap_t *map, const char *key)
561561
{
562562
hashmap_node_t *node = hashmap_get_node(map, key);
563563
return node ? node->val : NULL;
@@ -570,7 +570,7 @@ void *hashmap_get(hashmap_t *map, char *key)
570570
* Return: The look up result, if the key-value pair entry exists, then returns
571571
* true, false otherwise.
572572
*/
573-
bool hashmap_contains(hashmap_t *map, char *key)
573+
bool hashmap_contains(hashmap_t *map, const char *key)
574574
{
575575
return hashmap_get_node(map, key);
576576
}
@@ -601,7 +601,7 @@ bool hard_mul_div = false;
601601
*
602602
* Return: The pointer to the type, or NULL if not found.
603603
*/
604-
type_t *find_type(char *type_name, int flag)
604+
type_t *find_type(const char *type_name, int flag)
605605
{
606606
for (int i = 0; i < types_idx; i++) {
607607
if (TYPES[i].base_type == TYPE_struct ||
@@ -672,7 +672,7 @@ block_t *add_block(block_t *parent, func_t *func, macro_t *macro)
672672
return blk;
673673
}
674674

675-
void add_alias(char *alias, char *value)
675+
void add_alias(const char *alias, const char *value)
676676
{
677677
alias_t *al = hashmap_get(ALIASES_MAP, alias);
678678
if (!al) {
@@ -689,15 +689,15 @@ void add_alias(char *alias, char *value)
689689
al->disabled = false;
690690
}
691691

692-
char *find_alias(char alias[])
692+
char *find_alias(const char alias[])
693693
{
694694
alias_t *al = hashmap_get(ALIASES_MAP, alias);
695695
if (al && !al->disabled)
696696
return al->value;
697697
return NULL;
698698
}
699699

700-
bool remove_alias(char *alias)
700+
bool remove_alias(const char *alias)
701701
{
702702
alias_t *al = hashmap_get(ALIASES_MAP, alias);
703703
if (al && !al->disabled) {
@@ -724,15 +724,15 @@ macro_t *add_macro(char *name)
724724
return ma;
725725
}
726726

727-
macro_t *find_macro(char *name)
727+
macro_t *find_macro(const char *name)
728728
{
729729
macro_t *ma = hashmap_get(MACROS_MAP, name);
730730
if (ma && !ma->disabled)
731731
return ma;
732732
return NULL;
733733
}
734734

735-
bool remove_macro(char *name)
735+
bool remove_macro(const char *name)
736736
{
737737
macro_t *ma = hashmap_get(MACROS_MAP, name);
738738
if (ma) {
@@ -749,7 +749,7 @@ string_pool_t *string_pool;
749749
string_literal_pool_t *string_literal_pool;
750750

751751
/* Safe string interning that works with self-hosting */
752-
char *intern_string(char *str)
752+
char *intern_string(const char *str)
753753
{
754754
char *existing;
755755
char *interned;
@@ -761,7 +761,7 @@ char *intern_string(char *str)
761761

762762
/* Safety: can't intern before initialization */
763763
if (!GENERAL_ARENA || !string_pool)
764-
return str;
764+
return (char *) str;
765765

766766
/* Check if already interned */
767767
existing = hashmap_get(string_pool->strings, str);
@@ -778,7 +778,7 @@ char *intern_string(char *str)
778778
return interned;
779779
}
780780

781-
int find_macro_param_src_idx(char *name, block_t *parent)
781+
int find_macro_param_src_idx(const char *name, block_t *parent)
782782
{
783783
macro_t *macro = parent->macro;
784784

@@ -811,7 +811,7 @@ type_t *add_named_type(char *name)
811811
return type;
812812
}
813813

814-
void add_constant(char alias[], int value)
814+
void add_constant(const char alias[], int value)
815815
{
816816
constant_t *constant = arena_alloc_constant();
817817
if (!constant) {
@@ -825,12 +825,12 @@ void add_constant(char alias[], int value)
825825
hashmap_put(CONSTANTS_MAP, alias, constant);
826826
}
827827

828-
constant_t *find_constant(char alias[])
828+
constant_t *find_constant(const char alias[])
829829
{
830830
return hashmap_get(CONSTANTS_MAP, alias);
831831
}
832832

833-
var_t *find_member(char token[], type_t *type)
833+
var_t *find_member(const char token[], type_t *type)
834834
{
835835
/* If it is a forwardly declared alias of a structure, switch to the base
836836
* structure type.
@@ -845,7 +845,7 @@ var_t *find_member(char token[], type_t *type)
845845
return NULL;
846846
}
847847

848-
var_t *find_local_var(char *token, block_t *block)
848+
var_t *find_local_var(const char *token, block_t *block)
849849
{
850850
func_t *func = block->func;
851851

@@ -866,7 +866,7 @@ var_t *find_local_var(char *token, block_t *block)
866866
return NULL;
867867
}
868868

869-
var_t *find_global_var(char *token)
869+
var_t *find_global_var(const char *token)
870870
{
871871
var_list_t *var_list = &GLOBAL_BLOCK->locals;
872872

@@ -877,7 +877,7 @@ var_t *find_global_var(char *token)
877877
return NULL;
878878
}
879879

880-
var_t *find_var(char *token, block_t *parent)
880+
var_t *find_var(const char *token, block_t *parent)
881881
{
882882
var_t *var = find_local_var(token, parent);
883883
if (!var)
@@ -915,7 +915,7 @@ int size_var(var_t *var)
915915
*
916916
* Return: A pointer to the function.
917917
*/
918-
func_t *add_func(char *func_name, bool synthesize)
918+
func_t *add_func(const char *func_name, bool synthesize)
919919
{
920920
func_t *func = hashmap_get(FUNC_MAP, func_name);
921921

@@ -947,7 +947,7 @@ func_t *add_func(char *func_name, bool synthesize)
947947
*
948948
* Return: A pointer to the function if exists, NULL otherwise.
949949
*/
950-
func_t *find_func(char *func_name)
950+
func_t *find_func(const char *func_name)
951951
{
952952
return hashmap_get(FUNC_MAP, func_name);
953953
}
@@ -1164,7 +1164,7 @@ bool strbuf_putc(strbuf_t *src, char value)
11641164
return true;
11651165
}
11661166

1167-
bool strbuf_puts(strbuf_t *src, char *value)
1167+
bool strbuf_puts(strbuf_t *src, const char *value)
11681168
{
11691169
int len = strlen(value);
11701170

src/lexer.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
/* Hash table constants */
1414
#define NUM_DIRECTIVES 11
15-
#define NUM_KEYWORDS 16
15+
#define NUM_KEYWORDS 17
1616

1717
/* Token mapping structure for elegant initialization */
1818
typedef struct {
@@ -86,6 +86,7 @@ void lex_init_keywords()
8686
{"default", T_default},
8787
{"continue", T_continue},
8888
{"union", T_union},
89+
{"const", T_const},
8990
};
9091

9192
/* hashmap insertion */
@@ -96,7 +97,7 @@ void lex_init_keywords()
9697
}
9798

9899
/* Hash table lookup for preprocessor directives */
99-
token_t lookup_directive(char *token)
100+
token_t lookup_directive(const char *token)
100101
{
101102
if (!DIRECTIVE_MAP)
102103
lex_init_directives();
@@ -109,7 +110,7 @@ token_t lookup_directive(char *token)
109110
}
110111

111112
/* Hash table lookup for C keywords */
112-
token_t lookup_keyword(char *token)
113+
token_t lookup_keyword(const char *token)
113114
{
114115
if (!KEYWORD_MAP)
115116
lex_init_keywords();
@@ -787,13 +788,15 @@ token_t lex_token_impl(bool aliasing)
787788
keyword = T_case;
788789
break;
789790

790-
case 5: /* 5-letter keywords: while, break, union */
791+
case 5: /* 5-letter keywords: while, break, union, const */
791792
if (token_str[0] == 'w' && !memcmp(token_str, "while", 5))
792793
keyword = T_while;
793794
else if (token_str[0] == 'b' && !memcmp(token_str, "break", 5))
794795
keyword = T_break;
795796
else if (token_str[0] == 'u' && !memcmp(token_str, "union", 5))
796797
keyword = T_union;
798+
else if (token_str[0] == 'c' && !memcmp(token_str, "const", 5))
799+
keyword = T_const;
797800
break;
798801

799802
case 6: /* 6-letter keywords: return, struct, switch, sizeof */

0 commit comments

Comments
 (0)