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>
|
|
|
|
|
2021-04-18 22:29:54 +00:00
|
|
|
#include <llvm-c/Core.h>
|
2021-04-20 01:18:45 +00:00
|
|
|
#include <llvm-c/Analysis.h>
|
|
|
|
#include <llvm-c/BitWriter.h>
|
2021-04-22 07:35:42 +00:00
|
|
|
#include <llvm-c/Object.h>
|
2021-04-22 05:48:55 +00:00
|
|
|
#include <llvm-c/Transforms/PassManagerBuilder.h>
|
|
|
|
#include <llvm-c/Transforms/InstCombine.h>
|
|
|
|
#include <llvm-c/Transforms/Scalar.h>
|
|
|
|
#include <llvm-c/Transforms/Utils.h>
|
2021-04-22 07:35:42 +00:00
|
|
|
#include <llvm-c/TargetMachine.h>
|
2021-04-22 17:27:39 +00:00
|
|
|
#include <llvm-c/Target.h>
|
2021-04-18 22:45:06 +00:00
|
|
|
|
|
|
|
#include "ast.h"
|
|
|
|
|
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 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;
|
|
|
|
} 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;
|
|
|
|
|
2021-04-23 05:37:23 +00:00
|
|
|
typedef struct StructTypeDeclaration
|
2021-04-21 02:00:18 +00:00
|
|
|
{
|
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;
|
2021-04-23 05:37:23 +00:00
|
|
|
} StructTypeDeclaration;
|
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
|
|
|
|
|
|
|
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->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;
|
|
|
|
scope->scopeStack = realloc(scope->scopeStack, sizeof(ScopeFrame) * (scope->scopeStackCount + 1));
|
|
|
|
scope->scopeStack[index].localVariableCount = 0;
|
|
|
|
scope->scopeStack[index].localVariables = NULL;
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
scope->scopeStackCount -= 1;
|
|
|
|
|
|
|
|
scope->scopeStack = realloc(scope->scopeStack, sizeof(ScopeFrame) * scope->scopeStackCount);
|
2021-04-21 02:00:18 +00:00
|
|
|
}
|
|
|
|
|
2021-04-30 06:49:35 +00:00
|
|
|
static void AddLocalVariable(
|
|
|
|
Scope *scope,
|
|
|
|
LLVMValueRef pointer, /* can be NULL */
|
|
|
|
LLVMValueRef value, /* can be NULL */
|
|
|
|
char *name
|
|
|
|
) {
|
2021-04-22 04:29:38 +00:00
|
|
|
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;
|
2021-04-30 06:49:35 +00:00
|
|
|
scopeFrame->localVariables[index].value = value;
|
2021-04-22 04:29:38 +00:00
|
|
|
|
|
|
|
scopeFrame->localVariableCount += 1;
|
|
|
|
}
|
2021-04-21 02:40:39 +00:00
|
|
|
|
2021-04-24 20:53:21 +00:00
|
|
|
static LLVMTypeRef WraithTypeToLLVMType(PrimitiveType type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case Int:
|
|
|
|
return LLVMInt64Type();
|
|
|
|
|
|
|
|
case UInt:
|
|
|
|
return LLVMInt64Type();
|
|
|
|
|
|
|
|
case Bool:
|
|
|
|
return LLVMInt1Type();
|
|
|
|
|
|
|
|
case Void:
|
|
|
|
return LLVMVoidType();
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "Unrecognized type!");
|
|
|
|
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-04-22 04:29:38 +00:00
|
|
|
static LLVMValueRef FindStructFieldPointer(LLVMBuilderRef builder, LLVMValueRef structPointer, char *name)
|
|
|
|
{
|
|
|
|
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-04-22 04:29:38 +00:00
|
|
|
ptrName
|
|
|
|
);
|
|
|
|
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
|
|
|
|
{
|
|
|
|
return LLVMBuildLoad(builder, scope->scopeStack[i].localVariables[j].pointer, name);
|
|
|
|
}
|
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-22 04:29:38 +00:00
|
|
|
static void AddStructDeclaration(
|
|
|
|
LLVMTypeRef wStructType,
|
2021-04-23 05:37:23 +00:00
|
|
|
LLVMTypeRef wStructPointerType,
|
|
|
|
char *name,
|
2021-04-22 04:29:38 +00:00
|
|
|
Node **fieldDeclarations,
|
|
|
|
uint32_t fieldDeclarationCount
|
|
|
|
) {
|
|
|
|
uint32_t i;
|
2021-04-23 05:37:23 +00:00
|
|
|
uint32_t index = structTypeDeclarationCount;
|
|
|
|
structTypeDeclarations = realloc(structTypeDeclarations, sizeof(StructTypeDeclaration) * (structTypeDeclarationCount + 1));
|
|
|
|
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;
|
2021-04-22 04:29:38 +00:00
|
|
|
|
|
|
|
for (i = 0; i < fieldDeclarationCount; i += 1)
|
|
|
|
{
|
2021-04-23 05:37:23 +00:00
|
|
|
structTypeDeclarations[index].fields = realloc(structTypeDeclarations[index].fields, sizeof(StructTypeField) * (structTypeDeclarations[index].fieldCount + 1));
|
2021-05-15 22:34:15 +00:00
|
|
|
structTypeDeclarations[index].fields[i].name = strdup(fieldDeclarations[i]->declaration.identifier->identifier.name);
|
2021-04-23 05:37:23 +00:00
|
|
|
structTypeDeclarations[index].fields[i].index = i;
|
|
|
|
structTypeDeclarations[index].fieldCount += 1;
|
2021-04-22 04:29:38 +00:00
|
|
|
}
|
|
|
|
|
2021-04-23 05:37:23 +00:00
|
|
|
structTypeDeclarationCount += 1;
|
2021-04-22 04:29:38 +00:00
|
|
|
}
|
|
|
|
|
2021-04-23 00:19:35 +00:00
|
|
|
static void DeclareStructFunction(
|
2021-04-23 05:37:23 +00:00
|
|
|
LLVMTypeRef wStructPointerType,
|
2021-04-23 00:19:35 +00:00
|
|
|
LLVMValueRef function,
|
|
|
|
LLVMTypeRef returnType,
|
|
|
|
uint8_t isStatic,
|
|
|
|
char *name
|
|
|
|
) {
|
|
|
|
uint32_t i, index;
|
|
|
|
|
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 == wStructPointerType)
|
2021-04-23 00:19:35 +00:00
|
|
|
{
|
2021-04-23 05:37:23 +00:00
|
|
|
index = structTypeDeclarations[i].functionCount;
|
|
|
|
structTypeDeclarations[i].functions = realloc(structTypeDeclarations[i].functions, sizeof(StructTypeFunction) * (structTypeDeclarations[i].functionCount + 1));
|
|
|
|
structTypeDeclarations[i].functions[index].name = strdup(name);
|
|
|
|
structTypeDeclarations[i].functions[index].function = function;
|
|
|
|
structTypeDeclarations[i].functions[index].returnType = returnType;
|
|
|
|
structTypeDeclarations[i].functions[index].isStatic = isStatic;
|
|
|
|
structTypeDeclarations[i].functionCount += 1;
|
2021-04-23 00:19:35 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-23 05:37:23 +00:00
|
|
|
fprintf(stderr, "Could not find struct type for function!\n");
|
2021-04-23 00:19:35 +00:00
|
|
|
}
|
|
|
|
|
2021-04-23 05:37:23 +00:00
|
|
|
static LLVMTypeRef LookupCustomType(char *name)
|
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < structTypeDeclarationCount; i += 1)
|
|
|
|
{
|
|
|
|
if (strcmp(structTypeDeclarations[i].name, name) == 0)
|
|
|
|
{
|
|
|
|
return structTypeDeclarations[i].structType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "Could not find struct type!\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-04-24 20:53:21 +00:00
|
|
|
static LLVMTypeRef ResolveType(Node* typeNode)
|
|
|
|
{
|
|
|
|
if (IsPrimitiveType(typeNode))
|
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
return WraithTypeToLLVMType(typeNode->type.typeNode->primitiveType.type);
|
2021-04-24 20:53:21 +00:00
|
|
|
}
|
2021-05-15 22:34:15 +00:00
|
|
|
else if (typeNode->type.typeNode->syntaxKind == CustomTypeNode)
|
2021-04-24 20:53:21 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
return LookupCustomType(typeNode->type.typeNode->customType.name);
|
2021-04-24 20:53:21 +00:00
|
|
|
}
|
2021-05-15 22:34:15 +00:00
|
|
|
else if (typeNode->type.typeNode->syntaxKind == ReferenceTypeNode)
|
2021-04-24 20:53:21 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
return LLVMPointerType(ResolveType(typeNode->type.typeNode->referenceType.type), 0);
|
2021-04-24 20:53:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Unknown type node!\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-23 05:37:23 +00:00
|
|
|
static LLVMValueRef LookupFunctionByType(
|
|
|
|
LLVMTypeRef structType,
|
|
|
|
char *name,
|
|
|
|
LLVMTypeRef *pReturnType,
|
|
|
|
uint8_t *pStatic
|
|
|
|
) {
|
|
|
|
uint32_t i, j;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "Could not find struct function!\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static LLVMValueRef LookupFunctionByPointerType(
|
|
|
|
LLVMTypeRef structPointerType,
|
2021-04-23 00:19:35 +00:00
|
|
|
char *name,
|
|
|
|
LLVMTypeRef *pReturnType,
|
|
|
|
uint8_t *pStatic
|
|
|
|
) {
|
|
|
|
uint32_t i, j;
|
|
|
|
|
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-04-23 05:37:23 +00:00
|
|
|
if (strcmp(structTypeDeclarations[i].functions[j].name, name) == 0)
|
2021-04-23 00:19:35 +00:00
|
|
|
{
|
2021-04-23 05:37:23 +00:00
|
|
|
*pReturnType = structTypeDeclarations[i].functions[j].returnType;
|
|
|
|
*pStatic = structTypeDeclarations[i].functions[j].isStatic;
|
|
|
|
return structTypeDeclarations[i].functions[j].function;
|
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,
|
|
|
|
char *name,
|
|
|
|
LLVMTypeRef *pReturnType,
|
|
|
|
uint8_t *pStatic
|
|
|
|
) {
|
|
|
|
return LookupFunctionByPointerType(LLVMTypeOf(structPointer), name, pReturnType, pStatic);
|
|
|
|
}
|
|
|
|
|
2021-04-23 00:19:35 +00:00
|
|
|
static void AddStructVariablesToScope(
|
2021-04-22 04:29:38 +00:00
|
|
|
LLVMBuilderRef builder,
|
|
|
|
LLVMValueRef structPointer
|
|
|
|
) {
|
2021-04-21 02:07:11 +00:00
|
|
|
uint32_t i, j;
|
2021-04-21 02:00:18 +00:00
|
|
|
|
2021-04-23 05:37:23 +00:00
|
|
|
for (i = 0; i < structTypeDeclarationCount; i += 1)
|
2021-04-21 02:00:18 +00:00
|
|
|
{
|
2021-04-23 05:37:23 +00:00
|
|
|
if (structTypeDeclarations[i].structPointerType == LLVMTypeOf(structPointer))
|
2021-04-21 02:00:18 +00:00
|
|
|
{
|
2021-04-23 05:37:23 +00:00
|
|
|
for (j = 0; j < structTypeDeclarations[i].fieldCount; j += 1)
|
2021-04-21 02:07:11 +00:00
|
|
|
{
|
2021-04-23 05:37:23 +00:00
|
|
|
char *ptrName = strdup(structTypeDeclarations[i].fields[j].name);
|
2021-04-22 04:38:58 +00:00
|
|
|
strcat(ptrName, "_ptr");
|
2021-04-22 04:29:38 +00:00
|
|
|
LLVMValueRef elementPointer = LLVMBuildStructGEP(
|
|
|
|
builder,
|
|
|
|
structPointer,
|
2021-04-23 05:37:23 +00:00
|
|
|
structTypeDeclarations[i].fields[j].index,
|
2021-04-22 04:38:58 +00:00
|
|
|
ptrName
|
2021-04-22 04:29:38 +00:00
|
|
|
);
|
2021-04-22 04:38:58 +00:00
|
|
|
free(ptrName);
|
2021-04-22 04:29:38 +00:00
|
|
|
|
|
|
|
AddLocalVariable(
|
|
|
|
scope,
|
|
|
|
elementPointer,
|
2021-04-30 06:49:35 +00:00
|
|
|
NULL,
|
2021-04-23 05:37:23 +00:00
|
|
|
structTypeDeclarations[i].fields[j].name
|
2021-04-22 04:29:38 +00:00
|
|
|
);
|
2021-04-21 02:07:11 +00:00
|
|
|
}
|
2021-04-21 02:00:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-20 01:18:45 +00:00
|
|
|
static LLVMValueRef CompileExpression(
|
|
|
|
LLVMBuilderRef builder,
|
2021-04-29 04:25:25 +00:00
|
|
|
Node *expression
|
2021-04-20 01:18:45 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
static LLVMValueRef CompileNumber(
|
|
|
|
Node *numberExpression
|
2021-04-20 17:47:40 +00:00
|
|
|
) {
|
2021-05-15 22:34:15 +00:00
|
|
|
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,
|
|
|
|
Node *stringExpression
|
|
|
|
) {
|
2021-05-15 22:34:15 +00:00
|
|
|
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(
|
|
|
|
LLVMBuilderRef builder,
|
|
|
|
Node *binaryExpression
|
|
|
|
) {
|
2021-05-15 22:34:15 +00:00
|
|
|
LLVMValueRef left = CompileExpression(builder, binaryExpression->binaryExpression.left);
|
|
|
|
LLVMValueRef right = CompileExpression(builder, binaryExpression->binaryExpression.right);
|
2021-04-20 01:18:45 +00:00
|
|
|
|
2021-05-15 22:34:15 +00:00
|
|
|
switch (binaryExpression->binaryExpression.operator)
|
2021-04-20 01:18:45 +00:00
|
|
|
{
|
|
|
|
case Add:
|
2021-04-29 04:25:25 +00:00
|
|
|
return LLVMBuildAdd(builder, left, right, "addResult");
|
2021-04-20 17:47:40 +00:00
|
|
|
|
|
|
|
case Subtract:
|
2021-04-29 04:25:25 +00:00
|
|
|
return LLVMBuildSub(builder, left, right, "subtractResult");
|
2021-04-20 17:47:40 +00:00
|
|
|
|
|
|
|
case Multiply:
|
2021-04-29 04:25:25 +00:00
|
|
|
return LLVMBuildMul(builder, left, right, "multiplyResult");
|
2021-04-20 17:47:40 +00:00
|
|
|
|
2021-04-29 04:25:25 +00:00
|
|
|
/* FIXME: need type information for comparison */
|
|
|
|
case LessThan:
|
2021-04-29 22:26:30 +00:00
|
|
|
return LLVMBuildICmp(builder, LLVMIntSLT, left, right, "lessThanResult");
|
|
|
|
|
|
|
|
case GreaterThan:
|
|
|
|
return LLVMBuildICmp(builder, LLVMIntSGT, left, right, "greaterThanResult");
|
2021-04-30 06:49:35 +00:00
|
|
|
|
|
|
|
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(
|
|
|
|
LLVMBuilderRef builder,
|
2021-05-15 22:34:15 +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-15 22:34:15 +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 */
|
2021-05-15 22:34:15 +00:00
|
|
|
/* FIXME: this needs to be able to call same-struct functions implicitly */
|
|
|
|
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-15 22:34:15 +00:00
|
|
|
functionCallExpression->functionCallExpression.identifier->identifier.name
|
2021-04-23 05:37:23 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
if (typeReference != NULL)
|
|
|
|
{
|
|
|
|
function = LookupFunctionByType(
|
|
|
|
typeReference,
|
2021-05-15 22:34:15 +00:00
|
|
|
functionCallExpression->functionCallExpression.identifier->accessExpression.accessor->identifier.name,
|
2021-04-23 05:37:23 +00:00
|
|
|
&functionReturnType,
|
|
|
|
&isStatic
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
structInstance = FindVariablePointer(functionCallExpression->functionCallExpression.identifier->accessExpression.accessee->identifier.name);
|
|
|
|
function = LookupFunctionByInstance(structInstance, functionCallExpression->functionCallExpression.identifier->accessExpression.accessor->identifier.name, &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-15 22:34:15 +00:00
|
|
|
for (i = 0; i < functionCallExpression->functionCallExpression.argumentSequence->functionArgumentSequence.count; i += 1)
|
2021-04-23 00:19:35 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
args[argumentCount] = CompileExpression(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
|
|
|
}
|
|
|
|
|
|
|
|
static LLVMValueRef CompileAccessExpressionForStore(
|
|
|
|
LLVMBuilderRef builder,
|
2021-05-15 22:34:15 +00:00
|
|
|
Node *accessExpression
|
2021-04-22 04:29:38 +00:00
|
|
|
) {
|
2021-05-15 22:34:15 +00:00
|
|
|
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-15 22:34:15 +00:00
|
|
|
Node *accessExpression
|
2021-04-22 04:29:38 +00:00
|
|
|
) {
|
2021-05-15 22:34:15 +00:00
|
|
|
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-15 22:34:15 +00:00
|
|
|
Node *allocExpression
|
2021-04-28 19:49:45 +00:00
|
|
|
) {
|
2021-05-15 22:34:15 +00:00
|
|
|
LLVMTypeRef type = ResolveType(allocExpression->allocExpression.type);
|
2021-04-28 19:49:45 +00:00
|
|
|
return LLVMBuildMalloc(builder, type, "allocation");
|
|
|
|
}
|
|
|
|
|
2021-04-20 01:18:45 +00:00
|
|
|
static LLVMValueRef CompileExpression(
|
|
|
|
LLVMBuilderRef builder,
|
|
|
|
Node *expression
|
|
|
|
) {
|
|
|
|
switch (expression->syntaxKind)
|
|
|
|
{
|
2021-04-22 04:29:38 +00:00
|
|
|
case AccessExpression:
|
2021-04-23 00:19:35 +00:00
|
|
|
return CompileAccessExpression(builder, expression);
|
2021-04-22 04:29:38 +00:00
|
|
|
|
2021-04-28 19:49:45 +00:00
|
|
|
case AllocExpression:
|
|
|
|
return CompileAllocExpression(builder, expression);
|
|
|
|
|
2021-04-20 01:18:45 +00:00
|
|
|
case BinaryExpression:
|
2021-04-23 00:19:35 +00:00
|
|
|
return CompileBinaryExpression(builder, expression);
|
2021-04-20 01:18:45 +00:00
|
|
|
|
2021-04-20 17:47:40 +00:00
|
|
|
case FunctionCallExpression:
|
2021-04-23 00:19:35 +00:00
|
|
|
return CompileFunctionCallExpression(builder, expression);
|
2021-04-20 17:47:40 +00:00
|
|
|
|
2021-04-20 01:18:45 +00:00
|
|
|
case Identifier:
|
2021-05-15 22:34:15 +00:00
|
|
|
return FindVariableValue(builder, expression->identifier.name);
|
2021-04-20 01:18:45 +00:00
|
|
|
|
|
|
|
case Number:
|
2021-04-21 02:00:18 +00:00
|
|
|
return CompileNumber(expression);
|
2021-04-30 19:17:44 +00:00
|
|
|
|
|
|
|
case StringLiteral:
|
|
|
|
return CompileString(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-04-30 06:49:35 +00:00
|
|
|
static LLVMBasicBlockRef CompileStatement(LLVMBuilderRef builder, LLVMValueRef function, Node *statement);
|
2021-04-29 04:25:25 +00:00
|
|
|
|
2021-04-30 06:49:35 +00:00
|
|
|
static LLVMBasicBlockRef CompileReturn(LLVMBuilderRef builder, LLVMValueRef function, Node *returnStatemement)
|
2021-04-20 01:18:45 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
LLVMValueRef expression = CompileExpression(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-04-30 06:49:35 +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
|
|
|
}
|
|
|
|
|
2021-04-30 07:50:35 +00:00
|
|
|
/* FIXME: path for reference types */
|
|
|
|
static LLVMValueRef CompileFunctionVariableDeclaration(LLVMBuilderRef builder, LLVMValueRef function, Node *variableDeclaration)
|
|
|
|
{
|
|
|
|
LLVMValueRef variable;
|
2021-05-15 22:34:15 +00:00
|
|
|
char *variableName = variableDeclaration->declaration.identifier->identifier.name;
|
2021-04-30 07:50:35 +00:00
|
|
|
char *ptrName = strdup(variableName);
|
|
|
|
strcat(ptrName, "_ptr");
|
|
|
|
|
2021-05-15 22:34:15 +00:00
|
|
|
variable = LLVMBuildAlloca(builder, ResolveType(variableDeclaration->declaration.type), ptrName);
|
2021-04-30 07:50:35 +00:00
|
|
|
|
|
|
|
free(ptrName);
|
|
|
|
|
|
|
|
AddLocalVariable(scope, variable, NULL, variableName);
|
|
|
|
|
|
|
|
return variable;
|
|
|
|
}
|
|
|
|
|
2021-04-30 06:49:35 +00:00
|
|
|
static LLVMBasicBlockRef CompileAssignment(LLVMBuilderRef builder, LLVMValueRef function, Node *assignmentStatement)
|
2021-04-21 02:00:18 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
LLVMValueRef result = CompileExpression(builder, assignmentStatement->assignmentStatement.right);
|
2021-04-22 04:29:38 +00:00
|
|
|
LLVMValueRef identifier;
|
2021-05-15 22:34:15 +00:00
|
|
|
if (assignmentStatement->assignmentStatement.left->syntaxKind == AccessExpression)
|
2021-04-22 04:29:38 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
identifier = CompileAccessExpressionForStore(builder, assignmentStatement->assignmentStatement.left);
|
2021-04-22 04:29:38 +00:00
|
|
|
}
|
2021-05-15 22:34:15 +00:00
|
|
|
else if (assignmentStatement->assignmentStatement.left->syntaxKind == Identifier)
|
2021-04-22 04:29:38 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
identifier = FindVariablePointer(assignmentStatement->assignmentStatement.left->identifier.name);
|
2021-04-22 04:29:38 +00:00
|
|
|
}
|
2021-05-15 22:34:15 +00:00
|
|
|
else if (assignmentStatement->assignmentStatement.left->syntaxKind == Declaration)
|
2021-04-30 07:50:35 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
identifier = CompileFunctionVariableDeclaration(builder, function, assignmentStatement->assignmentStatement.left);
|
2021-04-30 07:50:35 +00:00
|
|
|
}
|
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-04-30 06:49:35 +00:00
|
|
|
static LLVMBasicBlockRef CompileIfStatement(LLVMBuilderRef builder, LLVMValueRef function, Node *ifStatement)
|
2021-04-29 04:25:25 +00:00
|
|
|
{
|
|
|
|
uint32_t i;
|
2021-05-15 22:34:15 +00:00
|
|
|
LLVMValueRef conditional = CompileExpression(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-15 22:34:15 +00:00
|
|
|
for (i = 0; i < ifStatement->ifStatement.statementSequence->statementSequence.count; i += 1)
|
2021-04-29 04:25:25 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
CompileStatement(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-04-30 06:49:35 +00:00
|
|
|
static LLVMBasicBlockRef CompileIfElseStatement(LLVMBuilderRef builder, LLVMValueRef function, Node *ifElseStatement)
|
2021-04-29 20:59:00 +00:00
|
|
|
{
|
|
|
|
uint32_t i;
|
2021-05-15 22:34:15 +00:00
|
|
|
LLVMValueRef conditional = CompileExpression(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-15 22:34:15 +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-15 22:34:15 +00:00
|
|
|
CompileStatement(builder, function, ifElseStatement->ifStatement.statementSequence->statementSequence.sequence[i]);
|
2021-04-29 20:59:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LLVMBuildBr(builder, afterCond);
|
|
|
|
|
|
|
|
LLVMPositionBuilderAtEnd(builder, elseBlock);
|
|
|
|
|
2021-05-15 22:34:15 +00:00
|
|
|
if (ifElseStatement->ifElseStatement.elseStatement->syntaxKind == StatementSequence)
|
2021-04-29 22:26:30 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
for (i = 0; i < ifElseStatement->ifElseStatement.elseStatement->statementSequence.count; i += 1)
|
2021-04-29 22:26:30 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
CompileStatement(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-15 22:34:15 +00:00
|
|
|
CompileStatement(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-04-30 06:49:35 +00:00
|
|
|
static LLVMBasicBlockRef CompileForLoopStatement(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");
|
2021-05-15 22:34:15 +00:00
|
|
|
char *iteratorVariableName = forLoopStatement->forLoop.declaration->declaration.identifier->identifier.name;
|
|
|
|
LLVMTypeRef iteratorVariableType = ResolveType(forLoopStatement->forLoop.declaration->declaration.type);
|
2021-04-30 06:49:35 +00:00
|
|
|
|
|
|
|
PushScopeFrame(scope);
|
|
|
|
|
|
|
|
LLVMBuildBr(builder, entryBlock);
|
|
|
|
|
|
|
|
LLVMPositionBuilderAtEnd(builder, entryBlock);
|
|
|
|
LLVMBuildBr(builder, checkBlock);
|
|
|
|
|
|
|
|
LLVMPositionBuilderAtEnd(builder, checkBlock);
|
2021-04-30 07:50:35 +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-15 22:34:15 +00:00
|
|
|
LLVMConstInt(iteratorVariableType, 1, 0), /* FIXME: add custom increment value */
|
2021-04-30 19:17:44 +00:00
|
|
|
"next"
|
|
|
|
);
|
2021-04-30 06:49:35 +00:00
|
|
|
|
|
|
|
LLVMPositionBuilderAtEnd(builder, checkBlock);
|
|
|
|
|
2021-05-15 22:34:15 +00:00
|
|
|
LLVMValueRef iteratorEndValue = CompileNumber(forLoopStatement->forLoop.endNumber);
|
2021-04-30 06:49:35 +00:00
|
|
|
LLVMValueRef comparison = LLVMBuildICmp(builder, LLVMIntULE, iteratorValue, iteratorEndValue, "iteratorCompare");
|
|
|
|
|
|
|
|
LLVMBuildCondBr(builder, comparison, bodyBlock, afterLoopBlock);
|
|
|
|
|
|
|
|
LLVMPositionBuilderAtEnd(builder, bodyBlock);
|
|
|
|
|
|
|
|
LLVMBasicBlockRef lastBlock;
|
2021-05-15 22:34:15 +00:00
|
|
|
for (i = 0; i < forLoopStatement->forLoop.statementSequence->statementSequence.count; i += 1)
|
2021-04-30 06:49:35 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
lastBlock = CompileStatement(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];
|
2021-05-15 22:34:15 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static LLVMBasicBlockRef CompileStatement(LLVMBuilderRef builder, LLVMValueRef function, Node *statement)
|
2021-04-20 01:18:45 +00:00
|
|
|
{
|
|
|
|
switch (statement->syntaxKind)
|
|
|
|
{
|
2021-04-21 02:00:18 +00:00
|
|
|
case Assignment:
|
2021-04-30 06:49:35 +00:00
|
|
|
return CompileAssignment(builder, function, statement);
|
|
|
|
|
|
|
|
case Declaration:
|
2021-04-30 07:50:35 +00:00
|
|
|
CompileFunctionVariableDeclaration(builder, function, statement);
|
|
|
|
return LLVMGetLastBasicBlock(function);
|
2021-04-30 06:49:35 +00:00
|
|
|
|
|
|
|
case ForLoop:
|
|
|
|
return CompileForLoopStatement(builder, function, statement);
|
2021-04-23 00:19:35 +00:00
|
|
|
|
|
|
|
case FunctionCallExpression:
|
|
|
|
CompileFunctionCallExpression(builder, statement);
|
2021-04-30 06:49:35 +00:00
|
|
|
return LLVMGetLastBasicBlock(function);
|
2021-04-21 06:51:26 +00:00
|
|
|
|
2021-04-29 04:25:25 +00:00
|
|
|
case IfStatement:
|
2021-04-30 06:49:35 +00:00
|
|
|
return CompileIfStatement(builder, function, statement);
|
2021-04-29 04:25:25 +00:00
|
|
|
|
2021-04-29 20:59:00 +00:00
|
|
|
case IfElseStatement:
|
2021-04-30 06:49:35 +00:00
|
|
|
return CompileIfElseStatement(builder, function, statement);
|
2021-04-29 20:59:00 +00:00
|
|
|
|
2021-04-20 01:18:45 +00:00
|
|
|
case Return:
|
2021-04-30 06:49:35 +00:00
|
|
|
return CompileReturn(builder, function, statement);
|
2021-04-21 02:00:18 +00:00
|
|
|
|
|
|
|
case ReturnVoid:
|
2021-04-30 06:49:35 +00:00
|
|
|
return CompileReturnVoid(builder, 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(
|
|
|
|
LLVMModuleRef module,
|
2021-04-22 17:27:39 +00:00
|
|
|
char *parentStructName,
|
2021-04-21 02:00:18 +00:00
|
|
|
LLVMTypeRef wStructPointerType,
|
|
|
|
Node **fieldDeclarations,
|
|
|
|
uint32_t fieldDeclarationCount,
|
|
|
|
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-15 22:34:15 +00:00
|
|
|
Node *functionSignature = functionDeclaration->functionDeclaration.functionSignature;
|
|
|
|
Node *functionBody = functionDeclaration->functionDeclaration.functionBody;
|
|
|
|
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-15 22:34:15 +00:00
|
|
|
if (functionSignature->functionSignature.modifiers->functionModifiers.count > 0)
|
2021-04-22 07:35:42 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
for (i = 0; i < functionSignature->functionSignature.modifiers->functionModifiers.count; i += 1)
|
2021-04-22 07:35:42 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +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-04-22 07:35:42 +00:00
|
|
|
if (!isStatic)
|
|
|
|
{
|
|
|
|
paramTypes[paramIndex] = wStructPointerType;
|
|
|
|
paramIndex += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
PushScopeFrame(scope);
|
2021-04-18 22:45:06 +00:00
|
|
|
|
2021-04-24 19:59:30 +00:00
|
|
|
/* FIXME: should work for non-primitive types */
|
2021-05-15 22:34:15 +00:00
|
|
|
for (i = 0; i < functionSignature->functionSignature.arguments->functionSignatureArguments.count; i += 1)
|
2021-04-18 22:45:06 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
paramTypes[paramIndex] = ResolveType(functionSignature->functionSignature.arguments->functionSignatureArguments.sequence[i]->declaration.type);
|
2021-04-22 07:35:42 +00:00
|
|
|
paramIndex += 1;
|
2021-04-20 01:18:45 +00:00
|
|
|
}
|
|
|
|
|
2021-05-15 22:34:15 +00:00
|
|
|
LLVMTypeRef returnType = ResolveType(functionSignature->functionSignature.type);
|
2021-04-22 07:35:42 +00:00
|
|
|
LLVMTypeRef functionType = LLVMFunctionType(returnType, paramTypes, paramIndex, 0);
|
2021-04-22 17:27:39 +00:00
|
|
|
|
|
|
|
char *functionName = strdup(parentStructName);
|
|
|
|
strcat(functionName, "_");
|
2021-05-15 22:34:15 +00:00
|
|
|
strcat(functionName, functionSignature->functionSignature.identifier->identifier.name);
|
2021-04-22 17:27:39 +00:00
|
|
|
LLVMValueRef function = LLVMAddFunction(module, functionName, functionType);
|
|
|
|
free(functionName);
|
2021-04-20 01:18:45 +00:00
|
|
|
|
2021-05-15 22:34:15 +00:00
|
|
|
DeclareStructFunction(wStructPointerType, function, returnType, isStatic, functionSignature->functionSignature.identifier->identifier.name);
|
2021-04-23 00:19:35 +00:00
|
|
|
|
2021-04-20 01:18:45 +00:00
|
|
|
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry");
|
|
|
|
LLVMBuilderRef builder = LLVMCreateBuilder();
|
|
|
|
LLVMPositionBuilderAtEnd(builder, entry);
|
|
|
|
|
2021-04-22 07:35:42 +00:00
|
|
|
if (!isStatic)
|
|
|
|
{
|
|
|
|
LLVMValueRef wStructPointer = LLVMGetParam(function, 0);
|
2021-04-23 00:19:35 +00:00
|
|
|
AddStructVariablesToScope(builder, wStructPointer);
|
2021-04-22 07:35:42 +00:00
|
|
|
}
|
2021-04-22 04:29:38 +00:00
|
|
|
|
2021-05-15 22:34:15 +00:00
|
|
|
for (i = 0; i < functionSignature->functionSignature.arguments->functionSignatureArguments.count; i += 1)
|
2021-04-21 02:00:18 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
char *ptrName = strdup(functionSignature->functionSignature.arguments->functionSignatureArguments.sequence[i]->identifier.name);
|
2021-04-22 04:38:58 +00:00
|
|
|
strcat(ptrName, "_ptr");
|
2021-04-23 05:37:23 +00:00
|
|
|
LLVMValueRef argument = LLVMGetParam(function, i + !isStatic);
|
2021-04-22 04:38:58 +00:00
|
|
|
LLVMValueRef argumentCopy = LLVMBuildAlloca(builder, LLVMTypeOf(argument), ptrName);
|
|
|
|
LLVMBuildStore(builder, argument, argumentCopy);
|
|
|
|
free(ptrName);
|
2021-05-15 22:34:15 +00:00
|
|
|
AddLocalVariable(scope, argumentCopy, NULL, functionSignature->functionSignature.arguments->functionSignatureArguments.sequence[i]->identifier.name);
|
2021-04-21 02:00:18 +00:00
|
|
|
}
|
|
|
|
|
2021-05-15 22:34:15 +00:00
|
|
|
for (i = 0; i < functionBody->statementSequence.count; i += 1)
|
2021-04-20 01:18:45 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
CompileStatement(builder, function, functionBody->statementSequence.sequence[i]);
|
2021-04-20 01:18:45 +00:00
|
|
|
}
|
2021-04-20 17:47:40 +00:00
|
|
|
|
2021-04-30 06:49:35 +00:00
|
|
|
hasReturn = LLVMGetBasicBlockTerminator(LLVMGetLastBasicBlock(function)) != NULL;
|
|
|
|
|
2021-04-21 02:00:18 +00:00
|
|
|
if (LLVMGetTypeKind(returnType) == LLVMVoidTypeKind && !hasReturn)
|
|
|
|
{
|
|
|
|
LLVMBuildRetVoid(builder);
|
|
|
|
}
|
|
|
|
else if (LLVMGetTypeKind(returnType) != LLVMVoidTypeKind && !hasReturn)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Return statement not provided!");
|
|
|
|
}
|
2021-04-22 04:29:38 +00:00
|
|
|
|
|
|
|
PopScopeFrame(scope);
|
2021-04-22 17:27:39 +00:00
|
|
|
|
|
|
|
LLVMDisposeBuilder(builder);
|
2021-04-21 02:00:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void CompileStruct(LLVMModuleRef module, LLVMContextRef context, Node *node)
|
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
uint32_t fieldCount = 0;
|
2021-05-15 22:34:15 +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;
|
|
|
|
Node *fieldDeclarations[declarationCount];
|
2021-05-15 22:34:15 +00:00
|
|
|
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-04-23 05:37:23 +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
|
|
|
|
|
|
|
/* first, build the structure definition */
|
|
|
|
for (i = 0; i < declarationCount; i += 1)
|
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
currentDeclarationNode = node->structDeclaration.declarationSequence->declarationSequence.sequence[i];
|
2021-04-21 02:00:18 +00:00
|
|
|
|
|
|
|
switch (currentDeclarationNode->syntaxKind)
|
|
|
|
{
|
|
|
|
case Declaration: /* this is badly named */
|
2021-05-15 22:34:15 +00:00
|
|
|
types[fieldCount] = ResolveType(currentDeclarationNode->declaration.type);
|
2021-04-21 02:00:18 +00:00
|
|
|
fieldDeclarations[fieldCount] = currentDeclarationNode;
|
|
|
|
fieldCount += 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-23 05:37:23 +00:00
|
|
|
LLVMStructSetBody(wStructType, types, fieldCount, packed);
|
2021-05-15 22:34:15 +00:00
|
|
|
AddStructDeclaration(wStructType, wStructPointerType, structName, fieldDeclarations, fieldCount);
|
2021-04-21 02:00:18 +00:00
|
|
|
|
|
|
|
/* now we can wire up the functions */
|
|
|
|
for (i = 0; i < declarationCount; i += 1)
|
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
currentDeclarationNode = node->structDeclaration.declarationSequence->declarationSequence.sequence[i];
|
2021-04-21 02:00:18 +00:00
|
|
|
|
|
|
|
switch (currentDeclarationNode->syntaxKind)
|
|
|
|
{
|
|
|
|
case FunctionDeclaration:
|
2021-04-22 17:27:39 +00:00
|
|
|
CompileFunction(module, structName, wStructPointerType, fieldDeclarations, fieldCount, currentDeclarationNode);
|
2021-04-21 02:00:18 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
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-15 22:34:15 +00:00
|
|
|
static void Compile(LLVMModuleRef module, LLVMContextRef context, Node *declarationSequenceNode)
|
2021-04-18 22:45:06 +00:00
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
|
2021-05-15 22:34:15 +00:00
|
|
|
for (i = 0; i < declarationSequenceNode->declarationSequence.count; i += 1)
|
2021-04-18 22:45:06 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
if (declarationSequenceNode->declarationSequence.sequence[i]->syntaxKind == StructDeclaration)
|
2021-04-23 00:19:35 +00:00
|
|
|
{
|
2021-05-15 22:34:15 +00:00
|
|
|
CompileStruct(module, context, declarationSequenceNode->declarationSequence.sequence[i]);
|
2021-04-23 00:19:35 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "top level declarations that are not structs are forbidden!\n");
|
|
|
|
}
|
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? */
|
|
|
|
static void RegisterLibraryFunctions(LLVMModuleRef module, LLVMContextRef context)
|
|
|
|
{
|
|
|
|
LLVMTypeRef structType = LLVMStructCreateNamed(context, "Console");
|
|
|
|
LLVMTypeRef structPointerType = LLVMPointerType(structType, 0);
|
|
|
|
AddStructDeclaration(structType, structPointerType, "Console", NULL, 0);
|
|
|
|
|
|
|
|
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(structPointerType, printLineFunction, LLVMInt8Type(), 1, "PrintLine");
|
|
|
|
}
|
|
|
|
|
2021-04-28 23:10:17 +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-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();
|
|
|
|
|
|
|
|
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 */
|
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;
|
|
|
|
if (LLVMGetTargetFromTriple(LLVM_DEFAULT_TARGET_TRIPLE, &target, &error) != 0)
|
|
|
|
{
|
|
|
|
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-04-22 05:48:55 +00:00
|
|
|
LLVMPassManagerBuilderRef passManagerBuilder = LLVMPassManagerBuilderCreate();
|
2021-04-28 22:21:51 +00:00
|
|
|
LLVMPassManagerBuilderSetOptLevel(passManagerBuilder, optimizationLevel);
|
2021-04-22 05:48:55 +00:00
|
|
|
LLVMPassManagerBuilderPopulateModulePassManager(passManagerBuilder, passManager);
|
|
|
|
|
|
|
|
LLVMRunPassManager(passManager, module);
|
|
|
|
|
2021-04-20 01:18:45 +00:00
|
|
|
if (LLVMWriteBitcodeToFile(module, "test.bc") != 0) {
|
|
|
|
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,
|
|
|
|
LLVMCodeModelDefault
|
|
|
|
);
|
2021-04-22 07:35:42 +00:00
|
|
|
|
2021-04-22 17:27:39 +00:00
|
|
|
if (LLVMTargetMachineEmitToFile(targetMachine, module, "test.o", LLVMObjectFile, &error) != 0)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|