progress on generics
							parent
							
								
									8a3920918c
								
							
						
					
					
						commit
						d641f713de
					
				|  | @ -740,6 +740,10 @@ TypeTag *MakeTypeTag(Node *node) | |||
|                               ->functionSignature.type); | ||||
|         break; | ||||
| 
 | ||||
|     case AllocExpression: | ||||
|         tag = MakeTypeTag(node->allocExpression.type); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         fprintf( | ||||
|             stderr, | ||||
|  |  | |||
							
								
								
									
										526
									
								
								src/codegen.c
								
								
								
								
							
							
						
						
									
										526
									
								
								src/codegen.c
								
								
								
								
							|  | @ -23,6 +23,12 @@ typedef struct LocalVariable | |||
|     LLVMValueRef value; | ||||
| } LocalVariable; | ||||
| 
 | ||||
| typedef struct LocalGenericType | ||||
| { | ||||
|     char *name; | ||||
|     LLVMTypeRef type; | ||||
| } LocalGenericType; | ||||
| 
 | ||||
| typedef struct FunctionArgument | ||||
| { | ||||
|     char *name; | ||||
|  | @ -33,6 +39,9 @@ typedef struct ScopeFrame | |||
| { | ||||
|     LocalVariable *localVariables; | ||||
|     uint32_t localVariableCount; | ||||
| 
 | ||||
|     LocalGenericType *genericTypes; | ||||
|     uint32_t genericTypeCount; | ||||
| } ScopeFrame; | ||||
| 
 | ||||
| typedef struct Scope | ||||
|  | @ -75,6 +84,8 @@ typedef struct MonomorphizedGenericFunctionHashArray | |||
| 
 | ||||
| typedef struct StructTypeGenericFunction | ||||
| { | ||||
|     char *parentStructName; | ||||
|     LLVMTypeRef parentStructPointerType; | ||||
|     char *name; | ||||
|     Node *functionDeclarationNode; | ||||
|     uint8_t isStatic; | ||||
|  | @ -100,6 +111,18 @@ typedef struct StructTypeDeclaration | |||
| StructTypeDeclaration *structTypeDeclarations; | ||||
| uint32_t structTypeDeclarationCount; | ||||
| 
 | ||||
| /* FUNCTION FORWARD DECLARATIONS */ | ||||
| static LLVMBasicBlockRef CompileStatement( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMBuilderRef builder, | ||||
|     LLVMValueRef function, | ||||
|     Node *statement); | ||||
| 
 | ||||
| static LLVMValueRef CompileExpression( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMBuilderRef builder, | ||||
|     Node *expression); | ||||
| 
 | ||||
| static Scope *CreateScope() | ||||
| { | ||||
|     Scope *scope = malloc(sizeof(Scope)); | ||||
|  | @ -107,6 +130,8 @@ static Scope *CreateScope() | |||
|     scope->scopeStack = malloc(sizeof(ScopeFrame)); | ||||
|     scope->scopeStack[0].localVariableCount = 0; | ||||
|     scope->scopeStack[0].localVariables = NULL; | ||||
|     scope->scopeStack[0].genericTypeCount = 0; | ||||
|     scope->scopeStack[0].genericTypes = NULL; | ||||
|     scope->scopeStackCount = 1; | ||||
| 
 | ||||
|     return scope; | ||||
|  | @ -120,6 +145,8 @@ static void PushScopeFrame(Scope *scope) | |||
|         sizeof(ScopeFrame) * (scope->scopeStackCount + 1)); | ||||
|     scope->scopeStack[index].localVariableCount = 0; | ||||
|     scope->scopeStack[index].localVariables = NULL; | ||||
|     scope->scopeStack[index].genericTypeCount = 0; | ||||
|     scope->scopeStack[index].genericTypes = NULL; | ||||
| 
 | ||||
|     scope->scopeStackCount += 1; | ||||
| } | ||||
|  | @ -138,31 +165,21 @@ static void PopScopeFrame(Scope *scope) | |||
|         free(scope->scopeStack[index].localVariables); | ||||
|     } | ||||
| 
 | ||||
|     if (scope->scopeStack[index].genericTypes != NULL) | ||||
|     { | ||||
|         for (i = 0; i < scope->scopeStack[index].genericTypeCount; i += 1) | ||||
|         { | ||||
|             free(scope->scopeStack[index].genericTypes[i].name); | ||||
|         } | ||||
|         free(scope->scopeStack[index].localVariables); | ||||
|     } | ||||
| 
 | ||||
|     scope->scopeStackCount -= 1; | ||||
| 
 | ||||
|     scope->scopeStack = | ||||
|         realloc(scope->scopeStack, sizeof(ScopeFrame) * scope->scopeStackCount); | ||||
| } | ||||
| 
 | ||||
| static void AddLocalVariable( | ||||
|     Scope *scope, | ||||
|     LLVMValueRef pointer, /* can be NULL */ | ||||
|     LLVMValueRef value,   /* can be NULL */ | ||||
|     char *name) | ||||
| { | ||||
|     ScopeFrame *scopeFrame = &scope->scopeStack[scope->scopeStackCount - 1]; | ||||
|     uint32_t index = scopeFrame->localVariableCount; | ||||
| 
 | ||||
|     scopeFrame->localVariables = realloc( | ||||
|         scopeFrame->localVariables, | ||||
|         sizeof(LocalVariable) * (scopeFrame->localVariableCount + 1)); | ||||
|     scopeFrame->localVariables[index].name = strdup(name); | ||||
|     scopeFrame->localVariables[index].pointer = pointer; | ||||
|     scopeFrame->localVariables[index].value = value; | ||||
| 
 | ||||
|     scopeFrame->localVariableCount += 1; | ||||
| } | ||||
| 
 | ||||
