basic compilation structure

generics
cosmonaut 2021-04-19 18:18:45 -07:00
parent 392ce41e97
commit 5c147d80ec
5 changed files with 200 additions and 9 deletions

View File

@ -3,6 +3,20 @@ project(WRAITH_LANG C)
set(CMAKE_C_STANDARD 99)
# Build Type
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
# By default, we use Release
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE "Release" CACHE
STRING "Choose the type of build." FORCE
)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
STRINGS "Debug" "Release" "RelWithDebInfo"
)
endif()
find_package(BISON)
find_package(FLEX)
find_package(LLVM)

19
ast.c
View File

@ -28,6 +28,7 @@ const char* SyntaxKindString(SyntaxKind syntaxKind)
case DeclarationSequence: return "DeclarationSequence";
case FunctionDeclaration: return "FunctionDeclaration";
case FunctionSignature: return "FunctionSignature";
case FunctionSignatureArguments: return "FunctionSignatureArguments";
case Identifier: return "Identifier";
case Number: return "Number";
case Return: return "Return";
@ -162,6 +163,24 @@ Node* MakeReturnStatementNode(
return node;
}
Node *MakeFunctionSignatureArgumentsNode(
Node **pArgumentNodes,
uint32_t argumentCount
) {
int32_t i;
Node* node = (Node*) malloc(sizeof(Node));
node->syntaxKind = FunctionSignatureArguments;
node->childCount = argumentCount;
node->children = (Node**) malloc(sizeof(Node*) * (node->childCount));
for (i = argumentCount - 1; i >= 0; i -= 1)
{
node->children[argumentCount - 1 - i] = pArgumentNodes[i];
}
return node;
}
Node* MakeFunctionSignatureNode(
Node *identifierNode,
Node* typeNode,

5
ast.h
View File

@ -14,6 +14,7 @@ typedef enum
ForLoop,
FunctionDeclaration,
FunctionSignature,
FunctionSignatureArguments,
Identifier,
Number,
Return,
@ -108,6 +109,10 @@ Node* MakeStatementSequenceNode(
Node* MakeReturnStatementNode(
Node *expressionNode
);
Node* MakeFunctionSignatureArgumentsNode(
Node **pArgumentNodes,
uint32_t argumentCount
);
Node* MakeFunctionSignatureNode(
Node *identifierNode,
Node* typeNode,

View File

@ -1,5 +1,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <llvm-c/Core.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/BitWriter.h>
#include "y.tab.h"
#include "ast.h"
@ -9,7 +14,50 @@ extern FILE *yyin;
Stack *stack;
Node *rootNode;
LLVMTypeRef WraithTypeToLLVMType(PrimitiveType type)
typedef struct VariableMapValue
{
char *name;
LLVMValueRef variable;
} VariableMapValue;
VariableMapValue *namedVariables;
uint32_t namedVariableCount;
static LLVMValueRef CompileExpression(
LLVMModuleRef module,
LLVMBuilderRef builder,
LLVMValueRef function,
Node *binaryExpression
);
static void AddNamedVariable(char *name, LLVMValueRef variable)
{
VariableMapValue mapValue;
mapValue.name = name;
mapValue.variable = variable;
namedVariables = realloc(namedVariables, namedVariableCount + 1);
namedVariables[namedVariableCount] = mapValue;
namedVariableCount += 1;
}
static LLVMValueRef FindVariableByName(char *name)
{
uint32_t i;
for (i = 0; i < namedVariableCount; i += 1)
{
if (strcmp(namedVariables[i].name, name) == 0)
{
return namedVariables[i].variable;
}
}
return NULL;
}
static LLVMTypeRef WraithTypeToLLVMType(PrimitiveType type)
{
switch (type)
{
@ -23,23 +71,105 @@ LLVMTypeRef WraithTypeToLLVMType(PrimitiveType type)
return NULL;
}
void CompileFunction(LLVMModuleRef module, Node *functionDeclaration)
static LLVMValueRef CompileNumber(
LLVMModuleRef module,
LLVMBuilderRef builder,
LLVMValueRef function,
Node *numberExpression
)
{
return LLVMConstInt(LLVMInt64Type(), numberExpression->value.number, 0);
}
static LLVMValueRef CompileBinaryExpression(
LLVMModuleRef module,
LLVMBuilderRef builder,
LLVMValueRef function,
Node *binaryExpression
) {
LLVMValueRef left = CompileExpression(module, builder, function, binaryExpression->children[0]);
LLVMValueRef right = CompileExpression(module, builder, function, binaryExpression->children[1]);
switch (binaryExpression->operator.binaryOperator)
{
case Add:
return LLVMBuildAdd(builder, left, right, "tmp");
}
return NULL;
}
static LLVMValueRef CompileExpression(
LLVMModuleRef module,
LLVMBuilderRef builder,
LLVMValueRef function,
Node *expression
) {
switch (expression->syntaxKind)
{
case BinaryExpression:
return CompileBinaryExpression(module, builder, function, expression);
case Identifier:
return FindVariableByName(expression->value.string);
case Number:
return CompileNumber(module, builder, function, expression);
}
printf("Error: expected expression\n");
return NULL;
}
static void CompileReturn(LLVMModuleRef module, LLVMBuilderRef builder, LLVMValueRef function, Node *returnStatemement)
{
LLVMBuildRet(builder, CompileExpression(module, builder, function, returnStatemement->children[0]));
}
static void CompileStatement(LLVMModuleRef module, LLVMBuilderRef builder, LLVMValueRef function, Node *statement)
{
switch (statement->syntaxKind)
{
case Return:
CompileReturn(module, builder, function, statement);
break;
}
}
static void CompileFunction(LLVMModuleRef module, Node *functionDeclaration)
{
uint32_t i;
Node *functionSignature = functionDeclaration->children[0];
Node *functionBody = functionDeclaration->children[1];
LLVMTypeRef paramTypes[functionSignature->children[2]->childCount];
for (i = 0; i < functionSignature->children[2]->childCount; i += 1)
{
LLVMTypeRef paramType = WraithTypeToLLVMType(functionSignature->children[0]->type);
paramTypes[i] = WraithTypeToLLVMType(functionSignature->children[2]->children[i]->children[0]->type);
}
LLVMTypeRef returnType = WraithTypeToLLVMType(functionSignature->children[1]->type);
LLVMTypeRef functionType = LLVMFunctionType(WraithTypeToLLVMType(functionSignature->children[1]->type), paramTypes, functionSignature->children[2]->childCount, 0);
LLVMAddFunction(module, functionSignature->children[0]->value.string, returnType);
LLVMValueRef function = LLVMAddFunction(module, functionSignature->children[0]->value.string, functionType);
for (i = 0; i < functionSignature->children[2]->childCount; i += 1)
{
LLVMValueRef argument = LLVMGetParam(function, i);
AddNamedVariable(functionSignature->children[2]->children[i]->children[1]->value.string, argument);
}
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry");
LLVMBuilderRef builder = LLVMCreateBuilder();
LLVMPositionBuilderAtEnd(builder, entry);
for (i = 0; i < functionBody->childCount; i += 1)
{
CompileStatement(module, builder, function, functionBody->children[i]);
}
}
void Compile(LLVMModuleRef module, Node *node)
static void Compile(LLVMModuleRef module, Node *node)
{
uint32_t i;
@ -64,6 +194,9 @@ int main(int argc, char *argv[])
return 1;
}
namedVariables = NULL;
namedVariableCount = 0;
stack = CreateStack();
FILE *fp = fopen(argv[1], "r");
@ -77,5 +210,13 @@ int main(int argc, char *argv[])
Compile(module, rootNode);
char *error = NULL;
LLVMVerifyModule(module, LLVMAbortProcessAction, &error);
LLVMDisposeMessage(error);
if (LLVMWriteBitcodeToFile(module, "test.bc") != 0) {
fprintf(stderr, "error writing bitcode to file\n");
}
return 0;
}

View File

@ -179,9 +179,15 @@ Statements : Statement Statements
PushStackFrame(stack);
}
Arguments : Arguments COMMA VariableDeclaration
Arguments : VariableDeclaration COMMA VariableDeclarations
{
AddDeclaration(stack, $1);
}
| VariableDeclaration
;
{
PushStackFrame(stack);
AddDeclaration(stack, $1);
}
Body : LEFT_BRACE Statements RIGHT_BRACE
{
@ -198,7 +204,13 @@ Body : LEFT_BRACE Statements RIGHT_BRACE
FunctionSignature : Type Identifier LEFT_PAREN Arguments RIGHT_PAREN
{
$$ = MakeFunctionSignatureNode($2, $1, $4);
Node **declarations;
uint32_t declarationCount;
declarations = GetDeclarations(stack, &declarationCount);
$$ = MakeFunctionSignatureNode($2, $1, MakeFunctionSignatureArgumentsNode(declarations, declarationCount));
PopStackFrame(stack);
}
FunctionDeclaration : FunctionSignature Body