Files
lc_lang/src/compiler/common.c
2024-04-13 15:29:53 +02:00

199 lines
5.5 KiB
C

#if __cplusplus
#define LC_Alignof(...) alignof(__VA_ARGS__)
#else
#define LC_Alignof(...) _Alignof(__VA_ARGS__)
#endif
#define LC_WRAP_AROUND_POWER_OF_2(x, pow2) (((x) & ((pow2)-1llu)))
#if defined(_MSC_VER)
#define LC_DebugBreak() (L->breakpoint_on_error && IsDebuggerPresent() && (__debugbreak(), 0))
#else
#define LC_DebugBreak() (L->breakpoint_on_error && (__builtin_trap(), 0))
#endif
#define LC_FatalError() (L->breakpoint_on_error ? LC_DebugBreak() : (LC_Exit(1), 0))
LC_FUNCTION void LC_IgnoreMessage(LC_Token *pos, char *str, int len) {
}
LC_FUNCTION void LC_SendErrorMessage(LC_Token *pos, LC_String s8) {
if (L->on_message) {
L->on_message(pos, s8.str, (int)s8.len);
} else {
if (pos) {
LC_String line = LC_GetTokenLine(pos);
LC_String fmt = LC_Format(L->arena, "%s(%d,%d): error: %.*s\n%.*s", (char *)pos->lex->file, pos->line, pos->column, LC_Expand(s8), LC_Expand(line));
LC_Print(fmt.str, fmt.len);
} else {
LC_Print(s8.str, s8.len);
}
}
LC_DebugBreak();
}
LC_FUNCTION void LC_SendErrorMessagef(LC_Lex *x, LC_Token *pos, const char *str, ...) {
LC_FORMAT(L->arena, str, s8);
LC_SendErrorMessage(pos, s8);
}
LC_FUNCTION void LC_HandleFatalError(void) {
if (L->on_fatal_error) {
L->on_fatal_error();
return;
}
LC_FatalError();
}
LC_FUNCTION void LC_MapReserve(LC_Map *map, int size) {
LC_Map old_map = *map;
LC_ASSERT(NULL, LC_IS_POW2(size));
map->len = 0;
map->cap = size;
LC_ASSERT(NULL, map->arena);
map->entries = LC_PushArray(map->arena, LC_MapEntry, map->cap);
if (old_map.entries) {
for (int i = 0; i < old_map.cap; i += 1) {
LC_MapEntry *it = old_map.entries + i;
if (it->key) LC_InsertMapEntry(map, it->key, it->value);
}
}
}
// FNV HASH (1a?)
LC_FUNCTION uint64_t LC_HashBytes(void *data, uint64_t size) {
uint8_t *data8 = (uint8_t *)data;
uint64_t hash = (uint64_t)14695981039346656037ULL;
for (uint64_t i = 0; i < size; i++) {
hash = hash ^ (uint64_t)(data8[i]);
hash = hash * (uint64_t)1099511628211ULL;
}
return hash;
}
LC_FUNCTION uint64_t LC_HashMix(uint64_t x, uint64_t y) {
x ^= y;
x *= 0xff51afd7ed558ccd;
x ^= x >> 32;
return x;
}
LC_FUNCTION int LC_NextPow2(int v) {
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
LC_FUNCTION LC_MapEntry *LC_GetMapEntryEx(LC_Map *map, uint64_t key) {
LC_ASSERT(NULL, key);
if (map->len * 2 >= map->cap) {
LC_MapReserve(map, map->cap * 2);
}
uint64_t hash = LC_HashBytes(&key, sizeof(key));
if (hash == 0) hash += 1;
uint64_t index = LC_WRAP_AROUND_POWER_OF_2(hash, map->cap);
uint64_t i = index;
for (;;) {
LC_MapEntry *it = map->entries + i;
if (it->key == key || it->key == 0) {
return it;
}
i = LC_WRAP_AROUND_POWER_OF_2(i + 1, map->cap);
if (i == index) return NULL;
}
LC_ASSERT(NULL, !"invalid codepath");
}
LC_FUNCTION bool LC_InsertWithoutReplace(LC_Map *map, void *key, void *value) {
LC_MapEntry *entry = LC_GetMapEntryEx(map, (uint64_t)key);
if (entry->key != 0) return false;
map->len += 1;
entry->key = (uint64_t)key;
entry->value = (uint64_t)value;
return true;
}
LC_FUNCTION LC_MapEntry *LC_InsertMapEntry(LC_Map *map, uint64_t key, uint64_t value) {
LC_MapEntry *entry = LC_GetMapEntryEx(map, key);
if (entry->key == key) {
entry->value = value;
}
if (entry->key == 0) {
entry->key = key;
entry->value = value;
map->len += 1;
}
return entry;
}
LC_FUNCTION LC_MapEntry *LC_GetMapEntry(LC_Map *map, uint64_t key) {
LC_MapEntry *entry = LC_GetMapEntryEx(map, key);
if (entry && entry->key == key) {
return entry;
}
return NULL;
}
LC_FUNCTION void LC_MapInsert(LC_Map *map, LC_String keystr, void *value) {
uint64_t key = LC_HashBytes(keystr.str, keystr.len);
LC_InsertMapEntry(map, key, (uint64_t)value);
}
LC_FUNCTION void *LC_MapGet(LC_Map *map, LC_String keystr) {
uint64_t key = LC_HashBytes(keystr.str, keystr.len);
LC_MapEntry *r = LC_GetMapEntry(map, key);
return r ? (void *)r->value : 0;
}
LC_FUNCTION void LC_MapInsertU64(LC_Map *map, uint64_t key, void *value) {
LC_InsertMapEntry(map, key, (uint64_t)value);
}
LC_FUNCTION void *LC_MapGetU64(LC_Map *map, uint64_t key) {
LC_MapEntry *r = LC_GetMapEntry(map, key);
return r ? (void *)r->value : 0;
}
LC_FUNCTION void *LC_MapGetP(LC_Map *map, void *key) {
return LC_MapGetU64(map, (uint64_t)key);
}
LC_FUNCTION void LC_MapInsertP(LC_Map *map, void *key, void *value) {
LC_InsertMapEntry(map, (uint64_t)key, (uint64_t)value);
}
LC_FUNCTION void LC_MapClear(LC_Map *map) {
if (map->len != 0) LC_MemoryZero(map->entries, map->cap * sizeof(LC_MapEntry));
map->len = 0;
}
LC_FUNCTION size_t LC_GetAlignOffset(size_t size, size_t align) {
size_t mask = align - 1;
size_t val = size & mask;
if (val) {
val = align - val;
}
return val;
}
LC_FUNCTION size_t LC_AlignUp(size_t size, size_t align) {
size_t result = size + LC_GetAlignOffset(size, align);
return result;
}
LC_FUNCTION size_t LC_AlignDown(size_t size, size_t align) {
size += 1; // Make sure when align is 8 doesn't get rounded down to 0
size_t result = size - (align - LC_GetAlignOffset(size, align));
return result;
}