| static LLVMTypeRef WraithTypeToLLVMType(PrimitiveType type) | ||||
| { | ||||
|     switch (type) | ||||
|  | @ -184,6 +201,120 @@ static LLVMTypeRef WraithTypeToLLVMType(PrimitiveType type) | |||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| static LLVMTypeRef LookupCustomType(char *name) | ||||
| { | ||||
|     int32_t i, j; | ||||
| 
 | ||||
|     for (i = scope->scopeStackCount - 1; i >= 0; i -= 1) | ||||
|     { | ||||
|         for (j = 0; j < scope->scopeStack[i].genericTypeCount; j += 1) | ||||
|         { | ||||
|             if (strcmp(scope->scopeStack[i].genericTypes[j].name, name) == 0) | ||||
|             { | ||||
|                 return scope->scopeStack[i].genericTypes[j].type; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     for (i = 0; i < structTypeDeclarationCount; i += 1) | ||||
|     { | ||||
|         if (strcmp(structTypeDeclarations[i].name, name) == 0) | ||||
|         { | ||||
|             return structTypeDeclarations[i].structType; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fprintf(stderr, "Could not find struct type!\n"); | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| static LLVMTypeRef ResolveType(TypeTag *typeTag) | ||||
| { | ||||
|     if (typeTag->type == Primitive) | ||||
|     { | ||||
|         return WraithTypeToLLVMType(typeTag->value.primitiveType); | ||||
|     } | ||||
|     else if (typeTag->type == Custom) | ||||
|     { | ||||
|         return LookupCustomType(typeTag->value.customType); | ||||
|     } | ||||
|     else if (typeTag->type == Reference) | ||||
|     { | ||||
|         return LLVMPointerType(ResolveType(typeTag->value.referenceType), 0); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         fprintf(stderr, "Unknown type node!\n"); | ||||
|         return NULL; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void AddLocalVariable( | ||||
|     Scope *scope, | ||||
|     LLVMValueRef pointer, /* can be NULL */ | ||||
|     LLVMValueRef value,   /* can be NULL */ | ||||
|     char *name) | ||||
| { | ||||
|     ScopeFrame *scopeFrame = &scope->scopeStack[scope->scopeStackCount - 1]; | ||||
|     uint32_t index = scopeFrame->localVariableCount; | ||||
| 
 | ||||
|     scopeFrame->localVariables = realloc( | ||||
|         scopeFrame->localVariables, | ||||
|         sizeof(LocalVariable) * (scopeFrame->localVariableCount + 1)); | ||||
|     scopeFrame->localVariables[index].name = strdup(name); | ||||
|     scopeFrame->localVariables[index].pointer = pointer; | ||||
|     scopeFrame->localVariables[index].value = value; | ||||
| 
 | ||||
|     scopeFrame->localVariableCount += 1; | ||||
| } | ||||
| 
 | ||||
| static void AddGenericVariable(Scope *scope, TypeTag *typeTag, char *name) | ||||
| { | ||||
|     ScopeFrame *scopeFrame = &scope->scopeStack[scope->scopeStackCount - 1]; | ||||
|     uint32_t index = scopeFrame->genericTypeCount; | ||||
| 
 | ||||
|     scopeFrame->genericTypes = realloc( | ||||
|         scopeFrame->genericTypes, | ||||
|         sizeof(LocalGenericType) * (scopeFrame->genericTypeCount + 1)); | ||||
|     scopeFrame->genericTypes[index].name = strdup(name); | ||||
|     scopeFrame->genericTypes[index].type = ResolveType(typeTag); | ||||
| 
 | ||||
|     scopeFrame->genericTypeCount += 1; | ||||
| } | ||||
| 
 | ||||
| static void AddStructVariablesToScope( | ||||
|     LLVMBuilderRef builder, | ||||
|     LLVMValueRef structPointer) | ||||
| { | ||||
|     uint32_t i, j; | ||||
| 
 | ||||
|     for (i = 0; i < structTypeDeclarationCount; i += 1) | ||||
|     { | ||||
|         if (structTypeDeclarations[i].structPointerType == | ||||
|             LLVMTypeOf(structPointer)) | ||||
|         { | ||||
|             for (j = 0; j < structTypeDeclarations[i].fieldCount; j += 1) | ||||
|             { | ||||
|                 char *ptrName = | ||||
|                     strdup(structTypeDeclarations[i].fields[j].name); | ||||
|                 strcat(ptrName, "_ptr"); | ||||
|                 LLVMValueRef elementPointer = LLVMBuildStructGEP( | ||||
|                     builder, | ||||
|                     structPointer, | ||||
|                     structTypeDeclarations[i].fields[j].index, | ||||
|                     ptrName); | ||||
|                 free(ptrName); | ||||
| 
 | ||||
|                 AddLocalVariable( | ||||
|                     scope, | ||||
|                     elementPointer, | ||||
|                     NULL, | ||||
|                     structTypeDeclarations[i].fields[j].name); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static LLVMTypeRef FindStructType(char *name) | ||||
| { | ||||
|     uint32_t i; | ||||
|  | @ -355,6 +486,7 @@ static void DeclareGenericStructFunction( | |||
|     LLVMTypeRef wStructPointerType, | ||||
|     Node *functionDeclarationNode, | ||||
|     uint8_t isStatic, | ||||
|     char *parentStructName, | ||||
|     char *name) | ||||
| { | ||||
|     uint32_t i, j, index; | ||||
|  | @ -364,8 +496,15 @@ static void DeclareGenericStructFunction( | |||
|         if (structTypeDeclarations[i].structPointerType == wStructPointerType) | ||||
|         { | ||||
|             index = structTypeDeclarations[i].genericFunctionCount; | ||||
|             structTypeDeclarations[i].genericFunctions = realloc( | ||||
|                 structTypeDeclarations[i].genericFunctions, | ||||
|                 sizeof(StructTypeGenericFunction) * | ||||
|                     (structTypeDeclarations[i].genericFunctionCount + 1)); | ||||
|             structTypeDeclarations[i].genericFunctions[index].name = | ||||
|                 strdup(name); | ||||
|             structTypeDeclarations[i].genericFunctions[index].parentStructName = | ||||
|                 parentStructName; | ||||
|             structTypeDeclarations[i].structPointerType = wStructPointerType; | ||||
|             structTypeDeclarations[i] | ||||
|                 .genericFunctions[index] | ||||
|                 .functionDeclarationNode = functionDeclarationNode; | ||||
|  | @ -391,46 +530,6 @@ static void DeclareGenericStructFunction( | |||
|     } | ||||
| } | ||||
| 
 | ||||
| static LLVMTypeRef LookupCustomType(char *name) | ||||
| { | ||||
|     uint32_t i; | ||||
| 
 | ||||
|     for (i = 0; i < structTypeDeclarationCount; i += 1) | ||||
|     { | ||||
|         if (strcmp(structTypeDeclarations[i].name, name) == 0) | ||||
|         { | ||||
|             return structTypeDeclarations[i].structType; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fprintf(stderr, "Could not find struct type!\n"); | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| static LLVMTypeRef ResolveType(Node *typeNode) | ||||
| { | ||||
|     if (IsPrimitiveType(typeNode)) | ||||
|     { | ||||
|         return WraithTypeToLLVMType( | ||||
|             typeNode->type.typeNode->primitiveType.type); | ||||
|     } | ||||
|     else if (typeNode->type.typeNode->syntaxKind == CustomTypeNode) | ||||
|     { | ||||
|         return LookupCustomType(typeNode->type.typeNode->customType.name); | ||||
|     } | ||||
|     else if (typeNode->type.typeNode->syntaxKind == ReferenceTypeNode) | ||||
|     { | ||||
|         return LLVMPointerType( | ||||
|             ResolveType(typeNode->type.typeNode->referenceType.type), | ||||
|             0); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         fprintf(stderr, "Unknown type node!\n"); | ||||
|         return NULL; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static inline uint64_t HashTypeTags(TypeTag **tags, uint32_t count) | ||||
| { | ||||
|     const uint64_t HASH_FACTOR = 97; | ||||
|  | @ -445,7 +544,159 @@ static inline uint64_t HashTypeTags(TypeTag **tags, uint32_t count) | |||
|     return result; | ||||
| } | ||||
| 
 | ||||
| static StructTypeFunction CompileGenericFunction( | ||||
|     LLVMModuleRef module, | ||||
|     char *parentStructName, | ||||
|     LLVMTypeRef wStructPointerType, | ||||
|     TypeTag **genericArgumentTypes, | ||||
|     uint32_t genericArgumentTypeCount, | ||||
|     Node *functionDeclaration) | ||||
| { | ||||
|     uint32_t i; | ||||
|     uint8_t hasReturn = 0; | ||||
|     uint8_t isStatic = 0; | ||||
|     Node *functionSignature = | ||||
|         functionDeclaration->functionDeclaration.functionSignature; | ||||
|     Node *functionBody = functionDeclaration->functionDeclaration.functionBody; | ||||
|     uint32_t argumentCount = functionSignature->functionSignature.arguments | ||||
|                                  ->functionSignatureArguments.count; | ||||
|     LLVMTypeRef paramTypes[argumentCount + 1]; | ||||
|     uint32_t paramIndex = 0; | ||||
| 
 | ||||
|     PushScopeFrame(scope); | ||||
| 
 | ||||
|     for (i = 0; i < genericArgumentTypeCount; i += 1) | ||||
|     { | ||||
|         AddGenericVariable( | ||||
|             scope, | ||||
|             genericArgumentTypes[i], | ||||
|             functionDeclaration->functionDeclaration.functionSignature | ||||
|                 ->functionSignature.genericArguments->genericArguments | ||||
|                 .arguments[i] | ||||
|                 ->genericArgument.identifier->identifier.name); | ||||
|     } | ||||
| 
 | ||||
|     if (functionSignature->functionSignature.modifiers->functionModifiers | ||||
|             .count > 0) | ||||
|     { | ||||
|         for (i = 0; i < functionSignature->functionSignature.modifiers | ||||
|                             ->functionModifiers.count; | ||||
|              i += 1) | ||||
|         { | ||||
|             if (functionSignature->functionSignature.modifiers | ||||
|                     ->functionModifiers.sequence[i] | ||||
|                     ->syntaxKind == StaticModifier) | ||||
|             { | ||||
|                 isStatic = 1; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     char *functionName = strdup(parentStructName); | ||||
|     strcat(functionName, "_"); | ||||
|     strcat( | ||||
|         functionName, | ||||
|         functionSignature->functionSignature.identifier->identifier.name); | ||||
| 
 | ||||
|     for (i = 0; i < genericArgumentTypeCount; i += 1) | ||||
|     { | ||||
|         strcat(functionName, TypeTagToString(genericArgumentTypes[i])); | ||||
|     } | ||||
| 
 | ||||
|     if (!isStatic) | ||||
|     { | ||||
|         paramTypes[paramIndex] = wStructPointerType; | ||||
|         paramIndex += 1; | ||||
|     } | ||||
| 
 | ||||
|     for (i = 0; i < functionSignature->functionSignature.arguments | ||||
|                         ->functionSignatureArguments.count; | ||||
|          i += 1) | ||||
|     { | ||||
|         paramTypes[paramIndex] = | ||||
|             ResolveType(functionSignature->functionSignature.arguments | ||||
|                             ->functionSignatureArguments.sequence[i] | ||||
|                             ->declaration.identifier->typeTag); | ||||
|         paramIndex += 1; | ||||
|     } | ||||
| 
 | ||||
|     LLVMTypeRef returnType = | ||||
|         ResolveType(functionSignature->functionSignature.identifier->typeTag); | ||||
|     LLVMTypeRef functionType = | ||||
|         LLVMFunctionType(returnType, paramTypes, paramIndex, 0); | ||||
| 
 | ||||
|     LLVMValueRef function = LLVMAddFunction(module, functionName, functionType); | ||||
| 
 | ||||
|     LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry"); | ||||
|     LLVMBuilderRef builder = LLVMCreateBuilder(); | ||||
|     LLVMPositionBuilderAtEnd(builder, entry); | ||||
| 
 | ||||
|     if (!isStatic) | ||||
|     { | ||||
|         LLVMValueRef wStructPointer = LLVMGetParam(function, 0); | ||||
|         AddStructVariablesToScope(builder, wStructPointer); | ||||
|     } | ||||
| 
 | ||||
|     for (i = 0; i < functionSignature->functionSignature.arguments | ||||
|                         ->functionSignatureArguments.count; | ||||
|          i += 1) | ||||
|     { | ||||
|         char *ptrName = strdup(functionSignature->functionSignature.arguments | ||||
|                                    ->functionSignatureArguments.sequence[i] | ||||
|                                    ->declaration.identifier->identifier.name); | ||||
|         strcat(ptrName, "_ptr"); | ||||
|         LLVMValueRef argument = LLVMGetParam(function, i + !isStatic); | ||||
|         LLVMValueRef argumentCopy = | ||||
|             LLVMBuildAlloca(builder, LLVMTypeOf(argument), ptrName); | ||||
|         LLVMBuildStore(builder, argument, argumentCopy); | ||||
|         free(ptrName); | ||||
|         AddLocalVariable( | ||||
|             scope, | ||||
|             argumentCopy, | ||||
|             NULL, | ||||
|             functionSignature->functionSignature.arguments | ||||
|                 ->functionSignatureArguments.sequence[i] | ||||
|                 ->declaration.identifier->identifier.name); | ||||
|     } | ||||
| 
 | ||||
|     for (i = 0; i < functionBody->statementSequence.count; i += 1) | ||||
|     { | ||||
|         CompileStatement( | ||||
|             module, | ||||
|             builder, | ||||
|             function, | ||||
|             functionBody->statementSequence.sequence[i]); | ||||
|     } | ||||
| 
 | ||||
|     hasReturn = | ||||
|         LLVMGetBasicBlockTerminator(LLVMGetLastBasicBlock(function)) != NULL; | ||||
| 
 | ||||
|     if (LLVMGetTypeKind(returnType) == LLVMVoidTypeKind && !hasReturn) | ||||
|     { | ||||
|         LLVMBuildRetVoid(builder); | ||||
|     } | ||||
|     else if (LLVMGetTypeKind(returnType) != LLVMVoidTypeKind && !hasReturn) | ||||
|     { | ||||
|         fprintf(stderr, "Return statement not provided!"); | ||||
|     } | ||||
| 
 | ||||
|     LLVMDisposeBuilder(builder); | ||||
|     PopScopeFrame(scope); | ||||
|     free(functionName); | ||||
| 
 | ||||
|     StructTypeFunction structTypeFunction; | ||||
|     structTypeFunction.name = strdup( | ||||
|         functionSignature->functionSignature.identifier->identifier.name); | ||||
|     structTypeFunction.function = function; | ||||
|     structTypeFunction.returnType = returnType; | ||||
|     structTypeFunction.isStatic = isStatic; | ||||
| 
 | ||||
|     return structTypeFunction; | ||||
| } | ||||
| 
 | ||||
| static LLVMValueRef LookupGenericFunction( | ||||
|     LLVMModuleRef module, | ||||
|     StructTypeGenericFunction *genericFunction, | ||||
|     TypeTag **genericArgumentTypes, | ||||
|     uint32_t genericArgumentTypeCount, | ||||
|  | @ -484,17 +735,41 @@ static LLVMValueRef LookupGenericFunction( | |||
| 
 | ||||
|     if (hashEntry == NULL) | ||||
|     { | ||||
|         StructTypeFunction function = CompileGenericFunction( | ||||
|             module, | ||||
|             genericFunction->parentStructName, | ||||
|             genericFunction->parentStructPointerType, | ||||
|             genericArgumentTypes, | ||||
|             genericArgumentTypeCount, | ||||
|             genericFunction->functionDeclarationNode); | ||||
| 
 | ||||
|         /* TODO: compile */ | ||||
|         /* TODO: add to hash */ | ||||
|         hashArray->elements = realloc( | ||||
|             hashArray->elements, | ||||
|             sizeof(MonomorphizedGenericFunctionHashEntry) * | ||||
|                 (hashArray->count + 1)); | ||||
|         hashArray->elements[hashArray->count].key = typeHash; | ||||
|         hashArray->elements[hashArray->count].types = | ||||
|             malloc(sizeof(TypeTag *) * genericArgumentTypeCount); | ||||
|         hashArray->elements[hashArray->count].typeCount = | ||||
|             genericArgumentTypeCount; | ||||
|         hashArray->elements[hashArray->count].function = function; | ||||
|         for (i = 0; i < genericArgumentTypeCount; i += 1) | ||||
|         { | ||||
|             hashArray->elements[hashArray->count].types[i] = | ||||
|                 genericArgumentTypes[i]; | ||||
|         } | ||||
|         hashArray->count += 1; | ||||
|     } | ||||
| 
 | ||||
|     *pReturnType = hashEntry->function.returnType; | ||||
|     *pStatic = hashEntry->function.isStatic; | ||||
|     *pStatic = genericFunction->isStatic; | ||||
| 
 | ||||
|     return hashEntry->function.function; | ||||
| } | ||||
| 
 | ||||
| static LLVMValueRef LookupFunctionByType( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMTypeRef structType, | ||||
|     char *name, | ||||
|     TypeTag **genericArgumentTypes, | ||||
|  | @ -528,6 +803,7 @@ static LLVMValueRef LookupFunctionByType( | |||
|                         name) == 0) | ||||
|                 { | ||||
|                     return LookupGenericFunction( | ||||
|                         module, | ||||
|                         &structTypeDeclarations[i].genericFunctions[j], | ||||
|                         genericArgumentTypes, | ||||
|                         genericArgumentTypeCount, | ||||
|  | @ -543,6 +819,7 @@ static LLVMValueRef LookupFunctionByType( | |||
| } | ||||
| 
 | ||||
| static LLVMValueRef LookupFunctionByPointerType( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMTypeRef structPointerType, | ||||
|     char *name, | ||||
|     TypeTag **genericArgumentTypes, | ||||
|  | @ -576,6 +853,7 @@ static LLVMValueRef LookupFunctionByPointerType( | |||
|                         name) == 0) | ||||
|                 { | ||||
|                     return LookupGenericFunction( | ||||
|                         module, | ||||
|                         &structTypeDeclarations[i].genericFunctions[j], | ||||
|                         genericArgumentTypes, | ||||
|                         genericArgumentTypeCount, | ||||
|  | @ -591,6 +869,7 @@ static LLVMValueRef LookupFunctionByPointerType( | |||
| } | ||||
| 
 | ||||
| static LLVMValueRef LookupFunctionByInstance( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMValueRef structPointer, | ||||
|     char *name, | ||||
|     TypeTag **genericArgumentTypes, | ||||
|  | @ -599,6 +878,7 @@ static LLVMValueRef LookupFunctionByInstance( | |||
|     uint8_t *pStatic) | ||||
| { | ||||
|     return LookupFunctionByPointerType( | ||||
|         module, | ||||
|         LLVMTypeOf(structPointer), | ||||
|         name, | ||||
|         genericArgumentTypes, | ||||
|  | @ -607,41 +887,6 @@ static LLVMValueRef LookupFunctionByInstance( | |||
|         pStatic); | ||||
| } | ||||
| 
 | ||||
| static void AddStructVariablesToScope( | ||||
|     LLVMBuilderRef builder, | ||||
|     LLVMValueRef structPointer) | ||||
| { | ||||
|     uint32_t i, j; | ||||
| 
 | ||||
|     for (i = 0; i < structTypeDeclarationCount; i += 1) | ||||
|     { | ||||
|         if (structTypeDeclarations[i].structPointerType == | ||||
|             LLVMTypeOf(structPointer)) | ||||
|         { | ||||
|             for (j = 0; j < structTypeDeclarations[i].fieldCount; j += 1) | ||||
|             { | ||||
|                 char *ptrName = | ||||
|                     strdup(structTypeDeclarations[i].fields[j].name); | ||||
|                 strcat(ptrName, "_ptr"); | ||||
|                 LLVMValueRef elementPointer = LLVMBuildStructGEP( | ||||
|                     builder, | ||||
|                     structPointer, | ||||
|                     structTypeDeclarations[i].fields[j].index, | ||||
|                     ptrName); | ||||
|                 free(ptrName); | ||||
| 
 | ||||
|                 AddLocalVariable( | ||||
|                     scope, | ||||
|                     elementPointer, | ||||
|                     NULL, | ||||
|                     structTypeDeclarations[i].fields[j].name); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static LLVMValueRef CompileExpression(LLVMBuilderRef builder, Node *expression); | ||||
| 
 | ||||
| static LLVMValueRef CompileNumber(Node *numberExpression) | ||||
| { | ||||
|     return LLVMConstInt(LLVMInt64Type(), numberExpression->number.value, 0); | ||||
|  | @ -658,13 +903,19 @@ static LLVMValueRef CompileString( | |||
| } | ||||
| 
 | ||||
| static LLVMValueRef CompileBinaryExpression( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMBuilderRef builder, | ||||
|     Node *binaryExpression) | ||||
| { | ||||
|     LLVMValueRef left = | ||||
|         CompileExpression(builder, binaryExpression->binaryExpression.left); | ||||
|     LLVMValueRef right = | ||||
|         CompileExpression(builder, binaryExpression->binaryExpression.right); | ||||
|     LLVMValueRef left = CompileExpression( | ||||
|         module, | ||||
|         builder, | ||||
|         binaryExpression->binaryExpression.left); | ||||
| 
 | ||||
|     LLVMValueRef right = CompileExpression( | ||||
|         module, | ||||
|         builder, | ||||
|         binaryExpression->binaryExpression.right); | ||||
| 
 | ||||
|     switch (binaryExpression->binaryExpression.operator) | ||||
|     { | ||||
|  | @ -709,6 +960,7 @@ static LLVMValueRef CompileBinaryExpression( | |||
| 
 | ||||
| /* FIXME THIS IS ALL BROKEN */ | ||||
| static LLVMValueRef CompileFunctionCallExpression( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMBuilderRef builder, | ||||
|     Node *functionCallExpression) | ||||
| { | ||||
|  | @ -728,6 +980,7 @@ static LLVMValueRef CompileFunctionCallExpression( | |||
|     LLVMTypeRef functionReturnType; | ||||
|     char *returnName = ""; | ||||
| 
 | ||||
|     /* FIXME: this is completely wrong and not how we get generic args */ | ||||
|     for (i = 0; i < functionCallExpression->functionCallExpression | ||||
|                         .argumentSequence->functionArgumentSequence.count; | ||||
|          i += 1) | ||||
|  | @ -739,7 +992,7 @@ static LLVMValueRef CompileFunctionCallExpression( | |||
|             genericArgumentTypes[genericArgumentCount] = | ||||
|                 functionCallExpression->functionCallExpression.argumentSequence | ||||
|                     ->functionArgumentSequence.sequence[i] | ||||
|                     ->typeTag; | ||||
|                     ->declaration.identifier->typeTag; | ||||
| 
 | ||||
|             genericArgumentCount += 1; | ||||
|         } | ||||
|  | @ -757,6 +1010,7 @@ static LLVMValueRef CompileFunctionCallExpression( | |||
|         if (typeReference != NULL) | ||||
|         { | ||||
|             function = LookupFunctionByType( | ||||
|                 module, | ||||
|                 typeReference, | ||||
|                 functionCallExpression->functionCallExpression.identifier | ||||
|                     ->accessExpression.accessor->identifier.name, | ||||
|  | @ -771,6 +1025,7 @@ static LLVMValueRef CompileFunctionCallExpression( | |||
|                 functionCallExpression->functionCallExpression.identifier | ||||
|                     ->accessExpression.accessee->identifier.name); | ||||
|             function = LookupFunctionByInstance( | ||||
|                 module, | ||||
|                 structInstance, | ||||
|                 functionCallExpression->functionCallExpression.identifier | ||||
|                     ->accessExpression.accessor->identifier.name, | ||||
|  | @ -797,6 +1052,7 @@ static LLVMValueRef CompileFunctionCallExpression( | |||
|          i += 1) | ||||
|     { | ||||
|         args[argumentCount] = CompileExpression( | ||||
|             module, | ||||
|             builder, | ||||
|             functionCallExpression->functionCallExpression.argumentSequence | ||||
|                 ->functionArgumentSequence.sequence[i]); | ||||
|  | @ -843,11 +1099,14 @@ static LLVMValueRef CompileAllocExpression( | |||
|     LLVMBuilderRef builder, | ||||
|     Node *allocExpression) | ||||
| { | ||||
|     LLVMTypeRef type = ResolveType(allocExpression->allocExpression.type); | ||||
|     LLVMTypeRef type = ResolveType(allocExpression->typeTag); | ||||
|     return LLVMBuildMalloc(builder, type, "allocation"); | ||||
| } | ||||
| 
 | ||||
| static LLVMValueRef CompileExpression(LLVMBuilderRef builder, Node *expression) | ||||
| static LLVMValueRef CompileExpression( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMBuilderRef builder, | ||||
|     Node *expression) | ||||
| { | ||||
|     switch (expression->syntaxKind) | ||||
|     { | ||||
|  | @ -858,10 +1117,10 @@ static LLVMValueRef CompileExpression(LLVMBuilderRef builder, Node *expression) | |||
|         return CompileAllocExpression(builder, expression); | ||||
| 
 | ||||
|     case BinaryExpression: | ||||
|         return CompileBinaryExpression(builder, expression); | ||||
|         return CompileBinaryExpression(module, builder, expression); | ||||
| 
 | ||||
|     case FunctionCallExpression: | ||||
|         return CompileFunctionCallExpression(builder, expression); | ||||
|         return CompileFunctionCallExpression(module, builder, expression); | ||||
| 
 | ||||
|     case Identifier: | ||||
|         return FindVariableValue(builder, expression->identifier.name); | ||||
|  | @ -877,17 +1136,14 @@ static LLVMValueRef CompileExpression(LLVMBuilderRef builder, Node *expression) | |||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| static LLVMBasicBlockRef CompileStatement( | ||||
|     LLVMBuilderRef builder, | ||||
|     LLVMValueRef function, | ||||
|     Node *statement); | ||||
| 
 | ||||
| static LLVMBasicBlockRef CompileReturn( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMBuilderRef builder, | ||||
|     LLVMValueRef function, | ||||
|     Node *returnStatemement) | ||||
| { | ||||
|     LLVMValueRef expression = CompileExpression( | ||||
|         module, | ||||
|         builder, | ||||
|         returnStatemement->returnStatement.expression); | ||||
|     LLVMBuildRet(builder, expression); | ||||
|  | @ -916,7 +1172,7 @@ static LLVMValueRef CompileFunctionVariableDeclaration( | |||
| 
 | ||||
|     variable = LLVMBuildAlloca( | ||||
|         builder, | ||||
|         ResolveType(variableDeclaration->declaration.type), | ||||
|         ResolveType(variableDeclaration->declaration.identifier->typeTag), | ||||
|         ptrName); | ||||
| 
 | ||||
|     free(ptrName); | ||||
|  | @ -927,11 +1183,13 @@ static LLVMValueRef CompileFunctionVariableDeclaration( | |||
| } | ||||
| 
 | ||||
| static LLVMBasicBlockRef CompileAssignment( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMBuilderRef builder, | ||||
|     LLVMValueRef function, | ||||
|     Node *assignmentStatement) | ||||
| { | ||||
|     LLVMValueRef result = CompileExpression( | ||||
|         module, | ||||
|         builder, | ||||
|         assignmentStatement->assignmentStatement.right); | ||||
|     LLVMValueRef identifier; | ||||
|  | @ -969,13 +1227,14 @@ static LLVMBasicBlockRef CompileAssignment( | |||
| } | ||||
| 
 | ||||
| static LLVMBasicBlockRef CompileIfStatement( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMBuilderRef builder, | ||||
|     LLVMValueRef function, | ||||
|     Node *ifStatement) | ||||
| { | ||||
|     uint32_t i; | ||||
|     LLVMValueRef conditional = | ||||
|         CompileExpression(builder, ifStatement->ifStatement.expression); | ||||
|         CompileExpression(module, builder, ifStatement->ifStatement.expression); | ||||
| 
 | ||||
|     LLVMBasicBlockRef block = LLVMAppendBasicBlock(function, "ifBlock"); | ||||
|     LLVMBasicBlockRef afterCond = LLVMAppendBasicBlock(function, "afterCond"); | ||||
|  | @ -990,6 +1249,7 @@ static LLVMBasicBlockRef CompileIfStatement( | |||
|          i += 1) | ||||
|     { | ||||
|         CompileStatement( | ||||
|             module, | ||||
|             builder, | ||||
|             function, | ||||
|             ifStatement->ifStatement.statementSequence->statementSequence | ||||
|  | @ -1003,12 +1263,14 @@ static LLVMBasicBlockRef CompileIfStatement( | |||
| } | ||||
| 
 | ||||
| static LLVMBasicBlockRef CompileIfElseStatement( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMBuilderRef builder, | ||||
|     LLVMValueRef function, | ||||
|     Node *ifElseStatement) | ||||
| { | ||||
|     uint32_t i; | ||||
|     LLVMValueRef conditional = CompileExpression( | ||||
|         module, | ||||
|         builder, | ||||
|         ifElseStatement->ifElseStatement.ifStatement->ifStatement.expression); | ||||
| 
 | ||||
|  | @ -1025,6 +1287,7 @@ static LLVMBasicBlockRef CompileIfElseStatement( | |||
|          i += 1) | ||||
|     { | ||||
|         CompileStatement( | ||||
|             module, | ||||
|             builder, | ||||
|             function, | ||||
|             ifElseStatement->ifElseStatement.ifStatement->ifStatement | ||||
|  | @ -1043,6 +1306,7 @@ static LLVMBasicBlockRef CompileIfElseStatement( | |||
|              i += 1) | ||||
|         { | ||||
|             CompileStatement( | ||||
|                 module, | ||||
|                 builder, | ||||
|                 function, | ||||
|                 ifElseStatement->ifElseStatement.elseStatement | ||||
|  | @ -1052,6 +1316,7 @@ static LLVMBasicBlockRef CompileIfElseStatement( | |||
|     else | ||||
|     { | ||||
|         CompileStatement( | ||||
|             module, | ||||
|             builder, | ||||
|             function, | ||||
|             ifElseStatement->ifElseStatement.elseStatement); | ||||
|  | @ -1064,6 +1329,7 @@ static LLVMBasicBlockRef CompileIfElseStatement( | |||
| } | ||||
| 
 | ||||
| static LLVMBasicBlockRef CompileForLoopStatement( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMBuilderRef builder, | ||||
|     LLVMValueRef function, | ||||
|     Node *forLoopStatement) | ||||
|  | @ -1076,8 +1342,8 @@ static LLVMBasicBlockRef CompileForLoopStatement( | |||
|         LLVMAppendBasicBlock(function, "afterLoop"); | ||||
|     char *iteratorVariableName = forLoopStatement->forLoop.declaration | ||||
|                                      ->declaration.identifier->identifier.name; | ||||
|     LLVMTypeRef iteratorVariableType = | ||||
|         ResolveType(forLoopStatement->forLoop.declaration->declaration.type); | ||||
|     LLVMTypeRef iteratorVariableType = ResolveType( | ||||
|         forLoopStatement->forLoop.declaration->declaration.identifier->typeTag); | ||||
| 
 | ||||
|     PushScopeFrame(scope); | ||||
| 
 | ||||
|  | @ -1123,6 +1389,7 @@ static LLVMBasicBlockRef CompileForLoopStatement( | |||
|          i += 1) | ||||
|     { | ||||
|         lastBlock = CompileStatement( | ||||
|             module, | ||||
|             builder, | ||||
|             function, | ||||
|             forLoopStatement->forLoop.statementSequence->statementSequence | ||||
|  | @ -1151,6 +1418,7 @@ static LLVMBasicBlockRef CompileForLoopStatement( | |||
| } | ||||
| 
 | ||||
| static LLVMBasicBlockRef CompileStatement( | ||||
|     LLVMModuleRef module, | ||||
|     LLVMBuilderRef builder, | ||||
|     LLVMValueRef function, | ||||
|     Node *statement) | ||||
|  | @ -1158,27 +1426,27 @@ static LLVMBasicBlockRef CompileStatement( | |||
|     switch (statement->syntaxKind) | ||||
|     { | ||||
|     case Assignment: | ||||
|         return CompileAssignment(builder, function, statement); | ||||
|         return CompileAssignment(module, builder, function, statement); | ||||
| 
 | ||||
|     case Declaration: | ||||
|         CompileFunctionVariableDeclaration(builder, function, statement); | ||||
|         return LLVMGetLastBasicBlock(function); | ||||
| 
 | ||||
|     case ForLoop: | ||||
|         return CompileForLoopStatement(builder, function, statement); | ||||
|         return CompileForLoopStatement(module, builder, function, statement); | ||||
| 
 | ||||
|     case FunctionCallExpression: | ||||
|         CompileFunctionCallExpression(builder, statement); | ||||
|         CompileFunctionCallExpression(module, builder, statement); | ||||
|         return LLVMGetLastBasicBlock(function); | ||||
| 
 | ||||
|     case IfStatement: | ||||
|         return CompileIfStatement(builder, function, statement); | ||||
|         return CompileIfStatement(module, builder, function, statement); | ||||
| 
 | ||||
|     case IfElseStatement: | ||||
|         return CompileIfElseStatement(builder, function, statement); | ||||
|         return CompileIfElseStatement(module, builder, function, statement); | ||||
| 
 | ||||
|     case Return: | ||||
|         return CompileReturn(builder, function, statement); | ||||
|         return CompileReturn(module, builder, function, statement); | ||||
| 
 | ||||
|     case ReturnVoid: | ||||
|         return CompileReturnVoid(builder, function); | ||||
|  | @ -1192,8 +1460,6 @@ static void CompileFunction( | |||
|     LLVMModuleRef module, | ||||
|     char *parentStructName, | ||||
|     LLVMTypeRef wStructPointerType, | ||||
|     Node **fieldDeclarations, | ||||
|     uint32_t fieldDeclarationCount, | ||||
|     Node *functionDeclaration) | ||||
| { | ||||
|     uint32_t i; | ||||
|  | @ -1248,12 +1514,12 @@ static void CompileFunction( | |||
|             paramTypes[paramIndex] = | ||||
|                 ResolveType(functionSignature->functionSignature.arguments | ||||
|                                 ->functionSignatureArguments.sequence[i] | ||||
|                                 ->declaration.type); | ||||
|                                 ->declaration.identifier->typeTag); | ||||
|             paramIndex += 1; | ||||
|         } | ||||
| 
 | ||||
|         LLVMTypeRef returnType = | ||||
|             ResolveType(functionSignature->functionSignature.type); | ||||
|         LLVMTypeRef returnType = ResolveType( | ||||
|             functionSignature->functionSignature.identifier->typeTag); | ||||
|         LLVMTypeRef functionType = | ||||
|             LLVMFunctionType(returnType, paramTypes, paramIndex, 0); | ||||
| 
 | ||||
|  | @ -1303,6 +1569,7 @@ static void CompileFunction( | |||
|         for (i = 0; i < functionBody->statementSequence.count; i += 1) | ||||
|         { | ||||
|             CompileStatement( | ||||
|                 module, | ||||
|                 builder, | ||||
|                 function, | ||||
|                 functionBody->statementSequence.sequence[i]); | ||||
|  | @ -1330,7 +1597,8 @@ static void CompileFunction( | |||
|             wStructPointerType, | ||||
|             functionDeclaration, | ||||
|             isStatic, | ||||
|             functionName); | ||||
|             parentStructName, | ||||
|             functionSignature->functionSignature.identifier->identifier.name); | ||||
|     } | ||||
| 
 | ||||
|     free(functionName); | ||||
|  | @ -1367,8 +1635,8 @@ static void CompileStruct( | |||
|         switch (currentDeclarationNode->syntaxKind) | ||||
|         { | ||||
|         case Declaration: /* this is badly named */ | ||||
|             types[fieldCount] = | ||||
|                 ResolveType(currentDeclarationNode->declaration.type); | ||||
|             types[fieldCount] = ResolveType( | ||||
|                 currentDeclarationNode->declaration.identifier->typeTag); | ||||
|             fieldDeclarations[fieldCount] = currentDeclarationNode; | ||||
|             fieldCount += 1; | ||||
|             break; | ||||
|  | @ -1396,8 +1664,6 @@ static void CompileStruct( | |||
|                 module, | ||||
|                 structName, | ||||
|                 wStructPointerType, | ||||
|                 fieldDeclarations, | ||||
|                 fieldCount, | ||||
|                 currentDeclarationNode); | ||||
|             break; | ||||
|         } | ||||
|  |  | |||
|  | @ -59,9 +59,7 @@ IdNode *MakeIdTree(Node *astNode, IdNode *parent) | |||
|         return NULL; | ||||
| 
 | ||||
|     case AllocExpression: | ||||
|         AddChildToNode( | ||||
|             parent, | ||||
|             MakeIdTree(astNode->allocExpression.type, parent)); | ||||
|         astNode->typeTag = MakeTypeTag(astNode); | ||||
|         return NULL; | ||||
| 
 | ||||
|     case Assignment: | ||||
|  | @ -154,6 +152,7 @@ IdNode *MakeIdTree(Node *astNode, IdNode *parent) | |||
|         idNode->typeTag = mainNode->typeTag; | ||||
|         MakeIdTree(sigNode->functionSignature.arguments, mainNode); | ||||
|         MakeIdTree(astNode->functionDeclaration.functionBody, mainNode); | ||||
|         MakeIdTree(sigNode->functionSignature.genericArguments, mainNode); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|  | @ -167,6 +166,23 @@ IdNode *MakeIdTree(Node *astNode, IdNode *parent) | |||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     case GenericArgument: | ||||
|     { | ||||
|         char *name = astNode->genericArgument.identifier->identifier.name; | ||||
|         mainNode = MakeIdNode(GenericType, name, parent); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case GenericArguments: | ||||
|     { | ||||
|         for (i = 0; i < astNode->genericArguments.count; i += 1) | ||||
|         { | ||||
|             Node *argNode = astNode->genericArguments.arguments[i]; | ||||
|             AddChildToNode(parent, MakeIdTree(argNode, parent)); | ||||
|         } | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     case Identifier: | ||||
|     { | ||||
|         char *name = astNode->identifier.name; | ||||
|  | @ -302,6 +318,12 @@ void PrintIdNode(IdNode *node) | |||
|     case Variable: | ||||
|         printf("%s : %s\n", node->name, TypeTagToString(node->typeTag)); | ||||
|         break; | ||||
|     case GenericType: | ||||
|         printf("Generic type: %s\n", node->name); | ||||
|         break; | ||||
|     case Alloc: | ||||
|         printf("Alloc: %s\n", TypeTagToString(node->typeTag)); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,7 +17,9 @@ typedef enum NodeType | |||
|     OrderedScope, | ||||
|     Struct, | ||||
|     Function, | ||||
|     Variable | ||||
|     Variable, | ||||
|     GenericType, | ||||
|     Alloc | ||||
| } NodeType; | ||||
| 
 | ||||
| typedef struct IdNode | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ uint64_t str_hash(char *str) | |||
|     uint64_t hash = 5381; | ||||
|     size_t c; | ||||
| 
 | ||||
|     while (c = *str++) | ||||
|     while ((c = *str++)) | ||||
|     { | ||||
|         hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ | ||||
|     } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue