Init new repository
This commit is contained in:
198
src/compiler/common.c
Normal file
198
src/compiler/common.c
Normal file
@@ -0,0 +1,198 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user