wraith-lang/src/codegen.c

2342 lines
70 KiB
C
Raw Normal View History

2021-04-18 22:29:54 +00:00
#include <stdio.h>
2021-04-20 01:18:45 +00:00
#include <stdlib.h>
#include <string.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/BitWriter.h>
2021-05-16 07:42:37 +00:00
#include <llvm-c/Core.h>
2021-04-22 07:35:42 +00:00
#include <llvm-c/Object.h>
2021-05-16 07:42:37 +00:00
#include <llvm-c/Target.h>
#include <llvm-c/TargetMachine.h>
2021-04-22 05:48:55 +00:00
#include <llvm-c/Transforms/InstCombine.h>
2021-05-16 07:42:37 +00:00
#include <llvm-c/Transforms/PassManagerBuilder.h>
2021-04-22 05:48:55 +00:00
#include <llvm-c/Transforms/Scalar.h>
#include <llvm-c/Transforms/Utils.h>
2021-04-18 22:45:06 +00:00
#include "ast.h"
#include "util.h"
2021-04-18 22:45:06 +00:00
2021-04-22 04:29:38 +00:00
typedef struct LocalVariable
{
char *name;
LLVMValueRef pointer;
2021-04-30 06:49:35 +00:00
LLVMValueRef value;
2021-04-22 04:29:38 +00:00
} LocalVariable;
typedef struct LocalGenericType
{
char *name;
TypeTag *concreteTypeTag;
LLVMTypeRef type;
} LocalGenericType;
2021-04-22 04:29:38 +00:00
typedef struct FunctionArgument
2021-04-21 02:00:18 +00:00
{
char *name;
LLVMValueRef value;
2021-04-22 04:29:38 +00:00
} FunctionArgument;
typedef struct ScopeFrame
{
LocalVariable *localVariables;
uint32_t localVariableCount;
LocalGenericType *genericTypes;
uint32_t genericTypeCount;
2021-04-22 04:29:38 +00:00
} ScopeFrame;
typedef struct Scope
{
ScopeFrame *scopeStack;
uint32_t scopeStackCount;
} Scope;
Scope *scope;
typedef struct StructTypeField
{
char *name;
2021-04-21 02:40:39 +00:00
uint32_t index;
2021-04-22 04:29:38 +00:00
} StructTypeField;
2021-04-21 02:00:18 +00:00
2021-04-23 00:19:35 +00:00
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
2021-06-03 21:40:14 +00:00
typedef struct StructTypeDeclaration StructTypeDeclaration;
typedef struct StructTypeGenericFunction
{
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *parentStruct;
char *name;
Node *functionDeclarationNode;
uint8_t isStatic;
MonomorphizedGenericFunctionHashArray
monomorphizedFunctions[NUM_MONOMORPHIZED_HASH_BUCKETS];
} StructTypeGenericFunction;
2021-06-03 21:40:14 +00:00
struct StructTypeDeclaration
2021-04-21 02:00:18 +00:00
{
2021-06-03 21:40:14 +00:00
LLVMModuleRef module;
2021-04-23 05:37:23 +00:00
char *name;
2021-04-22 04:29:38 +00:00
LLVMTypeRef structType;
2021-04-23 05:37:23 +00:00
LLVMTypeRef structPointerType;
2021-04-22 04:29:38 +00:00
StructTypeField *fields;
2021-04-21 02:00:18 +00:00
uint32_t fieldCount;
2021-04-23 00:19:35 +00:00
StructTypeFunction *functions;
uint32_t functionCount;
StructTypeGenericFunction *genericFunctions;
uint32_t genericFunctionCount;
2021-06-03 21:40:14 +00:00
};
2021-04-21 02:00:18 +00:00
2021-04-23 05:37:23 +00:00
StructTypeDeclaration *structTypeDeclarations;
uint32_t structTypeDeclarationCount;
2021-04-22 04:29:38 +00:00
2021-06-03 00:26:26 +00:00
typedef struct MonomorphizedGenericStructHashEntry
{
uint64_t key;
TypeTag **types;
uint32_t typeCount;
2021-06-03 22:08:01 +00:00
StructTypeDeclaration *structDeclaration;
2021-06-03 00:26:26 +00:00
} MonomorphizedGenericStructHashEntry;
typedef struct MonomorphizedGenericStructHashArray
{
MonomorphizedGenericStructHashEntry *elements;
uint32_t count;
} MonomorphizedGenericStructHashArray;
typedef struct GenericStructTypeDeclaration
{
2021-06-03 21:40:14 +00:00
LLVMModuleRef module;
2021-06-03 00:26:26 +00:00
Node *structDeclarationNode;
MonomorphizedGenericStructHashArray
monomorphizedStructs[NUM_MONOMORPHIZED_HASH_BUCKETS];
} GenericStructTypeDeclaration;
GenericStructTypeDeclaration *genericStructTypeDeclarations;
uint32_t genericStructTypeDeclarationCount;
2021-06-02 19:33:01 +00:00
typedef struct SystemFunction
{
char *name;
LLVMTypeRef functionType;
LLVMValueRef function;
} SystemFunction;
SystemFunction *systemFunctions;
uint32_t systemFunctionCount;
/* FUNCTION FORWARD DECLARATIONS */
static LLVMBasicBlockRef CompileStatement(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
LLVMBuilderRef builder,
LLVMValueRef function,
Node *statement);
static LLVMValueRef CompileExpression(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
LLVMBuilderRef builder,
Node *expression);
2021-06-03 21:40:14 +00:00
static void CompileFunction(
StructTypeDeclaration *structTypeDeclaration,
Node *functionDeclaration);
static LLVMTypeRef ResolveType(TypeTag *typeTag);
2021-05-16 07:42:37 +00:00
static Scope *CreateScope()
2021-04-21 02:00:18 +00:00
{
2021-04-22 04:29:38 +00:00
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;
2021-04-22 04:29:38 +00:00
scope->scopeStackCount = 1;
return scope;
2021-04-21 02:00:18 +00:00
}
2021-04-22 04:29:38 +00:00
static void PushScopeFrame(Scope *scope)
2021-04-21 02:00:18 +00:00
{
2021-04-22 04:29:38 +00:00
uint32_t index = scope->scopeStackCount;
2021-05-16 07:42:37 +00:00
scope->scopeStack = realloc(
scope->scopeStack,
sizeof(ScopeFrame) * (scope->scopeStackCount + 1));
2021-04-22 04:29:38 +00:00
scope->scopeStack[index].localVariableCount = 0;
scope->scopeStack[index].localVariables = NULL;
scope->scopeStack[index].genericTypeCount = 0;
scope->scopeStack[index].genericTypes = NULL;
2021-04-22 04:29:38 +00:00
scope->scopeStackCount += 1;
}
2021-04-21 02:00:18 +00:00
2021-04-22 04:29:38 +00:00
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);
2021-04-21 02:00:18 +00:00
}
2021-04-22 04:29:38 +00:00
free(scope->scopeStack[index].localVariables);
2021-04-21 02:00:18 +00:00
}
2021-04-22 04:29:38 +00:00
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);
}
2021-04-22 04:29:38 +00:00
scope->scopeStackCount -= 1;
2021-05-16 07:42:37 +00:00
scope->scopeStack =
realloc(scope->scopeStack, sizeof(ScopeFrame) * scope->scopeStackCount);
2021-04-21 02:00:18 +00:00
}
2021-06-03 21:40:14 +00:00
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();
2021-06-02 19:44:36 +00:00
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;
}
2021-06-03 00:26:26 +00:00
static TypeTag *ConcretizeType(TypeTag *type)
{
2021-06-03 00:26:26 +00:00
if (type->type == Generic)
{
2021-06-03 00:26:26 +00:00
return LookupGenericType(type->value.genericType)->concreteTypeTag;
}
2021-06-03 00:26:26 +00:00
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;
}
}
2021-06-03 00:26:26 +00:00
fprintf(stderr, "Could not find custom type!\n");
return NULL;
}
2021-06-03 22:08:01 +00:00
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(
2021-06-03 21:40:14 +00:00
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);
2021-06-03 22:08:01 +00:00
StructTypeDeclaration *declaration = AddStructDeclaration(
genericStructTypeDeclaration->module,
wStructType,
wStructPointerType,
structName);
2021-06-03 21:40:14 +00:00
/* 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(
2021-06-03 22:08:01 +00:00
declaration,
2021-06-03 21:40:14 +00:00
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(
2021-06-03 22:08:01 +00:00
declaration,
2021-06-03 21:40:14 +00:00
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)
{
2021-06-03 22:08:01 +00:00
StructTypeDeclaration *structTypeDeclaration =
2021-06-03 21:40:14 +00:00
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];
}
2021-06-03 22:08:01 +00:00
return hashEntry->structDeclaration;
2021-06-03 21:40:14 +00:00
}
}
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;
}
2021-06-03 21:40:14 +00:00
else if (typeTag->type == ConcreteGeneric)
{
return LookupGenericStructType(&typeTag->value.concreteGenericType)
->structType;
}
else
{
fprintf(stderr, "Unknown type node!\n");
return NULL;
}
}
2021-06-02 19:33:01 +00:00
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;
}
2021-06-03 00:26:26 +00:00
static SystemFunction *LookupSystemFunction(Node *systemCallExpression)
2021-06-02 19:33:01 +00:00
{
uint32_t i;
2021-06-03 00:26:26 +00:00
char *name = systemCallExpression->systemCall.identifier->identifier.name;
2021-06-02 19:33:01 +00:00
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;
}
2021-04-23 05:37:23 +00:00
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;
}
2021-05-16 07:42:37 +00:00
static LLVMValueRef FindStructFieldPointer(
LLVMBuilderRef builder,
LLVMValueRef structPointer,
char *name)
2021-04-22 04:29:38 +00:00
{
int32_t i, j;
2021-04-23 05:37:23 +00:00
LLVMTypeRef structPointerType = LLVMTypeOf(structPointer);
2021-04-22 04:29:38 +00:00
2021-04-23 05:37:23 +00:00
for (i = 0; i < structTypeDeclarationCount; i += 1)
2021-04-21 02:40:39 +00:00
{
2021-04-23 05:37:23 +00:00
if (structTypeDeclarations[i].structPointerType == structPointerType)
2021-04-21 02:40:39 +00:00
{
2021-04-23 05:37:23 +00:00
for (j = 0; j < structTypeDeclarations[i].fieldCount; j += 1)
2021-04-21 02:40:39 +00:00
{
2021-04-23 05:37:23 +00:00
if (strcmp(structTypeDeclarations[i].fields[j].name, name) == 0)
2021-04-21 02:40:39 +00:00
{
2021-04-22 04:29:38 +00:00
char *ptrName = strdup(name);
strcat(ptrName, "_ptr");
return LLVMBuildStructGEP(
builder,
structPointer,
2021-04-23 05:37:23 +00:00
structTypeDeclarations[i].fields[j].index,
2021-05-16 07:42:37 +00:00
ptrName);
2021-04-22 04:29:38 +00:00
free(ptrName);
2021-04-21 02:40:39 +00:00
}
}
}
}
2021-04-22 04:29:38 +00:00
printf("Failed to find struct field pointer!");
2021-04-21 02:40:39 +00:00
return NULL;
}
2021-04-22 04:29:38 +00:00
static LLVMValueRef FindVariablePointer(char *name)
2021-04-21 02:07:11 +00:00
{
2021-04-22 04:29:38 +00:00
int32_t i, j;
2021-04-21 02:07:11 +00:00
2021-04-22 04:29:38 +00:00
for (i = scope->scopeStackCount - 1; i >= 0; i -= 1)
2021-04-21 02:07:11 +00:00
{
2021-04-22 04:29:38 +00:00
for (j = 0; j < scope->scopeStack[i].localVariableCount; j += 1)
2021-04-21 02:07:11 +00:00
{
2021-04-22 04:29:38 +00:00
if (strcmp(scope->scopeStack[i].localVariables[j].name, name) == 0)
2021-04-21 02:07:11 +00:00
{
2021-04-22 04:29:38 +00:00
return scope->scopeStack[i].localVariables[j].pointer;
2021-04-21 02:07:11 +00:00
}
}
}
2021-04-22 04:29:38 +00:00
printf("Failed to find variable pointer!");
return NULL;
2021-04-21 02:07:11 +00:00
}
2021-04-22 04:29:38 +00:00
static LLVMValueRef FindVariableValue(LLVMBuilderRef builder, char *name)
2021-04-21 02:00:18 +00:00
{
2021-04-22 04:29:38 +00:00
int32_t i, j;
2021-04-21 02:00:18 +00:00
2021-04-22 04:29:38 +00:00
for (i = scope->scopeStackCount - 1; i >= 0; i -= 1)
2021-04-21 02:00:18 +00:00
{
2021-04-22 04:29:38 +00:00
for (j = 0; j < scope->scopeStack[i].localVariableCount; j += 1)
{
if (strcmp(scope->scopeStack[i].localVariables[j].name, name) == 0)
{
2021-04-30 06:49:35 +00:00
if (scope->scopeStack[i].localVariables[j].value != NULL)
{
return scope->scopeStack[i].localVariables[j].value;
}
else
{
2021-05-16 07:42:37 +00:00
return LLVMBuildLoad(
builder,
scope->scopeStack[i].localVariables[j].pointer,
name);
2021-04-30 06:49:35 +00:00
}
2021-04-21 02:00:18 +00:00
}
}
}
2021-04-22 04:29:38 +00:00
printf("Failed to find variable value!");
2021-04-21 02:00:18 +00:00
return NULL;
}
2021-04-23 00:19:35 +00:00
static void DeclareStructFunction(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
2021-04-23 00:19:35 +00:00
LLVMValueRef function,
LLVMTypeRef returnType,
uint8_t isStatic,
2021-05-16 07:42:37 +00:00
char *name)
{
2021-06-03 21:40:14 +00:00
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;
2021-04-23 00:19:35 +00:00
}
static void DeclareGenericStructFunction(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
Node *functionDeclarationNode,
uint8_t isStatic,
char *name)
2021-04-23 05:37:23 +00:00
{
2021-06-03 21:40:14 +00:00
uint32_t i, index;
2021-04-23 05:37:23 +00:00
2021-06-03 21:40:14 +00:00
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;
2021-06-03 21:40:14 +00:00
for (i = 0; i < NUM_MONOMORPHIZED_HASH_BUCKETS; i += 1)
{
2021-06-03 21:40:14 +00:00
structTypeDeclaration->genericFunctions[index]
.monomorphizedFunctions[i]
.elements = NULL;
structTypeDeclaration->genericFunctions[index]
.monomorphizedFunctions[i]
.count = 0;
}
2021-06-03 21:40:14 +00:00
structTypeDeclaration->genericFunctionCount += 1;
2021-04-23 05:37:23 +00:00
}
/* FIXME: lots of duplication with non-generic function compile */
static StructTypeFunction CompileGenericFunction(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
TypeTag **resolvedGenericArgumentTypes,
uint32_t genericArgumentTypeCount,
Node *functionDeclaration)
2021-04-24 20:53:21 +00:00
{
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)
2021-04-24 20:53:21 +00:00
{
AddGenericVariable(
scope,
resolvedGenericArgumentTypes[i],
functionDeclaration->functionDeclaration.functionSignature
->functionSignature.genericDeclarations->genericDeclarations
.declarations[i]
->genericDeclaration.identifier->identifier.name);
2021-04-24 20:53:21 +00:00
}
if (functionSignature->functionSignature.modifiers->functionModifiers
.count > 0)
2021-04-24 20:53:21 +00:00
{
for (i = 0; i < functionSignature->functionSignature.modifiers
->functionModifiers.count;
i += 1)
{
if (functionSignature->functionSignature.modifiers
->functionModifiers.sequence[i]
->syntaxKind == StaticModifier)
{
isStatic = 1;
break;
}
}
2021-04-24 20:53:21 +00:00
}
2021-06-03 21:40:14 +00:00
/* 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)
2021-04-24 20:53:21 +00:00
{
strcat(functionName, TypeTagToString(resolvedGenericArgumentTypes[i]));
2021-04-24 20:53:21 +00:00
}
if (!isStatic)
2021-04-24 20:53:21 +00:00
{
2021-06-03 21:40:14 +00:00
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);
2021-06-03 21:40:14 +00:00
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);
2021-06-03 21:40:14 +00:00
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(
2021-06-03 21:40:14 +00:00
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!");
2021-04-24 20:53:21 +00:00
}
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,
2021-06-03 00:26:26 +00:00
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];
2021-06-03 00:26:26 +00:00
uint32_t argumentCount = 0;
TypeTag
*argumentTypes[functionCallExpression->functionCallExpression
.argumentSequence->functionArgumentSequence.count];
2021-06-03 00:26:26 +00:00
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)
{
2021-06-03 00:26:26 +00:00
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;
2021-06-03 00:26:26 +00:00
j += 1)
{
2021-06-03 00:26:26 +00:00
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)
{
2021-06-03 00:26:26 +00:00
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(
2021-06-03 21:40:14 +00:00
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;
2021-04-24 20:53:21 +00:00
}
2021-04-23 05:37:23 +00:00
static LLVMValueRef LookupFunctionByType(
LLVMTypeRef structType,
2021-06-03 00:26:26 +00:00
Node *functionCallExpression,
2021-04-23 05:37:23 +00:00
LLVMTypeRef *pReturnType,
2021-05-16 07:42:37 +00:00
uint8_t *pStatic)
{
2021-04-23 05:37:23 +00:00
uint32_t i, j;
2021-06-03 00:26:26 +00:00
/* FIXME: hot garbage */
char *name = functionCallExpression->functionCallExpression.identifier
->accessExpression.accessor->identifier.name;
2021-04-23 05:37:23 +00:00
for (i = 0; i < structTypeDeclarationCount; i += 1)
{
if (structTypeDeclarations[i].structType == structType)
{
for (j = 0; j < structTypeDeclarations[i].functionCount; j += 1)
{
2021-05-16 07:42:37 +00:00
if (strcmp(structTypeDeclarations[i].functions[j].name, name) ==
0)
2021-04-23 05:37:23 +00:00
{
2021-05-16 07:42:37 +00:00
*pReturnType =
structTypeDeclarations[i].functions[j].returnType;
2021-04-23 05:37:23 +00:00
*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],
2021-06-03 00:26:26 +00:00
functionCallExpression,
pReturnType,
pStatic);
}
}
2021-04-23 05:37:23 +00:00
}
}
fprintf(stderr, "Could not find struct function!\n");
return NULL;
}
static LLVMValueRef LookupFunctionByPointerType(
LLVMTypeRef structPointerType,
2021-06-03 00:26:26 +00:00
Node *functionCallExpression,
2021-04-23 00:19:35 +00:00
LLVMTypeRef *pReturnType,
2021-05-16 07:42:37 +00:00
uint8_t *pStatic)
{
2021-04-23 00:19:35 +00:00
uint32_t i, j;
2021-06-03 00:26:26 +00:00
/* FIXME: hot garbage */
char *name = functionCallExpression->functionCallExpression.identifier
->accessExpression.accessor->identifier.name;
2021-04-23 00:19:35 +00:00
2021-04-23 05:37:23 +00:00
for (i = 0; i < structTypeDeclarationCount; i += 1)
2021-04-23 00:19:35 +00:00
{
2021-04-23 05:37:23 +00:00
if (structTypeDeclarations[i].structPointerType == structPointerType)
2021-04-23 00:19:35 +00:00
{
2021-04-23 05:37:23 +00:00
for (j = 0; j < structTypeDeclarations[i].functionCount; j += 1)
2021-04-23 00:19:35 +00:00
{
2021-05-16 07:42:37 +00:00
if (strcmp(structTypeDeclarations[i].functions[j].name, name) ==
0)
2021-04-23 00:19:35 +00:00
{
2021-05-16 07:42:37 +00:00
*pReturnType =
structTypeDeclarations[i].functions[j].returnType;
2021-04-23 05:37:23 +00:00
*pStatic = structTypeDeclarations[i].functions[j].isStatic;
return structTypeDeclarations[i].functions[j].function;
2021-04-23 00:19:35 +00:00
}
}
for (j = 0; j < structTypeDeclarations[i].genericFunctionCount;
j += 1)
{
if (strcmp(
structTypeDeclarations[i].genericFunctions[j].name,
name) == 0)
{
return LookupGenericFunction(
&structTypeDeclarations[i].genericFunctions[j],
2021-06-03 00:26:26 +00:00
functionCallExpression,
pReturnType,
pStatic);
}
}
2021-04-23 00:19:35 +00:00
}
}
2021-04-23 05:37:23 +00:00
fprintf(stderr, "Could not find struct function!\n");
2021-04-23 00:19:35 +00:00
return NULL;
}
2021-04-23 05:37:23 +00:00
static LLVMValueRef LookupFunctionByInstance(
LLVMValueRef structPointer,
2021-06-03 00:26:26 +00:00
Node *functionCallExpression,
2021-04-23 05:37:23 +00:00
LLVMTypeRef *pReturnType,
2021-05-16 07:42:37 +00:00
uint8_t *pStatic)
{
return LookupFunctionByPointerType(
LLVMTypeOf(structPointer),
2021-06-03 00:26:26 +00:00
functionCallExpression,
2021-05-16 07:42:37 +00:00
pReturnType,
pStatic);
2021-04-23 05:37:23 +00:00
}
2021-05-16 07:42:37 +00:00
static LLVMValueRef CompileNumber(Node *numberExpression)
{
return LLVMConstInt(LLVMInt64Type(), numberExpression->number.value, 0);
2021-04-20 01:18:45 +00:00
}
2021-04-30 19:17:44 +00:00
static LLVMValueRef CompileString(
LLVMBuilderRef builder,
2021-05-16 07:42:37 +00:00
Node *stringExpression)
{
return LLVMBuildGlobalStringPtr(
builder,
stringExpression->stringLiteral.string,
"stringConstant");
2021-04-30 19:17:44 +00:00
}
2021-04-20 01:18:45 +00:00
static LLVMValueRef CompileBinaryExpression(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
2021-04-20 01:18:45 +00:00
LLVMBuilderRef builder,
2021-05-16 07:42:37 +00:00
Node *binaryExpression)
{
LLVMValueRef left = CompileExpression(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
builder,
binaryExpression->binaryExpression.left);
LLVMValueRef right = CompileExpression(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
builder,
binaryExpression->binaryExpression.right);
2021-04-20 01:18:45 +00:00
switch (binaryExpression->binaryExpression.operator)
2021-04-20 01:18:45 +00:00
{
2021-05-16 07:42:37 +00:00
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");
2021-04-20 01:18:45 +00:00
}
return NULL;
}
2021-04-22 04:29:38 +00:00
/* FIXME THIS IS ALL BROKEN */
2021-04-20 17:47:40 +00:00
static LLVMValueRef CompileFunctionCallExpression(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
2021-04-20 17:47:40 +00:00
LLVMBuilderRef builder,
2021-05-16 07:42:37 +00:00
Node *functionCallExpression)
{
2021-04-20 17:47:40 +00:00
uint32_t i;
2021-04-23 00:19:35 +00:00
uint32_t argumentCount = 0;
2021-05-16 07:42:37 +00:00
LLVMValueRef args
[functionCallExpression->functionCallExpression.argumentSequence
->functionArgumentSequence.count +
1];
2021-04-23 00:19:35 +00:00
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
*/
2021-05-16 07:42:37 +00:00
if (functionCallExpression->functionCallExpression.identifier->syntaxKind ==
AccessExpression)
2021-04-23 00:19:35 +00:00
{
2021-04-23 05:37:23 +00:00
LLVMTypeRef typeReference = FindStructType(
2021-05-16 07:42:37 +00:00
functionCallExpression->functionCallExpression.identifier
->accessExpression.accessee->identifier.name);
2021-04-23 05:37:23 +00:00
if (typeReference != NULL)
{
function = LookupFunctionByType(
typeReference,
2021-06-03 00:26:26 +00:00
functionCallExpression,
2021-04-23 05:37:23 +00:00
&functionReturnType,
2021-05-16 07:42:37 +00:00
&isStatic);
2021-04-23 05:37:23 +00:00
}
else
{
2021-05-16 07:42:37 +00:00
structInstance = FindVariablePointer(
functionCallExpression->functionCallExpression.identifier
->accessExpression.accessee->identifier.name);
function = LookupFunctionByInstance(
structInstance,
2021-06-03 00:26:26 +00:00
functionCallExpression,
2021-05-16 07:42:37 +00:00
&functionReturnType,
&isStatic);
2021-04-23 05:37:23 +00:00
}
2021-04-23 00:19:35 +00:00
}
else
{
fprintf(stderr, "Failed to find function!\n");
return NULL;
}
2021-04-20 17:47:40 +00:00
2021-04-23 00:19:35 +00:00
if (!isStatic)
2021-04-20 17:47:40 +00:00
{
2021-04-23 00:19:35 +00:00
args[argumentCount] = structInstance;
argumentCount += 1;
2021-04-20 17:47:40 +00:00
}
2021-05-16 07:42:37 +00:00
for (i = 0; i < functionCallExpression->functionCallExpression
.argumentSequence->functionArgumentSequence.count;
i += 1)
2021-04-23 00:19:35 +00:00
{
2021-05-16 07:42:37 +00:00
args[argumentCount] = CompileExpression(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
2021-05-16 07:42:37 +00:00
builder,
functionCallExpression->functionCallExpression.argumentSequence
->functionArgumentSequence.sequence[i]);
2021-04-23 00:19:35 +00:00
argumentCount += 1;
}
if (LLVMGetTypeKind(functionReturnType) != LLVMVoidTypeKind)
{
returnName = "callReturn";
}
return LLVMBuildCall(builder, function, args, argumentCount, returnName);
2021-04-22 04:29:38 +00:00
}
2021-06-02 19:33:01 +00:00
static LLVMValueRef CompileSystemCallExpression(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
2021-06-02 19:33:01 +00:00
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(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
2021-06-02 19:33:01 +00:00
builder,
systemCallExpression->systemCall.argumentSequence
->functionArgumentSequence.sequence[i]);
}
2021-06-03 00:26:26 +00:00
SystemFunction *systemFunction = LookupSystemFunction(systemCallExpression);
2021-06-02 19:33:01 +00:00
if (systemFunction == NULL)
{
2021-06-03 00:26:26 +00:00
/* 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;
}
2021-06-02 19:33:01 +00:00
}
if (LLVMGetTypeKind(LLVMGetReturnType(systemFunction->functionType)) !=
LLVMVoidTypeKind)
{
returnName = "callReturn";
}
return LLVMBuildCall(
builder,
systemFunction->function,
args,
argumentCount,
returnName);
}
2021-04-22 04:29:38 +00:00
static LLVMValueRef CompileAccessExpressionForStore(
LLVMBuilderRef builder,
2021-05-16 07:42:37 +00:00
Node *accessExpression)
{
LLVMValueRef accesseeValue = FindVariablePointer(
accessExpression->accessExpression.accessee->identifier.name);
return FindStructFieldPointer(
builder,
accesseeValue,
accessExpression->accessExpression.accessor->identifier.name);
2021-04-22 04:29:38 +00:00
}
static LLVMValueRef CompileAccessExpression(
LLVMBuilderRef builder,
2021-05-16 07:42:37 +00:00
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);
2021-04-20 17:47:40 +00:00
}
2021-04-28 19:49:45 +00:00
static LLVMValueRef CompileAllocExpression(
LLVMBuilderRef builder,
2021-05-16 07:42:37 +00:00
Node *allocExpression)
{
LLVMTypeRef type = ResolveType(allocExpression->typeTag);
2021-04-28 19:49:45 +00:00
return LLVMBuildMalloc(builder, type, "allocation");
}
static LLVMValueRef CompileExpression(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
LLVMBuilderRef builder,
Node *expression)
2021-05-16 07:42:37 +00:00
{
2021-04-20 01:18:45 +00:00
switch (expression->syntaxKind)
{
2021-05-16 07:42:37 +00:00
case AccessExpression:
return CompileAccessExpression(builder, expression);
2021-04-28 19:49:45 +00:00
2021-05-16 07:42:37 +00:00
case AllocExpression:
return CompileAllocExpression(builder, expression);
2021-04-20 01:18:45 +00:00
2021-05-16 07:42:37 +00:00
case BinaryExpression:
2021-06-03 21:40:14 +00:00
return CompileBinaryExpression(
structTypeDeclaration,
builder,
expression);
2021-04-20 17:47:40 +00:00
2021-05-16 07:42:37 +00:00
case FunctionCallExpression:
2021-06-03 21:40:14 +00:00
return CompileFunctionCallExpression(
structTypeDeclaration,
builder,
expression);
2021-04-20 01:18:45 +00:00
2021-05-16 07:42:37 +00:00
case Identifier:
return FindVariableValue(builder, expression->identifier.name);
2021-04-30 19:17:44 +00:00
2021-05-16 07:42:37 +00:00
case Number:
return CompileNumber(expression);
2021-04-30 19:17:44 +00:00
2021-05-16 07:42:37 +00:00
case StringLiteral:
return CompileString(builder, expression);
2021-06-02 19:33:01 +00:00
case SystemCall:
2021-06-03 21:40:14 +00:00
return CompileSystemCallExpression(
structTypeDeclaration,
builder,
expression);
2021-04-20 01:18:45 +00:00
}
2021-04-21 02:00:18 +00:00
fprintf(stderr, "Unknown expression kind!\n");
2021-04-20 01:18:45 +00:00
return NULL;
}
2021-05-16 07:42:37 +00:00
static LLVMBasicBlockRef CompileReturn(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
2021-05-16 07:42:37 +00:00
LLVMBuilderRef builder,
LLVMValueRef function,
Node *returnStatemement)
2021-04-20 01:18:45 +00:00
{
2021-05-16 07:42:37 +00:00
LLVMValueRef expression = CompileExpression(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
2021-05-16 07:42:37 +00:00
builder,
returnStatemement->returnStatement.expression);
2021-04-22 04:29:38 +00:00
LLVMBuildRet(builder, expression);
2021-04-30 06:49:35 +00:00
return LLVMGetLastBasicBlock(function);
2021-04-21 02:00:18 +00:00
}
2021-05-16 07:42:37 +00:00
static LLVMBasicBlockRef CompileReturnVoid(
LLVMBuilderRef builder,
LLVMValueRef function)
2021-04-21 02:00:18 +00:00
{
LLVMBuildRetVoid(builder);
2021-04-30 06:49:35 +00:00
return LLVMGetLastBasicBlock(function);
2021-04-21 02:00:18 +00:00
}
/* FIXME: path for reference types */
2021-05-16 07:42:37 +00:00
static LLVMValueRef CompileFunctionVariableDeclaration(
LLVMBuilderRef builder,
LLVMValueRef function,
Node *variableDeclaration)
{
LLVMValueRef variable;
2021-05-16 07:42:37 +00:00
char *variableName =
variableDeclaration->declaration.identifier->identifier.name;
char *ptrName = strdup(variableName);
strcat(ptrName, "_ptr");
2021-05-16 07:42:37 +00:00
variable = LLVMBuildAlloca(
builder,
ResolveType(variableDeclaration->declaration.identifier->typeTag),
2021-05-16 07:42:37 +00:00
ptrName);
free(ptrName);
AddLocalVariable(scope, variable, NULL, variableName);
return variable;
}
2021-05-16 07:42:37 +00:00
static LLVMBasicBlockRef CompileAssignment(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
2021-05-16 07:42:37 +00:00
LLVMBuilderRef builder,
LLVMValueRef function,
Node *assignmentStatement)
2021-04-21 02:00:18 +00:00
{
2021-05-16 07:42:37 +00:00
LLVMValueRef result = CompileExpression(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
2021-05-16 07:42:37 +00:00
builder,
assignmentStatement->assignmentStatement.right);
2021-06-03 21:40:14 +00:00
2021-04-22 04:29:38 +00:00
LLVMValueRef identifier;
2021-06-03 21:40:14 +00:00
2021-05-16 07:42:37 +00:00
if (assignmentStatement->assignmentStatement.left->syntaxKind ==
AccessExpression)
2021-04-22 04:29:38 +00:00
{
2021-05-16 07:42:37 +00:00
identifier = CompileAccessExpressionForStore(
builder,
assignmentStatement->assignmentStatement.left);
2021-04-22 04:29:38 +00:00
}
2021-05-16 07:42:37 +00:00
else if (
assignmentStatement->assignmentStatement.left->syntaxKind == Identifier)
2021-04-22 04:29:38 +00:00
{
2021-05-16 07:42:37 +00:00
identifier = FindVariablePointer(
assignmentStatement->assignmentStatement.left->identifier.name);
2021-04-22 04:29:38 +00:00
}
2021-05-16 07:42:37 +00:00
else if (
assignmentStatement->assignmentStatement.left->syntaxKind ==
Declaration)
{
2021-05-16 07:42:37 +00:00
identifier = CompileFunctionVariableDeclaration(
builder,
function,
assignmentStatement->assignmentStatement.left);
}
2021-04-22 05:26:34 +00:00
else
{
printf("Identifier not found!");
2021-04-30 06:49:35 +00:00
return LLVMGetLastBasicBlock(function);
2021-04-22 05:26:34 +00:00
}
2021-04-21 02:00:18 +00:00
2021-04-22 04:29:38 +00:00
LLVMBuildStore(builder, result, identifier);
2021-04-30 06:49:35 +00:00
return LLVMGetLastBasicBlock(function);
2021-04-20 01:18:45 +00:00
}
2021-05-16 07:42:37 +00:00
static LLVMBasicBlockRef CompileIfStatement(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
2021-05-16 07:42:37 +00:00
LLVMBuilderRef builder,
LLVMValueRef function,
Node *ifStatement)
2021-04-29 04:25:25 +00:00
{
uint32_t i;
2021-06-03 21:40:14 +00:00
LLVMValueRef conditional = CompileExpression(
structTypeDeclaration,
builder,
ifStatement->ifStatement.expression);
2021-04-29 04:25:25 +00:00
LLVMBasicBlockRef block = LLVMAppendBasicBlock(function, "ifBlock");
LLVMBasicBlockRef afterCond = LLVMAppendBasicBlock(function, "afterCond");
LLVMBuildCondBr(builder, conditional, block, afterCond);
LLVMPositionBuilderAtEnd(builder, block);
2021-05-16 07:42:37 +00:00
for (i = 0;
i <
ifStatement->ifStatement.statementSequence->statementSequence.count;
i += 1)
2021-04-29 04:25:25 +00:00
{
2021-05-16 07:42:37 +00:00
CompileStatement(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
2021-05-16 07:42:37 +00:00
builder,
function,
ifStatement->ifStatement.statementSequence->statementSequence
.sequence[i]);
2021-04-29 04:25:25 +00:00
}
2021-04-29 20:59:00 +00:00
LLVMBuildBr(builder, afterCond);
LLVMPositionBuilderAtEnd(builder, afterCond);
2021-04-30 06:49:35 +00:00
return afterCond;
2021-04-29 20:59:00 +00:00
}
2021-05-16 07:42:37 +00:00
static LLVMBasicBlockRef CompileIfElseStatement(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
2021-05-16 07:42:37 +00:00
LLVMBuilderRef builder,
LLVMValueRef function,
Node *ifElseStatement)
2021-04-29 20:59:00 +00:00
{
uint32_t i;
2021-05-16 07:42:37 +00:00
LLVMValueRef conditional = CompileExpression(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
2021-05-16 07:42:37 +00:00
builder,
ifElseStatement->ifElseStatement.ifStatement->ifStatement.expression);
2021-04-29 20:59:00 +00:00
LLVMBasicBlockRef ifBlock = LLVMAppendBasicBlock(function, "ifBlock");
LLVMBasicBlockRef elseBlock = LLVMAppendBasicBlock(function, "elseBlock");
LLVMBasicBlockRef afterCond = LLVMAppendBasicBlock(function, "afterCond");
LLVMBuildCondBr(builder, conditional, ifBlock, elseBlock);
LLVMPositionBuilderAtEnd(builder, ifBlock);
2021-05-16 07:42:37 +00:00
for (i = 0; i < ifElseStatement->ifElseStatement.ifStatement->ifStatement
.statementSequence->statementSequence.count;
i += 1)
2021-04-29 20:59:00 +00:00
{
2021-05-16 07:42:37 +00:00
CompileStatement(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
2021-05-16 07:42:37 +00:00
builder,
function,
ifElseStatement->ifElseStatement.ifStatement->ifStatement
.statementSequence->statementSequence.sequence[i]);
2021-04-29 20:59:00 +00:00
}
LLVMBuildBr(builder, afterCond);
LLVMPositionBuilderAtEnd(builder, elseBlock);
2021-05-16 07:42:37 +00:00
if (ifElseStatement->ifElseStatement.elseStatement->syntaxKind ==
StatementSequence)
2021-04-29 22:26:30 +00:00
{
2021-05-16 07:42:37 +00:00
for (i = 0; i < ifElseStatement->ifElseStatement.elseStatement
->statementSequence.count;
i += 1)
2021-04-29 22:26:30 +00:00
{
2021-05-16 07:42:37 +00:00
CompileStatement(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
2021-05-16 07:42:37 +00:00
builder,
function,
ifElseStatement->ifElseStatement.elseStatement
->statementSequence.sequence[i]);
2021-04-29 22:26:30 +00:00
}
}
else
2021-04-29 20:59:00 +00:00
{
2021-05-16 07:42:37 +00:00
CompileStatement(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
2021-05-16 07:42:37 +00:00
builder,
function,
ifElseStatement->ifElseStatement.elseStatement);
2021-04-29 20:59:00 +00:00
}
LLVMBuildBr(builder, afterCond);
2021-04-29 04:25:25 +00:00
LLVMPositionBuilderAtEnd(builder, afterCond);
2021-04-30 06:49:35 +00:00
return afterCond;
2021-04-29 04:25:25 +00:00
}
2021-05-16 07:42:37 +00:00
static LLVMBasicBlockRef CompileForLoopStatement(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
2021-05-16 07:42:37 +00:00
LLVMBuilderRef builder,
LLVMValueRef function,
Node *forLoopStatement)
2021-04-30 06:49:35 +00:00
{
uint32_t i;
LLVMBasicBlockRef entryBlock = LLVMAppendBasicBlock(function, "loopEntry");
LLVMBasicBlockRef checkBlock = LLVMAppendBasicBlock(function, "loopCheck");
LLVMBasicBlockRef bodyBlock = LLVMAppendBasicBlock(function, "loopBody");
2021-05-16 07:42:37 +00:00
LLVMBasicBlockRef afterLoopBlock =
LLVMAppendBasicBlock(function, "afterLoop");
char *iteratorVariableName = forLoopStatement->forLoop.declaration
->declaration.identifier->identifier.name;
LLVMTypeRef iteratorVariableType = ResolveType(
forLoopStatement->forLoop.declaration->declaration.identifier->typeTag);
2021-04-30 06:49:35 +00:00
PushScopeFrame(scope);
LLVMBuildBr(builder, entryBlock);
LLVMPositionBuilderAtEnd(builder, entryBlock);
LLVMBuildBr(builder, checkBlock);
LLVMPositionBuilderAtEnd(builder, checkBlock);
2021-05-16 07:42:37 +00:00
LLVMValueRef iteratorValue =
LLVMBuildPhi(builder, iteratorVariableType, iteratorVariableName);
2021-04-30 06:49:35 +00:00
AddLocalVariable(scope, NULL, iteratorValue, iteratorVariableName);
LLVMPositionBuilderAtEnd(builder, bodyBlock);
2021-04-30 19:17:44 +00:00
LLVMValueRef nextValue = LLVMBuildAdd(
builder,
iteratorValue,
2021-05-16 07:42:37 +00:00
LLVMConstInt(
iteratorVariableType,
1,
0), /* FIXME: add custom increment value */
"next");
2021-04-30 06:49:35 +00:00
LLVMPositionBuilderAtEnd(builder, checkBlock);
2021-05-16 07:42:37 +00:00
LLVMValueRef iteratorEndValue =
CompileNumber(forLoopStatement->forLoop.endNumber);
LLVMValueRef comparison = LLVMBuildICmp(
builder,
LLVMIntULE,
iteratorValue,
iteratorEndValue,
"iteratorCompare");
2021-04-30 06:49:35 +00:00
LLVMBuildCondBr(builder, comparison, bodyBlock, afterLoopBlock);
LLVMPositionBuilderAtEnd(builder, bodyBlock);
LLVMBasicBlockRef lastBlock;
2021-05-16 07:42:37 +00:00
for (i = 0;
i <
forLoopStatement->forLoop.statementSequence->statementSequence.count;
i += 1)
2021-04-30 06:49:35 +00:00
{
2021-05-16 07:42:37 +00:00
lastBlock = CompileStatement(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
2021-05-16 07:42:37 +00:00
builder,
function,
forLoopStatement->forLoop.statementSequence->statementSequence
.sequence[i]);
2021-04-30 06:49:35 +00:00
}
LLVMBuildBr(builder, checkBlock);
LLVMPositionBuilderBefore(builder, LLVMGetFirstInstruction(checkBlock));
LLVMValueRef incomingValues[2];
incomingValues[0] = CompileNumber(forLoopStatement->forLoop.startNumber);
2021-04-30 06:49:35 +00:00
incomingValues[1] = nextValue;
LLVMBasicBlockRef incomingBlocks[2];
incomingBlocks[0] = entryBlock;
incomingBlocks[1] = lastBlock;
LLVMAddIncoming(iteratorValue, incomingValues, incomingBlocks, 2);
LLVMPositionBuilderAtEnd(builder, afterLoopBlock);
PopScopeFrame(scope);
return afterLoopBlock;
}
2021-05-16 07:42:37 +00:00
static LLVMBasicBlockRef CompileStatement(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
2021-05-16 07:42:37 +00:00
LLVMBuilderRef builder,
LLVMValueRef function,
Node *statement)
2021-04-20 01:18:45 +00:00
{
switch (statement->syntaxKind)
{
2021-05-16 07:42:37 +00:00
case Assignment:
2021-06-03 21:40:14 +00:00
return CompileAssignment(
structTypeDeclaration,
builder,
function,
statement);
2021-04-30 06:49:35 +00:00
2021-05-16 07:42:37 +00:00
case Declaration:
CompileFunctionVariableDeclaration(builder, function, statement);
return LLVMGetLastBasicBlock(function);
2021-04-30 06:49:35 +00:00
2021-05-16 07:42:37 +00:00
case ForLoop:
2021-06-03 21:40:14 +00:00
return CompileForLoopStatement(
structTypeDeclaration,
builder,
function,
statement);
2021-04-23 00:19:35 +00:00
2021-05-16 07:42:37 +00:00
case FunctionCallExpression:
2021-06-03 21:40:14 +00:00
CompileFunctionCallExpression(
structTypeDeclaration,
builder,
statement);
2021-05-16 07:42:37 +00:00
return LLVMGetLastBasicBlock(function);
2021-04-21 06:51:26 +00:00
2021-05-16 07:42:37 +00:00
case IfStatement:
2021-06-03 21:40:14 +00:00
return CompileIfStatement(
structTypeDeclaration,
builder,
function,
statement);
2021-04-29 04:25:25 +00:00
2021-05-16 07:42:37 +00:00
case IfElseStatement:
2021-06-03 21:40:14 +00:00
return CompileIfElseStatement(
structTypeDeclaration,
builder,
function,
statement);
2021-04-29 20:59:00 +00:00
2021-05-16 07:42:37 +00:00
case Return:
2021-06-03 21:40:14 +00:00
return CompileReturn(
structTypeDeclaration,
builder,
function,
statement);
2021-04-21 02:00:18 +00:00
2021-05-16 07:42:37 +00:00
case ReturnVoid:
return CompileReturnVoid(builder, function);
2021-06-02 19:33:01 +00:00
case SystemCall:
2021-06-03 21:40:14 +00:00
CompileSystemCallExpression(structTypeDeclaration, builder, statement);
2021-06-02 19:33:01 +00:00
return LLVMGetLastBasicBlock(function);
2021-04-20 01:18:45 +00:00
}
2021-04-21 02:00:18 +00:00
fprintf(stderr, "Unknown statement kind!\n");
2021-04-30 06:49:35 +00:00
return NULL;
2021-04-20 01:18:45 +00:00
}
2021-04-21 02:00:18 +00:00
static void CompileFunction(
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration,
2021-05-16 07:42:37 +00:00
Node *functionDeclaration)
{
2021-04-18 22:45:06 +00:00
uint32_t i;
2021-04-21 02:00:18 +00:00
uint8_t hasReturn = 0;
2021-04-22 07:35:42 +00:00
uint8_t isStatic = 0;
2021-05-16 07:42:37 +00:00
Node *functionSignature =
functionDeclaration->functionDeclaration.functionSignature;
Node *functionBody = functionDeclaration->functionDeclaration.functionBody;
2021-05-16 07:42:37 +00:00
uint32_t argumentCount = functionSignature->functionSignature.arguments
->functionSignatureArguments.count;
2021-04-22 07:35:42 +00:00
LLVMTypeRef paramTypes[argumentCount + 1];
uint32_t paramIndex = 0;
2021-04-21 02:00:18 +00:00
2021-05-16 07:42:37 +00:00
if (functionSignature->functionSignature.modifiers->functionModifiers
.count > 0)
2021-04-22 07:35:42 +00:00
{
2021-05-16 07:42:37 +00:00
for (i = 0; i < functionSignature->functionSignature.modifiers
->functionModifiers.count;
i += 1)
2021-04-22 07:35:42 +00:00
{
2021-05-16 07:42:37 +00:00
if (functionSignature->functionSignature.modifiers
->functionModifiers.sequence[i]
->syntaxKind == StaticModifier)
2021-04-22 07:35:42 +00:00
{
isStatic = 1;
break;
}
}
}
2021-04-22 04:29:38 +00:00
2021-06-03 21:40:14 +00:00
char *functionName = strdup(structTypeDeclaration->name);
uint32_t nameLen = strlen(functionName);
nameLen +=
2 +
strlen(
functionSignature->functionSignature.identifier->identifier.name);
functionName = realloc(functionName, sizeof(char) * nameLen);
2021-04-22 17:27:39 +00:00
strcat(functionName, "_");
2021-05-16 07:42:37 +00:00
strcat(
functionName,
functionSignature->functionSignature.identifier->identifier.name);
2021-04-20 01:18:45 +00:00
if (functionSignature->functionSignature.genericDeclarations
->genericDeclarations.count == 0)
{
PushScopeFrame(scope);
2021-04-23 00:19:35 +00:00
if (!isStatic)
{
2021-06-03 21:40:14 +00:00
paramTypes[paramIndex] = structTypeDeclaration->structPointerType;
paramIndex += 1;
}
2021-04-20 01:18:45 +00:00
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;
}
2021-04-22 04:29:38 +00:00
LLVMTypeRef returnType = ResolveType(
functionSignature->functionSignature.identifier->typeTag);
LLVMTypeRef functionType =
LLVMFunctionType(returnType, paramTypes, paramIndex, 0);
2021-04-21 02:00:18 +00:00
2021-06-03 21:40:14 +00:00
LLVMValueRef function = LLVMAddFunction(
structTypeDeclaration->module,
functionName,
functionType);
DeclareStructFunction(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
2021-05-16 07:42:37 +00:00
function,
returnType,
isStatic,
functionSignature->functionSignature.identifier->identifier.name);
2021-04-20 17:47:40 +00:00
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry");
LLVMBuilderRef builder = LLVMCreateBuilder();
LLVMPositionBuilderAtEnd(builder, entry);
2021-04-30 06:49:35 +00:00
if (!isStatic)
{
LLVMValueRef wStructPointer = LLVMGetParam(function, 0);
2021-06-03 21:40:14 +00:00
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(
2021-06-03 21:40:14 +00:00
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);
2021-04-21 02:00:18 +00:00
}
else
2021-04-21 02:00:18 +00:00
{
DeclareGenericStructFunction(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
functionDeclaration,
isStatic,
functionSignature->functionSignature.identifier->identifier.name);
2021-04-21 02:00:18 +00:00
}
2021-04-22 04:29:38 +00:00
free(functionName);
2021-04-21 02:00:18 +00:00
}
2021-05-16 07:42:37 +00:00
static void CompileStruct(
LLVMModuleRef module,
LLVMContextRef context,
Node *node)
2021-04-21 02:00:18 +00:00
{
uint32_t i;
uint32_t fieldCount = 0;
2021-05-16 07:42:37 +00:00
uint32_t declarationCount =
node->structDeclaration.declarationSequence->declarationSequence.count;
2021-04-21 02:00:18 +00:00
uint8_t packed = 1;
LLVMTypeRef types[declarationCount];
Node *currentDeclarationNode;
char *structName = node->structDeclaration.identifier->identifier.name;
2021-04-21 02:00:18 +00:00
2021-04-22 04:29:38 +00:00
PushScopeFrame(scope);
2021-06-03 00:26:26 +00:00
if (node->structDeclaration.genericDeclarations->genericDeclarations
.count == 0)
2021-04-21 02:00:18 +00:00
{
2021-06-03 00:26:26 +00:00
LLVMTypeRef wStructType = LLVMStructCreateNamed(context, structName);
LLVMTypeRef wStructPointerType = LLVMPointerType(
wStructType,
0); /* FIXME: is this address space correct? */
2021-04-21 02:00:18 +00:00
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration = AddStructDeclaration(
module,
wStructType,
wStructPointerType,
structName);
2021-06-03 00:26:26 +00:00
/* first, build the structure definition */
for (i = 0; i < declarationCount; i += 1)
2021-04-21 02:00:18 +00:00
{
2021-06-03 00:26:26 +00:00
currentDeclarationNode =
node->structDeclaration.declarationSequence->declarationSequence
.sequence[i];
2021-04-21 02:00:18 +00:00
2021-06-03 00:26:26 +00:00
switch (currentDeclarationNode->syntaxKind)
{
2021-06-03 21:40:14 +00:00
case Declaration: /* FIXME: this is badly named */
2021-06-03 00:26:26 +00:00
types[fieldCount] = ResolveType(
currentDeclarationNode->declaration.identifier->typeTag);
2021-06-03 21:40:14 +00:00
AddFieldToStructDeclaration(
structTypeDeclaration,
currentDeclarationNode->declaration.identifier->identifier
.name);
2021-06-03 00:26:26 +00:00
fieldCount += 1;
break;
}
}
2021-04-21 02:00:18 +00:00
2021-06-03 00:26:26 +00:00
LLVMStructSetBody(wStructType, types, fieldCount, packed);
2021-04-21 02:00:18 +00:00
2021-06-03 00:26:26 +00:00
/* now we can wire up the functions */
for (i = 0; i < declarationCount; i += 1)
2021-04-21 02:00:18 +00:00
{
2021-06-03 00:26:26 +00:00
currentDeclarationNode =
node->structDeclaration.declarationSequence->declarationSequence
.sequence[i];
switch (currentDeclarationNode->syntaxKind)
{
case FunctionDeclaration:
2021-06-03 21:40:14 +00:00
CompileFunction(structTypeDeclaration, currentDeclarationNode);
2021-06-03 00:26:26 +00:00
break;
}
2021-04-21 02:00:18 +00:00
}
}
2021-06-03 00:26:26 +00:00
else
{
2021-06-03 21:40:14 +00:00
AddGenericStructDeclaration(module, node);
2021-06-03 00:26:26 +00:00
}
2021-04-21 06:51:26 +00:00
2021-04-22 04:29:38 +00:00
PopScopeFrame(scope);
2021-04-18 22:45:06 +00:00
}
2021-05-16 07:42:37 +00:00
static void Compile(
LLVMModuleRef module,
LLVMContextRef context,
Node *declarationSequenceNode)
2021-04-18 22:45:06 +00:00
{
uint32_t i;
for (i = 0; i < declarationSequenceNode->declarationSequence.count; i += 1)
2021-04-18 22:45:06 +00:00
{
2021-05-16 07:42:37 +00:00
if (declarationSequenceNode->declarationSequence.sequence[i]
->syntaxKind == StructDeclaration)
2021-04-23 00:19:35 +00:00
{
2021-05-16 07:42:37 +00:00
CompileStruct(
module,
context,
declarationSequenceNode->declarationSequence.sequence[i]);
2021-04-23 00:19:35 +00:00
}
else
{
2021-05-16 07:42:37 +00:00
fprintf(
stderr,
"top level declarations that are not structs are "
"forbidden!\n");
2021-04-23 00:19:35 +00:00
}
2021-04-18 22:45:06 +00:00
}
}
2021-04-18 22:29:54 +00:00
2021-04-30 19:17:44 +00:00
/* TODO: move this to some kind of standard library file? */
2021-05-16 07:42:37 +00:00
static void RegisterLibraryFunctions(
LLVMModuleRef module,
LLVMContextRef context)
2021-04-30 19:17:44 +00:00
{
LLVMTypeRef structType = LLVMStructCreateNamed(context, "Console");
LLVMTypeRef structPointerType = LLVMPointerType(structType, 0);
2021-06-03 21:40:14 +00:00
StructTypeDeclaration *structTypeDeclaration =
AddStructDeclaration(module, structType, structPointerType, "Console");
2021-04-30 19:17:44 +00:00
LLVMTypeRef printfArg = LLVMPointerType(LLVMInt8Type(), 0);
2021-05-16 07:42:37 +00:00
LLVMTypeRef printfFunctionType =
LLVMFunctionType(LLVMInt32Type(), &printfArg, 1, 1);
LLVMValueRef printfFunction =
LLVMAddFunction(module, "printf", printfFunctionType);
2021-04-30 19:17:44 +00:00
LLVMSetLinkage(printfFunction, LLVMExternalLinkage);
2021-05-16 07:42:37 +00:00
LLVMTypeRef printLineFunctionType =
LLVMFunctionType(LLVMInt32Type(), &printfArg, 1, 1);
LLVMValueRef printLineFunction =
LLVMAddFunction(module, "printLine", printLineFunctionType);
2021-04-30 19:17:44 +00:00
LLVMBuilderRef builder = LLVMCreateBuilder();
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(printLineFunction, "entry");
LLVMPositionBuilderAtEnd(builder, entry);
LLVMValueRef newLine = LLVMBuildGlobalStringPtr(builder, "\n", "newline");
LLVMValueRef printParams[LLVMCountParams(printLineFunction)];
LLVMGetParams(printLineFunction, printParams);
2021-05-16 07:42:37 +00:00
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(
2021-06-03 21:40:14 +00:00
structTypeDeclaration,
2021-05-16 07:42:37 +00:00
printLineFunction,
LLVMInt8Type(),
1,
"PrintLine");
2021-06-02 19:33:01 +00:00
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);
2021-04-30 19:17:44 +00:00
}
int Codegen(Node *node, uint32_t optimizationLevel)
2021-04-18 22:29:54 +00:00
{
2021-04-22 04:29:38 +00:00
scope = CreateScope();
2021-04-20 01:18:45 +00:00
2021-04-23 05:37:23 +00:00
structTypeDeclarations = NULL;
structTypeDeclarationCount = 0;
2021-06-02 19:33:01 +00:00
2021-06-03 00:26:26 +00:00
genericStructTypeDeclarations = NULL;
genericStructTypeDeclarationCount = 0;
2021-06-02 19:33:01 +00:00
systemFunctions = NULL;
systemFunctionCount = 0;
2021-04-21 06:51:26 +00:00
2021-04-18 22:45:06 +00:00
LLVMModuleRef module = LLVMModuleCreateWithName("my_module");
2021-04-21 02:00:18 +00:00
LLVMContextRef context = LLVMGetGlobalContext();
2021-04-18 22:45:06 +00:00
2021-04-30 19:17:44 +00:00
RegisterLibraryFunctions(module, context);
2021-04-28 23:01:48 +00:00
Compile(module, context, node);
2021-04-18 22:29:54 +00:00
2021-04-22 17:27:39 +00:00
/* add main call */
LLVMBuilderRef builder = LLVMCreateBuilder();
2021-05-16 07:42:37 +00:00
LLVMTypeRef mainFunctionType =
LLVMFunctionType(LLVMInt64Type(), NULL, 0, 0);
LLVMValueRef mainFunction =
LLVMAddFunction(module, "main", mainFunctionType);
2021-04-22 17:27:39 +00:00
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(mainFunction, "entry");
LLVMPositionBuilderAtEnd(builder, entry);
2021-05-16 07:42:37 +00:00
LLVMValueRef wraithMainFunction =
LLVMGetNamedFunction(module, "Program_Main");
2021-04-22 17:27:39 +00:00
2021-05-16 07:42:37 +00:00
LLVMValueRef mainResult =
LLVMBuildCall(builder, wraithMainFunction, NULL, 0, "result");
2021-04-22 17:27:39 +00:00
LLVMBuildRet(builder, mainResult);
LLVMDisposeBuilder(builder);
/* verify */
2021-04-20 01:18:45 +00:00
char *error = NULL;
2021-04-28 22:21:51 +00:00
if (LLVMVerifyModule(module, LLVMAbortProcessAction, &error) != 0)
{
fprintf(stderr, "%s\n", error);
LLVMDisposeMessage(error);
return EXIT_FAILURE;
}
2021-04-22 07:35:42 +00:00
2021-04-22 17:27:39 +00:00
/* prepare to emit assembly */
LLVMInitializeNativeTarget();
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargets();
LLVMInitializeAllTargetMCs();
LLVMInitializeAllAsmParsers();
LLVMInitializeAllAsmPrinters();
2021-04-22 07:35:42 +00:00
LLVMSetTarget(module, LLVM_DEFAULT_TARGET_TRIPLE);
2021-04-22 17:27:39 +00:00
LLVMTargetRef target;
2021-05-16 07:42:37 +00:00
if (LLVMGetTargetFromTriple(LLVM_DEFAULT_TARGET_TRIPLE, &target, &error) !=
0)
2021-04-22 17:27:39 +00:00
{
fprintf(stderr, "Failed to get target!\n");
fprintf(stderr, "%s\n", error);
LLVMDisposeMessage(error);
2021-04-28 22:21:51 +00:00
return EXIT_FAILURE;
2021-04-22 17:27:39 +00:00
}
2021-04-20 01:18:45 +00:00
2021-04-22 05:48:55 +00:00
LLVMPassManagerRef passManager = LLVMCreatePassManager();
2021-04-22 17:27:39 +00:00
2021-05-16 07:42:37 +00:00
LLVMPassManagerBuilderRef passManagerBuilder =
LLVMPassManagerBuilderCreate();
2021-04-28 22:21:51 +00:00
LLVMPassManagerBuilderSetOptLevel(passManagerBuilder, optimizationLevel);
2021-05-16 07:42:37 +00:00
LLVMPassManagerBuilderPopulateModulePassManager(
passManagerBuilder,
passManager);
2021-04-22 05:48:55 +00:00
LLVMRunPassManager(passManager, module);
2021-05-16 07:42:37 +00:00
if (LLVMWriteBitcodeToFile(module, "test.bc") != 0)
{
2021-04-20 01:18:45 +00:00
fprintf(stderr, "error writing bitcode to file\n");
2021-04-28 22:21:51 +00:00
return EXIT_FAILURE;
2021-04-20 01:18:45 +00:00
}
2021-04-22 17:27:39 +00:00
char *cpu = "generic";
char *features = "";
LLVMTargetMachineRef targetMachine = LLVMCreateTargetMachine(
target,
LLVM_DEFAULT_TARGET_TRIPLE,
cpu,
features,
LLVMCodeGenLevelDefault,
LLVMRelocDefault,
2021-05-16 07:42:37 +00:00
LLVMCodeModelDefault);
if (LLVMTargetMachineEmitToFile(
targetMachine,
module,
"test.o",
LLVMObjectFile,
&error) != 0)
2021-04-22 17:27:39 +00:00
{
fprintf(stderr, "Failed to emit machine code!\n");
fprintf(stderr, "%s\n", error);
LLVMDisposeMessage(error);
2021-04-28 22:21:51 +00:00
return EXIT_FAILURE;
2021-04-22 17:27:39 +00:00
}
LLVMDisposeMessage(error);
LLVMDisposeTargetMachine(targetMachine);
2021-04-22 05:48:55 +00:00
LLVMPassManagerBuilderDispose(passManagerBuilder);
LLVMDisposePassManager(passManager);
LLVMDisposeModule(module);
2021-04-28 22:21:51 +00:00
return EXIT_SUCCESS;
}