141 lines
3.2 KiB
C
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);
|
|
}
|