forked from cosmonaut/wraith-lang
basic compilation structure
parent
392ce41e97
commit
5c147d80ec
|
@ -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
19
ast.c
|
@ -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
5
ast.h
|
@ -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,
|
||||
|
|
153
compiler.c
153
compiler.c
|
@ -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);
|
||||
}
|
||||
|
||||
void Compile(LLVMModuleRef module, Node *node)
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
18
wraith.y
18
wraith.y
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue