diff --git a/CMakeLists.txt b/CMakeLists.txt index a3cbf9e..9898440 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,10 +43,12 @@ add_executable( src/codegen.h src/identcheck.h src/parser.h + src/util.h src/ast.c src/codegen.c src/identcheck.c src/parser.c + src/util.c src/main.c # Generated code ${BISON_Parser_OUTPUTS} diff --git a/src/codegen.c b/src/codegen.c index bcc3eb4..f94e192 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -14,6 +14,7 @@ #include #include "ast.h" +#include "util.h" typedef struct LocalVariable { @@ -56,15 +57,11 @@ typedef struct StructTypeFunction uint8_t isStatic; } StructTypeFunction; -typedef struct StructTypeGenericFunction -{ - char *name; - Node *functionDeclarationNode; -} StructTypeGenericFunction; - typedef struct MonomorphizedGenericFunctionHashEntry { uint64_t key; + TypeTag **types; + uint32_t typeCount; StructTypeFunction function; } MonomorphizedGenericFunctionHashEntry; @@ -74,6 +71,17 @@ typedef struct MonomorphizedGenericFunctionHashArray uint32_t count; } MonomorphizedGenericFunctionHashArray; +#define NUM_MONOMORPHIZED_HASH_BUCKETS 1031 + +typedef struct StructTypeGenericFunction +{ + char *name; + Node *functionDeclarationNode; + uint8_t isStatic; + MonomorphizedGenericFunctionHashArray + monomorphizedFunctions[NUM_MONOMORPHIZED_HASH_BUCKETS]; +} StructTypeGenericFunction; + typedef struct StructTypeDeclaration { char *name; @@ -87,8 +95,6 @@ typedef struct StructTypeDeclaration StructTypeGenericFunction *genericFunctions; uint32_t genericFunctionCount; - - MonomorphizedGenericFunctionHashArray monomorphizedGenericFunctions; } StructTypeDeclaration; StructTypeDeclaration *structTypeDeclarations; @@ -296,8 +302,6 @@ static void AddStructDeclaration( structTypeDeclarations[index].functionCount = 0; structTypeDeclarations[index].genericFunctions = NULL; structTypeDeclarations[index].genericFunctionCount = 0; - structTypeDeclarations[index].monomorphizedGenericFunctions.elements = NULL; - structTypeDeclarations[index].monomorphizedGenericFunctions.count = 0; for (i = 0; i < fieldDeclarationCount; i += 1) { @@ -350,9 +354,10 @@ static void DeclareStructFunction( static void DeclareGenericStructFunction( LLVMTypeRef wStructPointerType, Node *functionDeclarationNode, + uint8_t isStatic, char *name) { - uint32_t i, index; + uint32_t i, j, index; for (i = 0; i < structTypeDeclarationCount; i += 1) { @@ -364,6 +369,21 @@ static void DeclareGenericStructFunction( structTypeDeclarations[i] .genericFunctions[index] .functionDeclarationNode = functionDeclarationNode; + structTypeDeclarations[i].genericFunctions[index].isStatic = + isStatic; + + for (j = 0; j < NUM_MONOMORPHIZED_HASH_BUCKETS; j += 1) + { + structTypeDeclarations[i] + .genericFunctions[index] + .monomorphizedFunctions[j] + .elements = NULL; + structTypeDeclarations[i] + .genericFunctions[index] + .monomorphizedFunctions[j] + .count = 0; + } + structTypeDeclarations[i].genericFunctionCount += 1; return; @@ -411,6 +431,20 @@ static LLVMTypeRef ResolveType(Node *typeNode) } } +static inline uint64_t HashTypeTags(TypeTag **tags, uint32_t count) +{ + const uint64_t HASH_FACTOR = 97; + uint64_t result = 1; + uint32_t i; + + for (i = 0; i < count; i += 1) + { + result *= HASH_FACTOR + str_hash(TypeTagToString(tags[i])); + } + + return result; +} + static LLVMValueRef LookupGenericFunction( StructTypeGenericFunction *genericFunction, TypeTag **genericArgumentTypes, @@ -418,8 +452,46 @@ static LLVMValueRef LookupGenericFunction( LLVMTypeRef *pReturnType, uint8_t *pStatic) { - /* TODO: hash the argument types */ - /* TODO: compile the monomorphism if doesnt exist */ + uint32_t i, j; + uint64_t typeHash = + HashTypeTags(genericArgumentTypes, genericArgumentTypeCount); + uint8_t match = 0; + + MonomorphizedGenericFunctionHashArray *hashArray = + &genericFunction->monomorphizedFunctions + [typeHash % NUM_MONOMORPHIZED_HASH_BUCKETS]; + + MonomorphizedGenericFunctionHashEntry *hashEntry = NULL; + for (i = 0; i < hashArray->count; i += 1) + { + match = 1; + + for (j = 0; j < hashArray->elements[i].typeCount; j += 1) + { + if (hashArray->elements[i].types[j] != genericArgumentTypes[j]) + { + match = 0; + break; + } + } + + if (match) + { + hashEntry = &hashArray->elements[i]; + break; + } + } + + if (hashEntry == NULL) + { + + /* TODO: compile */ + } + + *pReturnType = hashEntry->function.returnType; + *pStatic = hashEntry->function.isStatic; + + return hashEntry->function.function; } static LLVMValueRef LookupFunctionByType( @@ -1257,6 +1329,7 @@ static void CompileFunction( DeclareGenericStructFunction( wStructPointerType, functionDeclaration, + isStatic, functionName); } diff --git a/src/util.c b/src/util.c index 8001d03..aa5b4fb 100644 --- a/src/util.c +++ b/src/util.c @@ -1,7 +1,6 @@ #include "util.h" #include -#include char *strdup(const char *s) { @@ -15,3 +14,16 @@ char *strdup(const char *s) memcpy(result, s, slen + 1); return result; } + +uint64_t str_hash(char *str) +{ + uint64_t hash = 5381; + size_t c; + + while (c = *str++) + { + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + } + + return hash; +} diff --git a/src/util.h b/src/util.h index 884fa24..108211b 100644 --- a/src/util.h +++ b/src/util.h @@ -1,8 +1,10 @@ #ifndef WRAITH_UTIL_H #define WRAITH_UTIL_H +#include #include char *strdup(const char *s); +uint64_t str_hash(char *str); #endif /* WRAITH_UTIL_H */