@@ -32,7 +32,12 @@ int global_ir_idx = 0;
3232ph1_ir_t * PH1_IR ;
3333int ph1_ir_idx = 0 ;
3434
35- ph2_ir_t * PH2_IR ;
35+ arena_t * INSN_ARENA ;
36+
37+ /* BB_ARENA is responsible for basic_block_t / ph2_ir_t allocation */
38+ arena_t * BB_ARENA ;
39+
40+ ph2_ir_t * * PH2_IR_FLATTEN ;
3641int ph2_ir_idx = 0 ;
3742
3843label_lut_t * LABEL_LUT ;
@@ -69,6 +74,121 @@ char *elf_symtab;
6974char * elf_strtab ;
7075char * elf_section ;
7176
77+ /**
78+ * arena_block_create() - creates a new arena block with given capacity.
79+ * The created arena block is guaranteed to be zero-initialized.
80+ * @capacity: The capacity of the arena block. Must be positive.
81+ *
82+ * Return: The pointer of created arena block. NULL if failed to allocate.
83+ */
84+ arena_block_t * arena_block_create (int capacity )
85+ {
86+ arena_block_t * block = malloc (sizeof (arena_block_t ));
87+
88+ if (!block ) {
89+ printf ("Failed to allocate memory for arena block\n" );
90+ exit (1 );
91+ }
92+
93+ block -> memory = calloc (capacity , sizeof (char ));
94+
95+ if (!block -> memory ) {
96+ printf ("Failed to allocate memory for arena block\n" );
97+ free (block );
98+ exit (1 );
99+ }
100+
101+ block -> capacity = capacity ;
102+ block -> offset = 0 ;
103+ block -> next = NULL ;
104+ return block ;
105+ }
106+
107+ /**
108+ * arena_init() - initializes the given arena with initial capacity.
109+ * @initial_capacity: The initial capacity of the arena. Must be positive.
110+ *
111+ * Return: The pointer of initialized arena.
112+ */
113+ arena_t * arena_init (int initial_capacity )
114+ {
115+ arena_t * arena = malloc (sizeof (arena_t ));
116+ arena -> head = arena_block_create (initial_capacity );
117+ return arena ;
118+ }
119+
120+ /**
121+ * arena_alloc() - allocates memory from the given arena with given size.
122+ * The arena may create a new arena block if no space is available.
123+ * @arena: The arena to allocate memory from. Must not be NULL.
124+ * @size: The size of memory to allocate. Must be positive.
125+ *
126+ * Return: The pointer of allocated memory. NULL if new arena block is failed to
127+ * allocate.
128+ */
129+ void * arena_alloc (arena_t * arena , int size )
130+ {
131+ char * ptr ;
132+ arena_block_t * block = arena -> head ;
133+
134+ while (block ) {
135+ if (block -> offset + size <= block -> capacity ) {
136+ ptr = block -> memory + block -> offset ;
137+ block -> offset += size ;
138+ return ptr ;
139+ }
140+ if (!block -> next )
141+ break ;
142+ block = block -> next ;
143+ }
144+
145+ /* If no space is available, create a new block
146+ * Allocate at least 256 KiB or the requested size
147+ */
148+ int new_capacity = size > DEFAULT_ARENA_SIZE ? size : DEFAULT_ARENA_SIZE ;
149+ arena_block_t * new_block = arena_block_create (new_capacity );
150+
151+ if (!new_block )
152+ return NULL ;
153+
154+ block -> next = new_block ;
155+ ptr = new_block -> memory + new_block -> offset ;
156+ new_block -> offset += size ;
157+ return ptr ;
158+ }
159+
160+ /**
161+ * arena_reset() - resets the given arena by resetting all blocks' offset to 0.
162+ * @arena: The arena to reset. Must not be NULL.
163+ */
164+ void arena_reset (arena_t * arena )
165+ {
166+ arena_block_t * block = arena -> head ;
167+
168+ while (block ) {
169+ block -> offset = 0 ;
170+ block = block -> next ;
171+ }
172+ }
173+
174+ /**
175+ * arena_free() - frees the given arena and all its blocks.
176+ * @arena: The arena to free. Must not be NULL.
177+ */
178+ void arena_free (arena_t * arena )
179+ {
180+ arena_block_t * block = arena -> head , * next ;
181+
182+ while (block ) {
183+ next = block -> next ;
184+ free (block -> memory );
185+ free (block );
186+ block = next ;
187+ }
188+
189+ free (arena );
190+ }
191+
72192/**
73193 * hashmap_hash_index() - hashses a string with FNV-1a hash function
74194 * and converts into usable hashmap index. The range of returned
@@ -312,11 +432,17 @@ ph1_ir_t *add_ph1_ir(opcode_t op)
312432 return ph1_ir ;
313433}
314434
435+ ph2_ir_t * add_existed_ph2_ir (ph2_ir_t * ph2_ir )
436+ {
437+ PH2_IR_FLATTEN [ph2_ir_idx ++ ] = ph2_ir ;
438+ return ph2_ir ;
439+ }
440+
315441ph2_ir_t * add_ph2_ir (opcode_t op )
316442{
317- ph2_ir_t * ph2_ir = & PH2_IR [ ph2_ir_idx ++ ] ;
443+ ph2_ir_t * ph2_ir = arena_alloc ( BB_ARENA , sizeof ( ph2_ir_t )) ;
318444 ph2_ir -> op = op ;
319- return ph2_ir ;
445+ return add_existed_ph2_ir ( ph2_ir ) ;
320446}
321447
322448void set_var_liveout (var_t * var , int end )
@@ -579,7 +705,7 @@ fn_t *add_fn()
579705/* Create a basic block and set the scope of variables to 'parent' block */
580706basic_block_t * bb_create (block_t * parent )
581707{
582- basic_block_t * bb = calloc ( 1 , sizeof (basic_block_t ));
708+ basic_block_t * bb = arena_alloc ( BB_ARENA , sizeof (basic_block_t ));
583709
584710 for (int i = 0 ; i < MAX_BB_PRED ; i ++ ) {
585711 bb -> prev [i ].bb = NULL ;
@@ -691,7 +817,7 @@ void add_insn(block_t *block,
691817
692818 bb -> scope = block ;
693819
694- insn_t * n = calloc ( 1 , sizeof (insn_t ));
820+ insn_t * n = arena_alloc ( INSN_ARENA , sizeof (insn_t ));
695821 n -> opcode = op ;
696822 n -> rd = rd ;
697823 n -> rs1 = rs1 ;
@@ -725,7 +851,9 @@ void global_init()
725851 TYPES = malloc (MAX_TYPES * sizeof (type_t ));
726852 GLOBAL_IR = malloc (MAX_GLOBAL_IR * sizeof (ph1_ir_t ));
727853 PH1_IR = malloc (MAX_IR_INSTR * sizeof (ph1_ir_t ));
728- PH2_IR = malloc (MAX_IR_INSTR * sizeof (ph2_ir_t ));
854+ INSN_ARENA = arena_init (DEFAULT_ARENA_SIZE );
855+ BB_ARENA = arena_init (DEFAULT_ARENA_SIZE );
856+ PH2_IR_FLATTEN = malloc (MAX_IR_INSTR * sizeof (ph2_ir_t * ));
729857 LABEL_LUT = malloc (MAX_LABEL * sizeof (label_lut_t ));
730858 SOURCE = malloc (MAX_SOURCE );
731859 ALIASES = malloc (MAX_ALIASES * sizeof (alias_t ));
@@ -755,7 +883,9 @@ void global_release()
755883 free (TYPES );
756884 free (GLOBAL_IR );
757885 free (PH1_IR );
758- free (PH2_IR );
886+ arena_free (INSN_ARENA );
887+ arena_free (BB_ARENA );
888+ free (PH2_IR_FLATTEN );
759889 free (LABEL_LUT );
760890 free (SOURCE );
761891 free (ALIASES );
0 commit comments