diff --git a/CMakeLists.txt b/CMakeLists.txt index f1a1640..be9c716 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/ast.c b/ast.c index 6468cb6..a8634c8 100644 --- a/ast.c +++ b/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, diff --git a/ast.h b/ast.h index b98e77e..6dd42ad 100644 --- a/ast.h +++ b/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, diff --git a/compiler.c b/compiler.c index e7f1c9d..98b4e30 100644 --- a/compiler.c +++ b/compiler.c @@ -1,5 +1,10 @@ #include +#include +#include + #include +#include +#include #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; } diff --git a/wraith.y b/wraith.y index 95da9f5..dee5563 100644 --- a/wraith.y +++ b/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