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