Files
fz-lang/src/compiler/utils/fzl_const_pool.c
T

141 lines
3.2 KiB
C

#include <compiler/utils/fzl_const_pool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
bool fzl_consts_equal(fzl_const_t a, fzl_const_t b)
{
if (a.type != b.type)
return false;
switch (a.type)
{
case FZL_CONSTTYPE_STRING:
{
if (a.as.string.length != b.as.string.length)
return false;
return memcmp(a.as.string.chars, b.as.string.chars, a.as.string.length) ==
0;
}
}
return false;
}
uint32_t fzl_hash_const(fzl_const_t c)
{
uint32_t hash = 2166136261u;
const uint8_t *data = NULL;
size_t size = 0;
switch (c.type)
{
case FZL_CONSTTYPE_STRING:
data = (const uint8_t *)c.as.string.chars;
size = c.as.string.length;
break;
}
for (size_t i = 0; i < size; i++)
{
hash ^= data[i];
hash *= 16777619u;
}
return hash;
}
fzl_const_hash_pool_t *fzl_mkconstpool()
{
fzl_const_hash_pool_t *pool = malloc(sizeof(fzl_const_hash_pool_t));
pool->size = 0;
pool->capacity = 8;
pool->array = malloc(pool->capacity * sizeof(fzl_const_t));
pool->slots_count = 0;
pool->slots_capacity = 16;
pool->slots = malloc(pool->slots_capacity * sizeof(fzl_const_hash_slot_t));
for (size_t i = 0; i < pool->slots_capacity; i++)
pool->slots[i].pool_index = -1;
return pool;
}
void fzl_consts_pool_resize_hash(fzl_const_hash_pool_t *pool)
{
int old_capacity = pool->slots_capacity;
fzl_const_hash_slot_t *old_slots = pool->slots;
pool->slots_capacity = old_capacity * 2;
pool->slots = malloc(pool->slots_capacity * sizeof(fzl_const_hash_slot_t));
for (size_t i = 0; i < pool->slots_capacity; i++)
pool->slots[i].pool_index = -1;
pool->slots_count = 0;
for (int i = 0; i < old_capacity; i++)
{
if (old_slots[i].pool_index == -1)
continue;
int index_in_pool = old_slots[i].pool_index;
fzl_const_t c = pool->array[index_in_pool];
uint32_t hash = fzl_hash_const(c);
uint32_t bucket = hash & (pool->slots_capacity - 1);
while (pool->slots[bucket].pool_index != -1)
bucket = (bucket + 1) & (pool->slots_capacity - 1);
pool->slots[bucket].pool_index = index_in_pool;
pool->slots_count++;
}
free(old_slots);
}
size_t fzl_consts_pool_add(fzl_const_hash_pool_t *pool, fzl_const_t c)
{
if (pool->slots_count * 4 >= pool->slots_capacity * 3)
fzl_consts_pool_resize_hash(pool);
uint32_t hash = fzl_hash_const(c);
uint32_t bucket = hash & (pool->slots_capacity - 1);
while (pool->slots[bucket].pool_index != -1)
{
size_t existing_index = pool->slots[bucket].pool_index;
if (fzl_consts_equal(pool->array[existing_index], c))
return existing_index;
bucket = (bucket + 1) & (pool->slots_capacity - 1);
}
if (pool->size >= pool->capacity)
{
pool->capacity *= 2;
pool->array = (fzl_const_t *)realloc(pool->array,
pool->capacity * sizeof(fzl_const_t));
}
size_t new_index = pool->size;
pool->array[new_index] = c;
pool->size++;
pool->slots[bucket].pool_index = new_index;
pool->slots_count++;
return new_index;
}
void fzl_consts_pool_free(fzl_const_hash_pool_t *pool)
{
if (!pool)
return;
free(pool->array);
free(pool->slots);
free(pool);
}