basic compilation structure
parent
392ce41e97
commit
5c147d80ec
|
@ -3,6 +3,20 @@ project(WRAITH_LANG C)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
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(BISON)
|
||||||
find_package(FLEX)
|
find_package(FLEX)
|
||||||
find_package(LLVM)
|
find_package(LLVM)
|
||||||
|
|
19
ast.c
19
ast.c
|
@ -28,6 +28,7 @@ const char* SyntaxKindString(SyntaxKind syntaxKind)
|
||||||
case DeclarationSequence: return "DeclarationSequence";
|
case DeclarationSequence: return "DeclarationSequence";
|
||||||
case FunctionDeclaration: return "FunctionDeclaration";
|
case FunctionDeclaration: return "FunctionDeclaration";
|
||||||
case FunctionSignature: return "FunctionSignature";
|
case FunctionSignature: return "FunctionSignature";
|
||||||
|
case FunctionSignatureArguments: return "FunctionSignatureArguments";
|
||||||
case Identifier: return "Identifier";
|
case Identifier: return "Identifier";
|
||||||
case Number: return "Number";
|
case Number: return "Number";
|
||||||
case Return: return "Return";
|
case Return: return "Return";
|
||||||
|
@ -162,6 +163,24 @@ Node* MakeReturnStatementNode(
|
||||||
return node;
|
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* MakeFunctionSignatureNode(
|
||||||
Node *identifierNode,
|
Node *identifierNode,
|
||||||
Node* typeNode,
|
Node* typeNode,
|
||||||
|
|
5
ast.h
5
ast.h
|
@ -14,6 +14,7 @@ typedef enum
|
||||||
ForLoop,
|
ForLoop,
|
||||||
FunctionDeclaration,
|
FunctionDeclaration,
|
||||||
FunctionSignature,
|
FunctionSignature,
|
||||||
|
FunctionSignatureArguments,
|
||||||
Identifier,
|
Identifier,
|
||||||
Number,
|
Number,
|
||||||
Return,
|
Return,
|
||||||
|
@ -108,6 +109,10 @@ Node* MakeStatementSequenceNode(
|
||||||
Node* MakeReturnStatementNode(
|
Node* MakeReturnStatementNode(
|
||||||
Node *expressionNode
|
Node *expressionNode
|
||||||
);
|
);
|
||||||
|
Node* MakeFunctionSignatureArgumentsNode(
|
||||||
|
Node **pArgumentNodes,
|
||||||
|
uint32_t argumentCount
|
||||||
|
);
|
||||||
Node* MakeFunctionSignatureNode(
|
Node* MakeFunctionSignatureNode(
|
||||||
Node *identifierNode,
|
Node *identifierNode,
|
||||||
Node* typeNode,
|
Node* typeNode,
|
||||||
|
|
153
compiler.c
153
compiler.c
|
@ -1,5 +1,10 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <llvm-c/Core.h>
|
#include <llvm-c/Core.h>
|
||||||
|
#include <llvm-c/Analysis.h>
|
||||||
|
#include <llvm-c/BitWriter.h>
|
||||||
|
|
||||||
#include "y.tab.h"
|
#include "y.tab.h"
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
|
@ -9,7 +14,50 @@ extern FILE *yyin;
|
||||||
Stack *stack;
|
Stack *stack;
|
||||||
Node *rootNode;
|
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)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
@ -23,23 +71,105 @@ LLVMTypeRef WraithTypeToLLVMType(PrimitiveType type)
|
||||||
return NULL;
|
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;
|
uint32_t i;
|
||||||
Node *functionSignature = functionDeclaration->children[0];
|
Node *functionSignature = functionDeclaration->children[0];
|
||||||
|
Node *functionBody = functionDeclaration->children[1];
|
||||||
LLVMTypeRef paramTypes[functionSignature->children[2]->childCount];
|
LLVMTypeRef paramTypes[functionSignature->children[2]->childCount];
|
||||||
|
|
||||||
for (i = 0; i < functionSignature->children[2]->childCount; i += 1)
|
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;
|
uint32_t i;
|
||||||
|
|
||||||
|
@ -64,6 +194,9 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namedVariables = NULL;
|
||||||
|
namedVariableCount = 0;
|
||||||
|
|
||||||
stack = CreateStack();
|
stack = CreateStack();
|
||||||
|
|
||||||
FILE *fp = fopen(argv[1], "r");
|
FILE *fp = fopen(argv[1], "r");
|
||||||
|
@ -77,5 +210,13 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
Compile(module, rootNode);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
18
wraith.y
18
wraith.y
|
@ -179,9 +179,15 @@ Statements : Statement Statements
|
||||||
PushStackFrame(stack);
|
PushStackFrame(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
Arguments : Arguments COMMA VariableDeclaration
|
Arguments : VariableDeclaration COMMA VariableDeclarations
|
||||||
|
{
|
||||||
|
AddDeclaration(stack, $1);
|
||||||
|
}
|
||||||
| VariableDeclaration
|
| VariableDeclaration
|
||||||
;
|
{
|
||||||
|
PushStackFrame(stack);
|
||||||
|
AddDeclaration(stack, $1);
|
||||||
|
}
|
||||||
|
|
||||||
Body : LEFT_BRACE Statements RIGHT_BRACE
|
Body : LEFT_BRACE Statements RIGHT_BRACE
|
||||||
{
|
{
|
||||||
|
@ -198,7 +204,13 @@ Body : LEFT_BRACE Statements RIGHT_BRACE
|
||||||
|
|
||||||
FunctionSignature : Type Identifier LEFT_PAREN Arguments RIGHT_PAREN
|
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
|
FunctionDeclaration : FunctionSignature Body
|
||||||
|
|
Loading…
Reference in New Issue