#include #include #include #include #include #include #include #include #include #include #include #include #include #include "ast.h" #include "util.h" typedef struct LocalVariable { char *name; LLVMValueRef pointer; LLVMValueRef value; } LocalVariable; typedef struct LocalGenericType { char *name; TypeTag *concreteTypeTag; LLVMTypeRef type; } LocalGenericType; typedef struct FunctionArgument { char *name; LLVMValueRef value; } FunctionArgument; typedef struct ScopeFrame { LocalVariable *localVariables; uint32_t localVariableCount; LocalGenericType *genericTypes; uint32_t genericTypeCount; } ScopeFrame; typedef struct Scope { ScopeFrame *scopeStack; uint32_t scopeStackCount; } Scope; Scope *scope; typedef struct StructTypeField { char *name; uint32_t index; } StructTypeField; typedef struct StructTypeFunction { char *name; LLVMValueRef function; LLVMTypeRef returnType; uint8_t isStatic; } StructTypeFunction; typedef struct MonomorphizedGenericFunctionHashEntry { uint64_t key; TypeTag **types; uint32_t typeCount; StructTypeFunction function; } MonomorphizedGenericFunctionHashEntry; typedef struct MonomorphizedGenericFunctionHashArray { MonomorphizedGenericFunctionHashEntry *elements; uint32_t count; } MonomorphizedGenericFunctionHashArray; #define NUM_MONOMORPHIZED_HASH_BUCKETS 1031 typedef struct StructTypeDeclaration StructTypeDeclaration; typedef struct StructTypeGenericFunction { StructTypeDeclaration *parentStruct; char *name; Node *functionDeclarationNode; uint8_t isStatic; MonomorphizedGenericFunctionHashArray monomorphizedFunctions[NUM_MONOMORPHIZED_HASH_BUCKETS]; } StructTypeGenericFunction; struct StructTypeDeclaration { LLVMModuleRef module; char *name; LLVMTypeRef structType; LLVMTypeRef structPointerType; StructTypeField *fields; uint32_t fieldCount; StructTypeFunction *functions; uint32_t functionCount; StructTypeGenericFunction *genericFunctions; uint32_t genericFunctionCount; }; StructTypeDeclaration *structTypeDeclarations; uint32_t structTypeDeclarationCount; typedef struct MonomorphizedGenericStructHashEntry { uint64_t key; TypeTag **types; uint32_t typeCount; StructTypeDeclaration *structDeclaration; } MonomorphizedGenericStructHashEntry; typedef struct MonomorphizedGenericStructHashArray { MonomorphizedGenericStructHashEntry *elements; uint32_t count; } MonomorphizedGenericStructHashArray; typedef struct GenericStructTypeDeclaration { LLVMModuleRef module; Node *structDeclarationNode; MonomorphizedGenericStructHashArray monomorphizedStructs[NUM_MONOMORPHIZED_HASH_BUCKETS]; } GenericStructTypeDeclaration; GenericStructTypeDeclaration *genericStructTypeDeclarations; uint32_t genericStructTypeDeclarationCount; typedef struct SystemFunction { char *name; LLVMTypeRef functionType; LLVMValueRef function; } SystemFunction; SystemFunction *systemFunctions; uint32_t systemFunctionCount; /* FUNCTION FORWARD DECLARATIONS */ static LLVMBasicBlockRef CompileStatement( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, LLVMValueRef function, Node *statement); static LLVMValueRef CompileExpression( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, Node *expression); static void CompileFunction( StructTypeDeclaration *structTypeDeclaration, Node *functionDeclaration); static LLVMTypeRef ResolveType(TypeTag *typeTag); static Scope *CreateScope() { Scope *scope = malloc(sizeof(Scope)); 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; } static void PushScopeFrame(Scope *scope) { uint32_t index = scope->scopeStackCount; scope->scopeStack = realloc( scope->scopeStack, 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; } static void PopScopeFrame(Scope *scope) { uint32_t i; uint32_t index = scope->scopeStackCount - 1; if (scope->scopeStack[index].localVariables != NULL) { for (i = 0; i < scope->scopeStack[index].localVariableCount; i += 1) { free(scope->scopeStack[index].localVariables[i].name); } 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].genericTypes); } scope->scopeStackCount -= 1; scope->scopeStack = realloc(scope->scopeStack, sizeof(ScopeFrame) * scope->scopeStackCount); } 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 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].concreteTypeTag = typeTag; scopeFrame->genericTypes[index].type = ResolveType(typeTag); scopeFrame->genericTypeCount += 1; } static void AddStructVariablesToScope( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, LLVMValueRef structPointer) { uint32_t i; for (i = 0; i < structTypeDeclaration->fieldCount; i += 1) { char *ptrName = strdup(structTypeDeclaration->fields[i].name); strcat(ptrName, "_ptr"); /* FIXME: needs to be realloc'd */ LLVMValueRef elementPointer = LLVMBuildStructGEP( builder, structPointer, structTypeDeclaration->fields[i].index, ptrName); free(ptrName); AddLocalVariable( scope, elementPointer, NULL, structTypeDeclaration->fields[i].name); } } static void AddFieldToStructDeclaration( StructTypeDeclaration *structTypeDeclaration, char *name) { structTypeDeclaration->fields = realloc( structTypeDeclaration->fields, sizeof(StructTypeField) * (structTypeDeclaration->fieldCount + 1)); structTypeDeclaration->fields[structTypeDeclaration->fieldCount].name = strdup(name); structTypeDeclaration->fields[structTypeDeclaration->fieldCount].index = structTypeDeclaration->fieldCount; structTypeDeclaration->fieldCount += 1; } static void AddGenericStructDeclaration( LLVMModuleRef module, Node *structDeclarationNode) { uint32_t i; genericStructTypeDeclarations = realloc( genericStructTypeDeclarations, sizeof(GenericStructTypeDeclaration) * (genericStructTypeDeclarationCount + 1)); genericStructTypeDeclarations[genericStructTypeDeclarationCount] .structDeclarationNode = structDeclarationNode; genericStructTypeDeclarations[genericStructTypeDeclarationCount].module = module; for (i = 0; i < NUM_MONOMORPHIZED_HASH_BUCKETS; i += 1) { genericStructTypeDeclarations[genericStructTypeDeclarationCount] .monomorphizedStructs[i] .elements = NULL; genericStructTypeDeclarations[genericStructTypeDeclarationCount] .monomorphizedStructs[i] .count = 0; } genericStructTypeDeclarationCount += 1; } static LLVMTypeRef WraithTypeToLLVMType(PrimitiveType type) { switch (type) { case Int: return LLVMInt64Type(); case UInt: return LLVMInt64Type(); case Bool: return LLVMInt1Type(); case MemoryAddress: return LLVMInt64Type(); case Void: return LLVMVoidType(); } fprintf(stderr, "Unrecognized type!"); return NULL; } static LocalGenericType *LookupGenericType(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]; } } } fprintf(stderr, "Could not find resolved generic type!\n"); return NULL; } static TypeTag *ConcretizeType(TypeTag *type) { if (type->type == Generic) { return LookupGenericType(type->value.genericType)->concreteTypeTag; } return type; } static LLVMTypeRef LookupCustomType(char *name) { int32_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 custom type!\n"); return NULL; } static StructTypeDeclaration *AddStructDeclaration( LLVMModuleRef module, LLVMTypeRef wStructType, LLVMTypeRef wStructPointerType, char *name) { uint32_t index = structTypeDeclarationCount; structTypeDeclarations = realloc( structTypeDeclarations, sizeof(StructTypeDeclaration) * (structTypeDeclarationCount + 1)); structTypeDeclarations[index].module = module; structTypeDeclarations[index].structType = wStructType; structTypeDeclarations[index].structPointerType = wStructPointerType; structTypeDeclarations[index].name = strdup(name); structTypeDeclarations[index].fields = NULL; structTypeDeclarations[index].fieldCount = 0; structTypeDeclarations[index].functions = NULL; structTypeDeclarations[index].functionCount = 0; structTypeDeclarations[index].genericFunctions = NULL; structTypeDeclarations[index].genericFunctionCount = 0; structTypeDeclarationCount += 1; return &structTypeDeclarations[index]; } static StructTypeDeclaration *CompileMonomorphizedGenericStruct( GenericStructTypeDeclaration *genericStructTypeDeclaration, TypeTag **genericArgumentTypes, uint32_t genericArgumentTypeCount) { uint32_t i = 0; uint32_t nameLen; uint32_t fieldCount = 0; Node *structDeclarationNode = genericStructTypeDeclaration->structDeclarationNode; uint32_t declarationCount = structDeclarationNode->structDeclaration.declarationSequence ->declarationSequence.count; LLVMTypeRef types[declarationCount]; PushScopeFrame(scope); for (i = 0; i < genericArgumentTypeCount; i += 1) { AddGenericVariable( scope, genericArgumentTypes[i], structDeclarationNode->structDeclaration.genericDeclarations ->genericDeclarations.declarations[i] ->genericDeclaration.identifier->identifier.name); } char *structName = strdup( structDeclarationNode->structDeclaration.identifier->identifier.name); nameLen = strlen(structName); for (i = 0; i < genericArgumentTypeCount; i += 1) { char *inner = TypeTagToString(genericArgumentTypes[i]); nameLen += 2 + strlen(inner); structName = realloc(structName, sizeof(char) * nameLen); strcat(structName, "_"); strcat(structName, inner); } LLVMContextRef context = LLVMGetGlobalContext(); /* FIXME: should we pass a context? */ LLVMTypeRef wStructType = LLVMStructCreateNamed(context, structName); LLVMTypeRef wStructPointerType = LLVMPointerType(wStructType, 0); StructTypeDeclaration *declaration = AddStructDeclaration( genericStructTypeDeclaration->module, wStructType, wStructPointerType, structName); /* first build the structure def */ for (i = 0; i < declarationCount; i += 1) { switch (structDeclarationNode->structDeclaration.declarationSequence ->declarationSequence.sequence[i] ->syntaxKind) { case Declaration: types[fieldCount] = ResolveType( structDeclarationNode->structDeclaration.declarationSequence ->declarationSequence.sequence[i] ->declaration.identifier->typeTag); AddFieldToStructDeclaration( declaration, structDeclarationNode->structDeclaration.declarationSequence ->declarationSequence.sequence[i] ->declaration.identifier->identifier.name); fieldCount += 1; break; } } LLVMStructSetBody(wStructType, types, fieldCount, 1); /* now we wire up the functions */ for (i = 0; i < declarationCount; i += 1) { switch (structDeclarationNode->structDeclaration.declarationSequence ->declarationSequence.sequence[i] ->syntaxKind) { case FunctionDeclaration: CompileFunction( declaration, structDeclarationNode->structDeclaration.declarationSequence ->declarationSequence.sequence[i]); break; } } PopScopeFrame(scope); return declaration; } static StructTypeDeclaration *LookupGenericStructType( ConcreteGenericTypeTag *typeTag) { uint32_t i, j, k; uint64_t typeHash; uint8_t match; TypeTag *genericTypeTags[typeTag->genericArgumentCount]; for (i = 0; i < typeTag->genericArgumentCount; i += 1) { genericTypeTags[i] = ConcretizeType(typeTag->genericArguments[i]); } for (i = 0; i < genericStructTypeDeclarationCount; i += 1) { if (strcmp( genericStructTypeDeclarations[i] .structDeclarationNode->structDeclaration.identifier ->identifier.name, typeTag->name) == 0) { typeHash = HashTypeTags(genericTypeTags, typeTag->genericArgumentCount); MonomorphizedGenericStructHashArray *hashArray = &genericStructTypeDeclarations[i].monomorphizedStructs [typeHash % NUM_MONOMORPHIZED_HASH_BUCKETS]; MonomorphizedGenericStructHashEntry *hashEntry = NULL; for (j = 0; j < hashArray->count; j += 1) { match = 1; for (k = 0; k < hashArray->elements[j].typeCount; k += 1) { if (hashArray->elements[j].types[k] != genericTypeTags[k]) { match = 0; break; } } if (match) { hashEntry = &hashArray->elements[i]; break; } } if (hashEntry == NULL) { StructTypeDeclaration *structTypeDeclaration = CompileMonomorphizedGenericStruct( &genericStructTypeDeclarations[i], genericTypeTags, typeTag->genericArgumentCount); hashArray->elements = realloc( hashArray->elements, sizeof(MonomorphizedGenericStructHashEntry) * (hashArray->count + 1)); hashArray->elements[hashArray->count].key = typeHash; hashArray->elements[hashArray->count].types = malloc(sizeof(TypeTag *) * typeTag->genericArgumentCount); hashArray->elements[hashArray->count].typeCount = typeTag->genericArgumentCount; hashArray->elements[hashArray->count].structDeclaration = structTypeDeclaration; for (j = 0; j < typeTag->genericArgumentCount; j += 1) { hashArray->elements[hashArray->count].types[j] = genericTypeTags[j]; } hashArray->count += 1; hashEntry = &hashArray->elements[hashArray->count - 1]; } return hashEntry->structDeclaration; } } fprintf(stderr, "Could not find generic struct declaration!"); 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 if (typeTag->type == Generic) { return LookupGenericType(typeTag->value.genericType)->type; } else if (typeTag->type == ConcreteGeneric) { return LookupGenericStructType(&typeTag->value.concreteGenericType) ->structType; } else { fprintf(stderr, "Unknown type node!\n"); return NULL; } } static void AddSystemFunction( char *name, LLVMTypeRef functionType, LLVMValueRef function) { systemFunctions = realloc( systemFunctions, sizeof(SystemFunction) * (systemFunctionCount + 1)); systemFunctions[systemFunctionCount].name = strdup(name); systemFunctions[systemFunctionCount].functionType = functionType; systemFunctions[systemFunctionCount].function = function; systemFunctionCount += 1; } static SystemFunction *LookupSystemFunction(Node *systemCallExpression) { uint32_t i; char *name = systemCallExpression->systemCall.identifier->identifier.name; for (i = 0; i < systemFunctionCount; i += 1) { if (strcmp(name, systemFunctions[i].name) == 0) { return &systemFunctions[i]; } } fprintf(stderr, "%s %s %s", "System function", name, "not found!"); return NULL; } static LLVMTypeRef FindStructType(char *name) { uint32_t i; for (i = 0; i < structTypeDeclarationCount; i += 1) { if (strcmp(structTypeDeclarations[i].name, name) == 0) { return structTypeDeclarations[i].structType; } } return NULL; } static LLVMValueRef FindStructFieldPointer( LLVMBuilderRef builder, LLVMValueRef structPointer, char *name) { int32_t i, j; LLVMTypeRef structPointerType = LLVMTypeOf(structPointer); for (i = 0; i < structTypeDeclarationCount; i += 1) { if (structTypeDeclarations[i].structPointerType == structPointerType) { for (j = 0; j < structTypeDeclarations[i].fieldCount; j += 1) { if (strcmp(structTypeDeclarations[i].fields[j].name, name) == 0) { char *ptrName = strdup(name); strcat(ptrName, "_ptr"); return LLVMBuildStructGEP( builder, structPointer, structTypeDeclarations[i].fields[j].index, ptrName); free(ptrName); } } } } printf("Failed to find struct field pointer!"); return NULL; } static LLVMValueRef FindVariablePointer(char *name) { int32_t i, j; for (i = scope->scopeStackCount - 1; i >= 0; i -= 1) { for (j = 0; j < scope->scopeStack[i].localVariableCount; j += 1) { if (strcmp(scope->scopeStack[i].localVariables[j].name, name) == 0) { return scope->scopeStack[i].localVariables[j].pointer; } } } printf("Failed to find variable pointer!"); return NULL; } static LLVMValueRef FindVariableValue(LLVMBuilderRef builder, char *name) { int32_t i, j; for (i = scope->scopeStackCount - 1; i >= 0; i -= 1) { for (j = 0; j < scope->scopeStack[i].localVariableCount; j += 1) { if (strcmp(scope->scopeStack[i].localVariables[j].name, name) == 0) { if (scope->scopeStack[i].localVariables[j].value != NULL) { return scope->scopeStack[i].localVariables[j].value; } else { return LLVMBuildLoad( builder, scope->scopeStack[i].localVariables[j].pointer, name); } } } } printf("Failed to find variable value!"); return NULL; } static void DeclareStructFunction( StructTypeDeclaration *structTypeDeclaration, LLVMValueRef function, LLVMTypeRef returnType, uint8_t isStatic, char *name) { uint32_t index = structTypeDeclaration->functionCount; structTypeDeclaration->functions = realloc( structTypeDeclaration->functions, sizeof(StructTypeFunction) * (structTypeDeclaration->functionCount + 1)); structTypeDeclaration->functions[index].name = strdup(name); structTypeDeclaration->functions[index].function = function; structTypeDeclaration->functions[index].returnType = returnType; structTypeDeclaration->functions[index].isStatic = isStatic; structTypeDeclaration->functionCount += 1; } static void DeclareGenericStructFunction( StructTypeDeclaration *structTypeDeclaration, Node *functionDeclarationNode, uint8_t isStatic, char *name) { uint32_t i, index; index = structTypeDeclaration->genericFunctionCount; structTypeDeclaration->genericFunctions = realloc( structTypeDeclaration->genericFunctions, sizeof(StructTypeGenericFunction) * (structTypeDeclaration->genericFunctionCount + 1)); structTypeDeclaration->genericFunctions[index].name = strdup(name); structTypeDeclaration->genericFunctions[index].parentStruct = structTypeDeclaration; structTypeDeclaration->genericFunctions[index].functionDeclarationNode = functionDeclarationNode; structTypeDeclaration->genericFunctions[index].isStatic = isStatic; for (i = 0; i < NUM_MONOMORPHIZED_HASH_BUCKETS; i += 1) { structTypeDeclaration->genericFunctions[index] .monomorphizedFunctions[i] .elements = NULL; structTypeDeclaration->genericFunctions[index] .monomorphizedFunctions[i] .count = 0; } structTypeDeclaration->genericFunctionCount += 1; } /* FIXME: lots of duplication with non-generic function compile */ static StructTypeFunction CompileGenericFunction( StructTypeDeclaration *structTypeDeclaration, TypeTag **resolvedGenericArgumentTypes, 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; LLVMTypeRef returnType; PushScopeFrame(scope); for (i = 0; i < genericArgumentTypeCount; i += 1) { AddGenericVariable( scope, resolvedGenericArgumentTypes[i], functionDeclaration->functionDeclaration.functionSignature ->functionSignature.genericDeclarations->genericDeclarations .declarations[i] ->genericDeclaration.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; } } } /* FIXME: these cats need to be realloc'd */ char *functionName = strdup(structTypeDeclaration->name); strcat(functionName, "_"); strcat( functionName, functionSignature->functionSignature.identifier->identifier.name); for (i = 0; i < genericArgumentTypeCount; i += 1) { strcat(functionName, TypeTagToString(resolvedGenericArgumentTypes[i])); } if (!isStatic) { paramTypes[paramIndex] = structTypeDeclaration->structPointerType; 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; } returnType = ResolveType(functionSignature->functionSignature.identifier->typeTag); LLVMTypeRef functionType = LLVMFunctionType(returnType, paramTypes, paramIndex, 0); LLVMValueRef function = LLVMAddFunction( structTypeDeclaration->module, functionName, functionType); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry"); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, entry); if (!isStatic) { LLVMValueRef wStructPointer = LLVMGetParam(function, 0); AddStructVariablesToScope( structTypeDeclaration, 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( structTypeDeclaration, 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( StructTypeGenericFunction *genericFunction, Node *functionCallExpression, LLVMTypeRef *pReturnType, uint8_t *pStatic) { uint32_t i, j; uint64_t typeHash; uint8_t match = 0; uint32_t genericArgumentTypeCount = genericFunction->functionDeclarationNode->functionDeclaration .functionSignature->functionSignature.genericDeclarations ->genericDeclarations.count; TypeTag *resolvedGenericArgumentTypes[genericArgumentTypeCount]; uint32_t argumentCount = 0; TypeTag *argumentTypes[functionCallExpression->functionCallExpression .argumentSequence->functionArgumentSequence.count]; for (i = 0; i < functionCallExpression->functionCallExpression .argumentSequence->functionArgumentSequence.count; i += 1) { argumentTypes[i] = functionCallExpression->functionCallExpression.argumentSequence ->functionArgumentSequence.sequence[i] ->typeTag; argumentCount += 1; } if (functionCallExpression->functionCallExpression.genericArguments ->genericArguments.count > 0) { for (i = 0; i < functionCallExpression->functionCallExpression .genericArguments->genericArguments.count; i += 1) { resolvedGenericArgumentTypes[i] = functionCallExpression->functionCallExpression.genericArguments ->genericArguments.arguments[i] ->genericArgument.type->typeTag; } } else /* we have to infer the generics */ { for (i = 0; i < genericArgumentTypeCount; i += 1) { for (j = 0; j < genericFunction->functionDeclarationNode->functionDeclaration .functionSignature->functionSignature.arguments ->functionSignatureArguments.count; j += 1) { if (genericFunction->functionDeclarationNode ->functionDeclaration.functionSignature ->functionSignature.arguments ->functionSignatureArguments.sequence[j] ->declaration.identifier->typeTag->type == Generic && strcmp( genericFunction->functionDeclarationNode ->functionDeclaration.functionSignature ->functionSignature.arguments ->functionSignatureArguments.sequence[j] ->declaration.identifier->typeTag->value .genericType, genericFunction->functionDeclarationNode ->functionDeclaration.functionSignature ->functionSignature.genericDeclarations ->genericDeclarations.declarations[i] ->genericDeclaration.identifier->identifier.name) == 0) { resolvedGenericArgumentTypes[i] = argumentTypes[j]; break; } } } } /* Concretize generics if we are compiling nested generic functions */ for (i = 0; i < genericArgumentTypeCount; i += 1) { resolvedGenericArgumentTypes[i] = ConcretizeType(resolvedGenericArgumentTypes[i]); } typeHash = HashTypeTags(resolvedGenericArgumentTypes, genericArgumentTypeCount); 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] != resolvedGenericArgumentTypes[j]) { match = 0; break; } } if (match) { hashEntry = &hashArray->elements[i]; break; } } if (hashEntry == NULL) { StructTypeFunction function = CompileGenericFunction( genericFunction->parentStruct, resolvedGenericArgumentTypes, genericArgumentTypeCount, genericFunction->functionDeclarationNode); 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] = resolvedGenericArgumentTypes[i]; } hashArray->count += 1; hashEntry = &hashArray->elements[hashArray->count - 1]; } *pReturnType = hashEntry->function.returnType; *pStatic = genericFunction->isStatic; return hashEntry->function.function; } static LLVMValueRef LookupFunctionByType( LLVMTypeRef structType, Node *functionCallExpression, LLVMTypeRef *pReturnType, uint8_t *pStatic) { uint32_t i, j; /* FIXME: hot garbage */ char *name = functionCallExpression->functionCallExpression.identifier ->accessExpression.accessor->identifier.name; for (i = 0; i < structTypeDeclarationCount; i += 1) { if (structTypeDeclarations[i].structType == structType) { for (j = 0; j < structTypeDeclarations[i].functionCount; j += 1) { if (strcmp(structTypeDeclarations[i].functions[j].name, name) == 0) { *pReturnType = structTypeDeclarations[i].functions[j].returnType; *pStatic = structTypeDeclarations[i].functions[j].isStatic; return structTypeDeclarations[i].functions[j].function; } } for (j = 0; j < structTypeDeclarations[i].genericFunctionCount; j += 1) { if (strcmp( structTypeDeclarations[i].genericFunctions[j].name, name) == 0) { return LookupGenericFunction( &structTypeDeclarations[i].genericFunctions[j], functionCallExpression, pReturnType, pStatic); } } } } fprintf(stderr, "Could not find struct function!\n"); return NULL; } static LLVMValueRef LookupFunctionByPointerType( LLVMTypeRef structPointerType, Node *functionCallExpression, LLVMTypeRef *pReturnType, uint8_t *pStatic) { uint32_t i, j; /* FIXME: hot garbage */ char *name = functionCallExpression->functionCallExpression.identifier ->accessExpression.accessor->identifier.name; for (i = 0; i < structTypeDeclarationCount; i += 1) { if (structTypeDeclarations[i].structPointerType == structPointerType) { for (j = 0; j < structTypeDeclarations[i].functionCount; j += 1) { if (strcmp(structTypeDeclarations[i].functions[j].name, name) == 0) { *pReturnType = structTypeDeclarations[i].functions[j].returnType; *pStatic = structTypeDeclarations[i].functions[j].isStatic; return structTypeDeclarations[i].functions[j].function; } } for (j = 0; j < structTypeDeclarations[i].genericFunctionCount; j += 1) { if (strcmp( structTypeDeclarations[i].genericFunctions[j].name, name) == 0) { return LookupGenericFunction( &structTypeDeclarations[i].genericFunctions[j], functionCallExpression, pReturnType, pStatic); } } } } fprintf(stderr, "Could not find struct function!\n"); return NULL; } static LLVMValueRef LookupFunctionByInstance( LLVMValueRef structPointer, Node *functionCallExpression, LLVMTypeRef *pReturnType, uint8_t *pStatic) { return LookupFunctionByPointerType( LLVMTypeOf(structPointer), functionCallExpression, pReturnType, pStatic); } static LLVMValueRef CompileNumber(Node *numberExpression) { return LLVMConstInt(LLVMInt64Type(), numberExpression->number.value, 0); } static LLVMValueRef CompileString( LLVMBuilderRef builder, Node *stringExpression) { return LLVMBuildGlobalStringPtr( builder, stringExpression->stringLiteral.string, "stringConstant"); } static LLVMValueRef CompileBinaryExpression( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, Node *binaryExpression) { LLVMValueRef left = CompileExpression( structTypeDeclaration, builder, binaryExpression->binaryExpression.left); LLVMValueRef right = CompileExpression( structTypeDeclaration, builder, binaryExpression->binaryExpression.right); switch (binaryExpression->binaryExpression.operator) { case Add: return LLVMBuildAdd(builder, left, right, "addResult"); case Subtract: return LLVMBuildSub(builder, left, right, "subtractResult"); case Multiply: return LLVMBuildMul(builder, left, right, "multiplyResult"); /* FIXME: need type information for comparison */ case LessThan: return LLVMBuildICmp( builder, LLVMIntSLT, left, right, "lessThanResult"); case GreaterThan: return LLVMBuildICmp( builder, LLVMIntSGT, left, right, "greaterThanResult"); case Mod: return LLVMBuildSRem(builder, left, right, "modResult"); case Equal: return LLVMBuildICmp(builder, LLVMIntEQ, left, right, "equalResult"); case LogicalOr: return LLVMBuildOr(builder, left, right, "orResult"); } return NULL; } /* FIXME THIS IS ALL BROKEN */ static LLVMValueRef CompileFunctionCallExpression( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, Node *functionCallExpression) { uint32_t i; uint32_t argumentCount = 0; LLVMValueRef args [functionCallExpression->functionCallExpression.argumentSequence ->functionArgumentSequence.count + 1]; LLVMValueRef function; uint8_t isStatic; LLVMValueRef structInstance; LLVMTypeRef functionReturnType; char *returnName = ""; /* FIXME: this needs to be recursive on access chains */ /* FIXME: this needs to be able to call same-struct functions implicitly */ if (functionCallExpression->functionCallExpression.identifier->syntaxKind == AccessExpression) { LLVMTypeRef typeReference = FindStructType( functionCallExpression->functionCallExpression.identifier ->accessExpression.accessee->identifier.name); if (typeReference != NULL) { function = LookupFunctionByType( typeReference, functionCallExpression, &functionReturnType, &isStatic); } else { structInstance = FindVariablePointer( functionCallExpression->functionCallExpression.identifier ->accessExpression.accessee->identifier.name); function = LookupFunctionByInstance( structInstance, functionCallExpression, &functionReturnType, &isStatic); } } else { fprintf(stderr, "Failed to find function!\n"); return NULL; } if (!isStatic) { args[argumentCount] = structInstance; argumentCount += 1; } for (i = 0; i < functionCallExpression->functionCallExpression .argumentSequence->functionArgumentSequence.count; i += 1) { args[argumentCount] = CompileExpression( structTypeDeclaration, builder, functionCallExpression->functionCallExpression.argumentSequence ->functionArgumentSequence.sequence[i]); argumentCount += 1; } if (LLVMGetTypeKind(functionReturnType) != LLVMVoidTypeKind) { returnName = "callReturn"; } return LLVMBuildCall(builder, function, args, argumentCount, returnName); } static LLVMValueRef CompileSystemCallExpression( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, Node *systemCallExpression) { uint32_t i; uint32_t argumentCount = systemCallExpression->systemCall.argumentSequence ->functionArgumentSequence.count; LLVMValueRef args[argumentCount]; char *returnName = ""; for (i = 0; i < systemCallExpression->systemCall.argumentSequence ->functionArgumentSequence.count; i += 1) { args[i] = CompileExpression( structTypeDeclaration, builder, systemCallExpression->systemCall.argumentSequence ->functionArgumentSequence.sequence[i]); } SystemFunction *systemFunction = LookupSystemFunction(systemCallExpression); if (systemFunction == NULL) { /* special case for sizeof */ if (strcmp( systemCallExpression->systemCall.identifier->identifier.name, "sizeof") == 0) { TypeTag *typeTag = systemCallExpression->systemCall.genericArguments ->genericArguments.arguments[0] ->type.typeNode->typeTag; return LLVMSizeOf(ResolveType(ConcretizeType(typeTag))); } else { fprintf(stderr, "System function not found!"); return NULL; } } if (LLVMGetTypeKind(LLVMGetReturnType(systemFunction->functionType)) != LLVMVoidTypeKind) { returnName = "callReturn"; } return LLVMBuildCall( builder, systemFunction->function, args, argumentCount, returnName); } static LLVMValueRef CompileAccessExpressionForStore( LLVMBuilderRef builder, Node *accessExpression) { LLVMValueRef accesseeValue = FindVariablePointer( accessExpression->accessExpression.accessee->identifier.name); return FindStructFieldPointer( builder, accesseeValue, accessExpression->accessExpression.accessor->identifier.name); } static LLVMValueRef CompileAccessExpression( LLVMBuilderRef builder, Node *accessExpression) { LLVMValueRef accesseeValue = FindVariablePointer( accessExpression->accessExpression.accessee->identifier.name); LLVMValueRef access = FindStructFieldPointer( builder, accesseeValue, accessExpression->accessExpression.accessor->identifier.name); return LLVMBuildLoad( builder, access, accessExpression->accessExpression.accessor->identifier.name); } static LLVMValueRef CompileAllocExpression( LLVMBuilderRef builder, Node *allocExpression) { LLVMTypeRef type = ResolveType(allocExpression->typeTag); return LLVMBuildMalloc(builder, type, "allocation"); } static LLVMValueRef CompileExpression( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, Node *expression) { switch (expression->syntaxKind) { case AccessExpression: return CompileAccessExpression(builder, expression); case AllocExpression: return CompileAllocExpression(builder, expression); case BinaryExpression: return CompileBinaryExpression( structTypeDeclaration, builder, expression); case FunctionCallExpression: return CompileFunctionCallExpression( structTypeDeclaration, builder, expression); case Identifier: return FindVariableValue(builder, expression->identifier.name); case Number: return CompileNumber(expression); case StringLiteral: return CompileString(builder, expression); case SystemCall: return CompileSystemCallExpression( structTypeDeclaration, builder, expression); } fprintf(stderr, "Unknown expression kind!\n"); return NULL; } static LLVMBasicBlockRef CompileReturn( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, LLVMValueRef function, Node *returnStatemement) { LLVMValueRef expression = CompileExpression( structTypeDeclaration, builder, returnStatemement->returnStatement.expression); LLVMBuildRet(builder, expression); return LLVMGetLastBasicBlock(function); } static LLVMBasicBlockRef CompileReturnVoid( LLVMBuilderRef builder, LLVMValueRef function) { LLVMBuildRetVoid(builder); return LLVMGetLastBasicBlock(function); } /* FIXME: path for reference types */ static LLVMValueRef CompileFunctionVariableDeclaration( LLVMBuilderRef builder, LLVMValueRef function, Node *variableDeclaration) { LLVMValueRef variable; char *variableName = variableDeclaration->declaration.identifier->identifier.name; char *ptrName = strdup(variableName); strcat(ptrName, "_ptr"); variable = LLVMBuildAlloca( builder, ResolveType(variableDeclaration->declaration.identifier->typeTag), ptrName); free(ptrName); AddLocalVariable(scope, variable, NULL, variableName); return variable; } static LLVMBasicBlockRef CompileAssignment( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, LLVMValueRef function, Node *assignmentStatement) { LLVMValueRef result = CompileExpression( structTypeDeclaration, builder, assignmentStatement->assignmentStatement.right); LLVMValueRef identifier; if (assignmentStatement->assignmentStatement.left->syntaxKind == AccessExpression) { identifier = CompileAccessExpressionForStore( builder, assignmentStatement->assignmentStatement.left); } else if ( assignmentStatement->assignmentStatement.left->syntaxKind == Identifier) { identifier = FindVariablePointer( assignmentStatement->assignmentStatement.left->identifier.name); } else if ( assignmentStatement->assignmentStatement.left->syntaxKind == Declaration) { identifier = CompileFunctionVariableDeclaration( builder, function, assignmentStatement->assignmentStatement.left); } else { printf("Identifier not found!"); return LLVMGetLastBasicBlock(function); } LLVMBuildStore(builder, result, identifier); return LLVMGetLastBasicBlock(function); } static LLVMBasicBlockRef CompileIfStatement( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, LLVMValueRef function, Node *ifStatement) { uint32_t i; LLVMValueRef conditional = CompileExpression( structTypeDeclaration, builder, ifStatement->ifStatement.expression); LLVMBasicBlockRef block = LLVMAppendBasicBlock(function, "ifBlock"); LLVMBasicBlockRef afterCond = LLVMAppendBasicBlock(function, "afterCond"); LLVMBuildCondBr(builder, conditional, block, afterCond); LLVMPositionBuilderAtEnd(builder, block); for (i = 0; i < ifStatement->ifStatement.statementSequence->statementSequence.count; i += 1) { CompileStatement( structTypeDeclaration, builder, function, ifStatement->ifStatement.statementSequence->statementSequence .sequence[i]); } LLVMBuildBr(builder, afterCond); LLVMPositionBuilderAtEnd(builder, afterCond); return afterCond; } static LLVMBasicBlockRef CompileIfElseStatement( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, LLVMValueRef function, Node *ifElseStatement) { uint32_t i; LLVMValueRef conditional = CompileExpression( structTypeDeclaration, builder, ifElseStatement->ifElseStatement.ifStatement->ifStatement.expression); LLVMBasicBlockRef ifBlock = LLVMAppendBasicBlock(function, "ifBlock"); LLVMBasicBlockRef elseBlock = LLVMAppendBasicBlock(function, "elseBlock"); LLVMBasicBlockRef afterCond = LLVMAppendBasicBlock(function, "afterCond"); LLVMBuildCondBr(builder, conditional, ifBlock, elseBlock); LLVMPositionBuilderAtEnd(builder, ifBlock); for (i = 0; i < ifElseStatement->ifElseStatement.ifStatement->ifStatement .statementSequence->statementSequence.count; i += 1) { CompileStatement( structTypeDeclaration, builder, function, ifElseStatement->ifElseStatement.ifStatement->ifStatement .statementSequence->statementSequence.sequence[i]); } LLVMBuildBr(builder, afterCond); LLVMPositionBuilderAtEnd(builder, elseBlock); if (ifElseStatement->ifElseStatement.elseStatement->syntaxKind == StatementSequence) { for (i = 0; i < ifElseStatement->ifElseStatement.elseStatement ->statementSequence.count; i += 1) { CompileStatement( structTypeDeclaration, builder, function, ifElseStatement->ifElseStatement.elseStatement ->statementSequence.sequence[i]); } } else { CompileStatement( structTypeDeclaration, builder, function, ifElseStatement->ifElseStatement.elseStatement); } LLVMBuildBr(builder, afterCond); LLVMPositionBuilderAtEnd(builder, afterCond); return afterCond; } static LLVMBasicBlockRef CompileForLoopStatement( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, LLVMValueRef function, Node *forLoopStatement) { uint32_t i; LLVMBasicBlockRef entryBlock = LLVMAppendBasicBlock(function, "loopEntry"); LLVMBasicBlockRef checkBlock = LLVMAppendBasicBlock(function, "loopCheck"); LLVMBasicBlockRef bodyBlock = LLVMAppendBasicBlock(function, "loopBody"); LLVMBasicBlockRef afterLoopBlock = LLVMAppendBasicBlock(function, "afterLoop"); char *iteratorVariableName = forLoopStatement->forLoop.declaration ->declaration.identifier->identifier.name; LLVMTypeRef iteratorVariableType = ResolveType( forLoopStatement->forLoop.declaration->declaration.identifier->typeTag); PushScopeFrame(scope); LLVMBuildBr(builder, entryBlock); LLVMPositionBuilderAtEnd(builder, entryBlock); LLVMBuildBr(builder, checkBlock); LLVMPositionBuilderAtEnd(builder, checkBlock); LLVMValueRef iteratorValue = LLVMBuildPhi(builder, iteratorVariableType, iteratorVariableName); AddLocalVariable(scope, NULL, iteratorValue, iteratorVariableName); LLVMPositionBuilderAtEnd(builder, bodyBlock); LLVMValueRef nextValue = LLVMBuildAdd( builder, iteratorValue, LLVMConstInt( iteratorVariableType, 1, 0), /* FIXME: add custom increment value */ "next"); LLVMPositionBuilderAtEnd(builder, checkBlock); LLVMValueRef iteratorEndValue = CompileNumber(forLoopStatement->forLoop.endNumber); LLVMValueRef comparison = LLVMBuildICmp( builder, LLVMIntULE, iteratorValue, iteratorEndValue, "iteratorCompare"); LLVMBuildCondBr(builder, comparison, bodyBlock, afterLoopBlock); LLVMPositionBuilderAtEnd(builder, bodyBlock); LLVMBasicBlockRef lastBlock; for (i = 0; i < forLoopStatement->forLoop.statementSequence->statementSequence.count; i += 1) { lastBlock = CompileStatement( structTypeDeclaration, builder, function, forLoopStatement->forLoop.statementSequence->statementSequence .sequence[i]); } LLVMBuildBr(builder, checkBlock); LLVMPositionBuilderBefore(builder, LLVMGetFirstInstruction(checkBlock)); LLVMValueRef incomingValues[2]; incomingValues[0] = CompileNumber(forLoopStatement->forLoop.startNumber); incomingValues[1] = nextValue; LLVMBasicBlockRef incomingBlocks[2]; incomingBlocks[0] = entryBlock; incomingBlocks[1] = lastBlock; LLVMAddIncoming(iteratorValue, incomingValues, incomingBlocks, 2); LLVMPositionBuilderAtEnd(builder, afterLoopBlock); PopScopeFrame(scope); return afterLoopBlock; } static LLVMBasicBlockRef CompileStatement( StructTypeDeclaration *structTypeDeclaration, LLVMBuilderRef builder, LLVMValueRef function, Node *statement) { switch (statement->syntaxKind) { case Assignment: return CompileAssignment( structTypeDeclaration, builder, function, statement); case Declaration: CompileFunctionVariableDeclaration(builder, function, statement); return LLVMGetLastBasicBlock(function); case ForLoop: return CompileForLoopStatement( structTypeDeclaration, builder, function, statement); case FunctionCallExpression: CompileFunctionCallExpression( structTypeDeclaration, builder, statement); return LLVMGetLastBasicBlock(function); case IfStatement: return CompileIfStatement( structTypeDeclaration, builder, function, statement); case IfElseStatement: return CompileIfElseStatement( structTypeDeclaration, builder, function, statement); case Return: return CompileReturn( structTypeDeclaration, builder, function, statement); case ReturnVoid: return CompileReturnVoid(builder, function); case SystemCall: CompileSystemCallExpression(structTypeDeclaration, builder, statement); return LLVMGetLastBasicBlock(function); } fprintf(stderr, "Unknown statement kind!\n"); return NULL; } static void CompileFunction( StructTypeDeclaration *structTypeDeclaration, 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; 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(structTypeDeclaration->name); uint32_t nameLen = strlen(functionName); nameLen += 2 + strlen( functionSignature->functionSignature.identifier->identifier.name); functionName = realloc(functionName, sizeof(char) * nameLen); strcat(functionName, "_"); strcat( functionName, functionSignature->functionSignature.identifier->identifier.name); if (functionSignature->functionSignature.genericDeclarations ->genericDeclarations.count == 0) { PushScopeFrame(scope); if (!isStatic) { paramTypes[paramIndex] = structTypeDeclaration->structPointerType; 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( structTypeDeclaration->module, functionName, functionType); DeclareStructFunction( structTypeDeclaration, function, returnType, isStatic, functionSignature->functionSignature.identifier->identifier.name); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry"); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, entry); if (!isStatic) { LLVMValueRef wStructPointer = LLVMGetParam(function, 0); AddStructVariablesToScope( structTypeDeclaration, 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( structTypeDeclaration, 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); } else { DeclareGenericStructFunction( structTypeDeclaration, functionDeclaration, isStatic, functionSignature->functionSignature.identifier->identifier.name); } free(functionName); } static void CompileStruct( LLVMModuleRef module, LLVMContextRef context, Node *node) { uint32_t i; uint32_t fieldCount = 0; uint32_t declarationCount = node->structDeclaration.declarationSequence->declarationSequence.count; uint8_t packed = 1; LLVMTypeRef types[declarationCount]; Node *currentDeclarationNode; char *structName = node->structDeclaration.identifier->identifier.name; PushScopeFrame(scope); if (node->structDeclaration.genericDeclarations->genericDeclarations .count == 0) { LLVMTypeRef wStructType = LLVMStructCreateNamed(context, structName); LLVMTypeRef wStructPointerType = LLVMPointerType( wStructType, 0); /* FIXME: is this address space correct? */ StructTypeDeclaration *structTypeDeclaration = AddStructDeclaration( module, wStructType, wStructPointerType, structName); /* first, build the structure definition */ for (i = 0; i < declarationCount; i += 1) { currentDeclarationNode = node->structDeclaration.declarationSequence->declarationSequence .sequence[i]; switch (currentDeclarationNode->syntaxKind) { case Declaration: /* FIXME: this is badly named */ types[fieldCount] = ResolveType( currentDeclarationNode->declaration.identifier->typeTag); AddFieldToStructDeclaration( structTypeDeclaration, currentDeclarationNode->declaration.identifier->identifier .name); fieldCount += 1; break; } } LLVMStructSetBody(wStructType, types, fieldCount, packed); /* now we can wire up the functions */ for (i = 0; i < declarationCount; i += 1) { currentDeclarationNode = node->structDeclaration.declarationSequence->declarationSequence .sequence[i]; switch (currentDeclarationNode->syntaxKind) { case FunctionDeclaration: CompileFunction(structTypeDeclaration, currentDeclarationNode); break; } } } else { AddGenericStructDeclaration(module, node); } PopScopeFrame(scope); } static void Compile( LLVMModuleRef module, LLVMContextRef context, Node *declarationSequenceNode) { uint32_t i; for (i = 0; i < declarationSequenceNode->declarationSequence.count; i += 1) { if (declarationSequenceNode->declarationSequence.sequence[i] ->syntaxKind == StructDeclaration) { CompileStruct( module, context, declarationSequenceNode->declarationSequence.sequence[i]); } else { fprintf( stderr, "top level declarations that are not structs are " "forbidden!\n"); } } } /* TODO: move this to some kind of standard library file? */ static void RegisterLibraryFunctions( LLVMModuleRef module, LLVMContextRef context) { LLVMTypeRef structType = LLVMStructCreateNamed(context, "Console"); LLVMTypeRef structPointerType = LLVMPointerType(structType, 0); StructTypeDeclaration *structTypeDeclaration = AddStructDeclaration(module, structType, structPointerType, "Console"); LLVMTypeRef printfArg = LLVMPointerType(LLVMInt8Type(), 0); LLVMTypeRef printfFunctionType = LLVMFunctionType(LLVMInt32Type(), &printfArg, 1, 1); LLVMValueRef printfFunction = LLVMAddFunction(module, "printf", printfFunctionType); LLVMSetLinkage(printfFunction, LLVMExternalLinkage); LLVMTypeRef printLineFunctionType = LLVMFunctionType(LLVMInt32Type(), &printfArg, 1, 1); LLVMValueRef printLineFunction = LLVMAddFunction(module, "printLine", printLineFunctionType); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(printLineFunction, "entry"); LLVMPositionBuilderAtEnd(builder, entry); LLVMValueRef newLine = LLVMBuildGlobalStringPtr(builder, "\n", "newline"); LLVMValueRef printParams[LLVMCountParams(printLineFunction)]; LLVMGetParams(printLineFunction, printParams); LLVMValueRef stringPrint = LLVMBuildCall( builder, printfFunction, printParams, LLVMCountParams(printLineFunction), "printfCall"); LLVMValueRef newlinePrint = LLVMBuildCall(builder, printfFunction, &newLine, 1, "printNewLine"); LLVMBuildRet( builder, LLVMBuildAnd(builder, stringPrint, newlinePrint, "and")); DeclareStructFunction( structTypeDeclaration, printLineFunction, LLVMInt8Type(), 1, "PrintLine"); LLVMTypeRef mallocArg = LLVMInt64Type(); LLVMTypeRef mallocFunctionType = LLVMFunctionType(LLVMInt64Type(), &mallocArg, 1, 0); LLVMValueRef mallocFunction = LLVMAddFunction(module, "malloc", mallocFunctionType); LLVMSetLinkage(mallocFunction, LLVMExternalLinkage); AddSystemFunction("malloc", mallocFunctionType, mallocFunction); LLVMTypeRef freeArg = LLVMInt64Type(); LLVMTypeRef freeFunctionType = LLVMFunctionType(LLVMVoidType(), &freeArg, 1, 0); LLVMValueRef freeFunction = LLVMAddFunction(module, "free", freeFunctionType); LLVMSetLinkage(freeFunction, LLVMExternalLinkage); AddSystemFunction("free", freeFunctionType, freeFunction); LLVMDisposeBuilder(builder); } int Codegen(Node *node, uint32_t optimizationLevel) { scope = CreateScope(); structTypeDeclarations = NULL; structTypeDeclarationCount = 0; genericStructTypeDeclarations = NULL; genericStructTypeDeclarationCount = 0; systemFunctions = NULL; systemFunctionCount = 0; LLVMModuleRef module = LLVMModuleCreateWithName("my_module"); LLVMContextRef context = LLVMGetGlobalContext(); RegisterLibraryFunctions(module, context); Compile(module, context, node); /* add main call */ LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMTypeRef mainFunctionType = LLVMFunctionType(LLVMInt64Type(), NULL, 0, 0); LLVMValueRef mainFunction = LLVMAddFunction(module, "main", mainFunctionType); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(mainFunction, "entry"); LLVMPositionBuilderAtEnd(builder, entry); LLVMValueRef wraithMainFunction = LLVMGetNamedFunction(module, "Program_Main"); LLVMValueRef mainResult = LLVMBuildCall(builder, wraithMainFunction, NULL, 0, "result"); LLVMBuildRet(builder, mainResult); LLVMDisposeBuilder(builder); /* verify */ char *error = NULL; if (LLVMVerifyModule(module, LLVMAbortProcessAction, &error) != 0) { fprintf(stderr, "%s\n", error); LLVMDisposeMessage(error); return EXIT_FAILURE; } /* prepare to emit assembly */ LLVMInitializeNativeTarget(); LLVMInitializeAllTargetInfos(); LLVMInitializeAllTargets(); LLVMInitializeAllTargetMCs(); LLVMInitializeAllAsmParsers(); LLVMInitializeAllAsmPrinters(); LLVMSetTarget(module, LLVM_DEFAULT_TARGET_TRIPLE); LLVMTargetRef target; if (LLVMGetTargetFromTriple(LLVM_DEFAULT_TARGET_TRIPLE, &target, &error) != 0) { fprintf(stderr, "Failed to get target!\n"); fprintf(stderr, "%s\n", error); LLVMDisposeMessage(error); return EXIT_FAILURE; } LLVMPassManagerRef passManager = LLVMCreatePassManager(); LLVMPassManagerBuilderRef passManagerBuilder = LLVMPassManagerBuilderCreate(); LLVMPassManagerBuilderSetOptLevel(passManagerBuilder, optimizationLevel); LLVMPassManagerBuilderPopulateModulePassManager( passManagerBuilder, passManager); LLVMRunPassManager(passManager, module); if (LLVMWriteBitcodeToFile(module, "test.bc") != 0) { fprintf(stderr, "error writing bitcode to file\n"); return EXIT_FAILURE; } char *cpu = "generic"; char *features = ""; LLVMTargetMachineRef targetMachine = LLVMCreateTargetMachine( target, LLVM_DEFAULT_TARGET_TRIPLE, cpu, features, LLVMCodeGenLevelDefault, LLVMRelocDefault, LLVMCodeModelDefault); if (LLVMTargetMachineEmitToFile( targetMachine, module, "test.o", LLVMObjectFile, &error) != 0) { fprintf(stderr, "Failed to emit machine code!\n"); fprintf(stderr, "%s\n", error); LLVMDisposeMessage(error); return EXIT_FAILURE; } LLVMDisposeMessage(error); LLVMDisposeTargetMachine(targetMachine); LLVMPassManagerBuilderDispose(passManagerBuilder); LLVMDisposePassManager(passManager); LLVMDisposeModule(module); return EXIT_SUCCESS; }