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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										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