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