removed redundant files
This commit is contained in:
parent
220b5d7dcb
commit
614c917b81
|
@ -1,10 +1,4 @@
|
||||||
|
|
||||||
#include <llvm/decl/variable.h>
|
|
||||||
#include <llvm/function/function-types.h>
|
|
||||||
#include <llvm/function/function.h>
|
|
||||||
#include <llvm/types/scope.h>
|
|
||||||
#include <llvm/types/structs.h>
|
|
||||||
#include <llvm/types/type.h>
|
|
||||||
#include <codegen/backend.h>
|
#include <codegen/backend.h>
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
#include <ast/ast.h>
|
#include <ast/ast.h>
|
||||||
|
@ -23,46 +17,6 @@ static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**)
|
||||||
|
|
||||||
BackendError err;
|
BackendError err;
|
||||||
|
|
||||||
TypeScopeRef global_scope = type_scope_new();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < module_node->child_count; i++) {
|
|
||||||
// iterate over all nodes in module
|
|
||||||
// can either be a function, box, definition, declaration or typedefine
|
|
||||||
|
|
||||||
AST_NODE_PTR global_node = AST_get_node(module_node, i);
|
|
||||||
|
|
||||||
GemstoneTypedefRef typedefref;
|
|
||||||
GArray* decls;
|
|
||||||
|
|
||||||
switch (global_node->kind) {
|
|
||||||
case AST_Typedef:
|
|
||||||
typedefref = get_type_def_from_ast(global_scope, global_node);
|
|
||||||
type_scope_append_type(global_scope, typedefref);
|
|
||||||
break;
|
|
||||||
case AST_Fun:
|
|
||||||
llvm_generate_function_implementation(global_scope, module, global_node);
|
|
||||||
break;
|
|
||||||
case AST_Decl:
|
|
||||||
decls = declaration_from_ast(global_scope, global_node);
|
|
||||||
for (size_t i = 0; i < decls->len; i++) {
|
|
||||||
GemstoneDeclRef decl = ((GemstoneDeclRef*) decls->data)[i];
|
|
||||||
|
|
||||||
err = llvm_create_declaration(module, NULL, decl, &decl->llvm_value);
|
|
||||||
|
|
||||||
if (err.kind != Success)
|
|
||||||
break;
|
|
||||||
|
|
||||||
type_scope_add_variable(global_scope, decl);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PANIC("NOT IMPLEMENTED");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type_scope_delete(global_scope);
|
|
||||||
|
|
||||||
LLVMDisposeModule(module);
|
LLVMDisposeModule(module);
|
||||||
LLVMContextDispose(context);
|
LLVMContextDispose(context);
|
||||||
|
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
#include <codegen/backend.h>
|
|
||||||
#include <llvm/types/scope.h>
|
|
||||||
#include <llvm/types/structs.h>
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
#include <llvm/types/type.h>
|
|
||||||
#include <ast/ast.h>
|
|
||||||
#include <llvm/decl/variable.h>
|
|
||||||
#include <sys/log.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
static StorageQualifier get_storage_qualifier_from_ast(AST_NODE_PTR storageQualifierNode) {
|
|
||||||
if (storageQualifierNode->kind != AST_Storage) {
|
|
||||||
PANIC("Node must be of type AST_Fun: %s", AST_node_to_string(storageQualifierNode));
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageQualifier storageQualifier;
|
|
||||||
|
|
||||||
if (strcmp(storageQualifierNode->value, "local") == 0) {
|
|
||||||
storageQualifier = StorageQualifierLocal;
|
|
||||||
} else if (strcmp(storageQualifierNode->value, "static") == 0) {
|
|
||||||
storageQualifier = StorageQualifierStatic;
|
|
||||||
} else if (strcmp(storageQualifierNode->value, "global") == 0) {
|
|
||||||
storageQualifier = StorageQualifierGlobal;
|
|
||||||
} else {
|
|
||||||
PANIC("unknown storage qualifier: %s", storageQualifierNode->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return storageQualifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
GArray* declaration_from_ast(TypeScopeRef scope, const AST_NODE_PTR node) {
|
|
||||||
if (node->kind != AST_Decl) {
|
|
||||||
PANIC("Node must be of type AST_Fun: %s", AST_node_to_string(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
GArray* decls = g_array_new(FALSE, FALSE, sizeof(GemstoneDeclRef));
|
|
||||||
|
|
||||||
AST_NODE_PTR first_child = AST_get_node(node, 0);
|
|
||||||
|
|
||||||
StorageQualifier qualifier = StorageQualifierStatic;
|
|
||||||
GemstoneTypeRef type = NULL;
|
|
||||||
AST_NODE_PTR list = NULL;
|
|
||||||
|
|
||||||
if (first_child->kind == AST_Storage) {
|
|
||||||
qualifier = get_storage_qualifier_from_ast(first_child);
|
|
||||||
type = get_type_from_ast(scope, AST_get_node(node, 1));
|
|
||||||
list = AST_get_node(node, 2);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
type = get_type_from_ast(scope, first_child);
|
|
||||||
list = AST_get_node(node, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list->kind != AST_IdentList) {
|
|
||||||
PANIC("Node must be of type AST_IdentList: %s", AST_node_to_string(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < list->child_count; i++) {
|
|
||||||
GemstoneDeclRef ref = malloc(sizeof(GemstoneDecl));
|
|
||||||
ref->name = AST_get_node(list, i)->value;
|
|
||||||
ref->storageQualifier = qualifier;
|
|
||||||
ref->type = type;
|
|
||||||
|
|
||||||
g_array_append_val(decls, ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
return decls;
|
|
||||||
}
|
|
||||||
|
|
||||||
BackendError llvm_create_declaration(LLVMModuleRef llvm_module, LLVMBuilderRef llvm_builder, GemstoneDeclRef gem_decl, LLVMValueRef* llvm_decl) {
|
|
||||||
LLVMContextRef context = LLVMGetModuleContext(llvm_module);
|
|
||||||
LLVMTypeRef llvmTypeRef = llvm_type_from_gemstone_type(context, gem_decl->type);
|
|
||||||
LLVMValueRef defaultValue = llvm_default_value_of_type(context, gem_decl->type);
|
|
||||||
|
|
||||||
switch(gem_decl->storageQualifier) {
|
|
||||||
case StorageQualifierLocal:
|
|
||||||
if (llvm_builder == NULL) {
|
|
||||||
return new_backend_impl_error(Implementation, NULL, "initializing a local variable on non-local scope");
|
|
||||||
}
|
|
||||||
*llvm_decl = LLVMBuildAlloca(llvm_builder, llvmTypeRef, gem_decl->name);
|
|
||||||
LLVMBuildStore(llvm_builder, defaultValue, *llvm_decl);
|
|
||||||
break;
|
|
||||||
case StorageQualifierStatic:
|
|
||||||
// add global
|
|
||||||
*llvm_decl = LLVMAddGlobal(llvm_module, llvmTypeRef, gem_decl->name);
|
|
||||||
LLVMSetInitializer(*llvm_decl, defaultValue);
|
|
||||||
break;
|
|
||||||
case StorageQualifierGlobal:
|
|
||||||
PANIC("Global not implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
|
|
||||||
#ifndef LLVM_DECL_VAR_H_
|
|
||||||
#define LLVM_DECL_VAR_H_
|
|
||||||
|
|
||||||
#include <codegen/backend.h>
|
|
||||||
#include <ast/ast.h>
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
#include <llvm/types/structs.h>
|
|
||||||
#include <llvm/types/scope.h>
|
|
||||||
#include <llvm-c/Core.h>
|
|
||||||
|
|
||||||
GArray* declaration_from_ast(TypeScopeRef scope, const AST_NODE_PTR node);
|
|
||||||
|
|
||||||
BackendError llvm_create_declaration(LLVMModuleRef llvm_module, LLVMBuilderRef llvm_builder, GemstoneDeclRef gem_decl, LLVMValueRef* llvm_decl);
|
|
||||||
|
|
||||||
#endif // LLVM_DECL_VAR_H_
|
|
|
@ -1,134 +0,0 @@
|
||||||
#include <llvm/types/scope.h>
|
|
||||||
#include <ast/ast.h>
|
|
||||||
#include <codegen/backend.h>
|
|
||||||
#include <llvm-c/Core.h>
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
#include <llvm/expr/build.h>
|
|
||||||
|
|
||||||
BackendError llvm_build_arithmetic_operation(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, enum AST_SyntaxElement_t operation, LLVMValueRef* yield) {
|
|
||||||
AST_NODE_PTR expr_lhs = AST_get_node(expr_node, 0);
|
|
||||||
AST_NODE_PTR expr_rhs = AST_get_node(expr_node, 1);
|
|
||||||
|
|
||||||
LLVMValueRef llvm_lhs = NULL;
|
|
||||||
LLVMValueRef llvm_rhs = NULL;
|
|
||||||
BackendError err;
|
|
||||||
|
|
||||||
err = llvm_build_expression(builder, scope, module, expr_lhs, &llvm_lhs);
|
|
||||||
if (err.kind != Success)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = llvm_build_expression(builder, scope, module, expr_rhs, &llvm_rhs);
|
|
||||||
if (err.kind != Success)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
switch (operation) {
|
|
||||||
case AST_Add:
|
|
||||||
*yield = LLVMBuildAdd(builder, llvm_lhs, llvm_rhs, "Addition");
|
|
||||||
break;
|
|
||||||
case AST_Sub:
|
|
||||||
*yield = LLVMBuildSub(builder, llvm_lhs, llvm_rhs, "Subtraction");
|
|
||||||
break;
|
|
||||||
case AST_Mul:
|
|
||||||
*yield = LLVMBuildMul(builder, llvm_lhs, llvm_rhs, "Multiplication");
|
|
||||||
break;
|
|
||||||
case AST_Div:
|
|
||||||
*yield = LLVMBuildSDiv(builder, llvm_lhs, llvm_rhs, "Division");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new_backend_impl_error(Implementation, expr_node, "invalid arithmetic operation");
|
|
||||||
}
|
|
||||||
|
|
||||||
BackendError llvm_build_relational_operation(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, enum AST_SyntaxElement_t operation, LLVMValueRef* yield) {
|
|
||||||
AST_NODE_PTR expr_lhs = AST_get_node(expr_node, 0);
|
|
||||||
AST_NODE_PTR expr_rhs = AST_get_node(expr_node, 1);
|
|
||||||
|
|
||||||
LLVMValueRef llvm_lhs = NULL;
|
|
||||||
LLVMValueRef llvm_rhs = NULL;
|
|
||||||
BackendError err;
|
|
||||||
|
|
||||||
err = llvm_build_expression(builder, scope, module, expr_lhs, &llvm_lhs);
|
|
||||||
if (err.kind != Success)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = llvm_build_expression(builder, scope, module, expr_rhs, &llvm_rhs);
|
|
||||||
if (err.kind != Success)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
// TODO: make a difference between SignedInt, UnsignedInt and Float
|
|
||||||
switch (operation) {
|
|
||||||
case AST_Eq:
|
|
||||||
*yield = LLVMBuildICmp(builder, LLVMIntEQ, llvm_lhs, llvm_rhs, "Equal");
|
|
||||||
break;
|
|
||||||
case AST_Greater:
|
|
||||||
*yield = LLVMBuildICmp(builder, LLVMIntSGT, llvm_lhs, llvm_rhs, "Greater");
|
|
||||||
break;
|
|
||||||
case AST_Less:
|
|
||||||
*yield = LLVMBuildICmp(builder, LLVMIntSLT, llvm_lhs, llvm_rhs, "Less");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new_backend_impl_error(Implementation, expr_node, "invalid arithmetic operation");
|
|
||||||
}
|
|
||||||
|
|
||||||
BackendError llvm_build_expression(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, LLVMValueRef* yield) {
|
|
||||||
|
|
||||||
switch (expr_node->kind) {
|
|
||||||
case AST_Ident: {
|
|
||||||
AST_NODE_PTR variable_name = AST_get_node(expr_node, 0);
|
|
||||||
GemstoneDeclRef decl = type_scope_get_variable(scope, variable_name->value);
|
|
||||||
*yield = decl->llvm_value;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AST_Int: {
|
|
||||||
AST_NODE_PTR constant = AST_get_node(expr_node, 0);
|
|
||||||
// TODO: type annotation needed
|
|
||||||
*yield = LLVMConstIntOfString(LLVMInt32Type(), constant->value, 10);
|
|
||||||
}
|
|
||||||
case AST_Float: {
|
|
||||||
AST_NODE_PTR constant = AST_get_node(expr_node, 0);
|
|
||||||
// TODO: type annotation needed
|
|
||||||
*yield = LLVMConstRealOfString(LLVMFloatType(), constant->value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AST_Add:
|
|
||||||
case AST_Sub:
|
|
||||||
case AST_Mul:
|
|
||||||
case AST_Div: {
|
|
||||||
BackendError err = llvm_build_arithmetic_operation(builder, scope, module, expr_node, expr_node->kind, yield);
|
|
||||||
if (err.kind != Success)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
case AST_Eq:
|
|
||||||
case AST_Greater:
|
|
||||||
case AST_Less: {
|
|
||||||
BackendError err = llvm_build_relational_operation(builder, scope, module, expr_node, expr_node->kind, yield);
|
|
||||||
if (err.kind != Success)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
BackendError llvm_build_expression_list(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR exprlist_node, LLVMValueRef** yields) {
|
|
||||||
|
|
||||||
if (exprlist_node->kind != AST_ExprList) {
|
|
||||||
return new_backend_impl_error(Implementation, exprlist_node, "expected expression list");
|
|
||||||
}
|
|
||||||
|
|
||||||
*yields = malloc(sizeof(LLVMValueRef) * exprlist_node->child_count);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < exprlist_node->child_count; i++) {
|
|
||||||
AST_NODE_PTR expr = AST_get_node(exprlist_node, 0);
|
|
||||||
|
|
||||||
llvm_build_expression(builder, scope, module, expr, *yields + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
|
|
||||||
#ifndef LLVM_EXPR_BUILD_H_
|
|
||||||
#define LLVM_EXPR_BUILD_H_
|
|
||||||
|
|
||||||
#include "codegen/backend.h"
|
|
||||||
#include "llvm/types/scope.h"
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
|
|
||||||
BackendError llvm_build_expression(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, LLVMValueRef* yield);
|
|
||||||
|
|
||||||
BackendError llvm_build_expression_list(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, LLVMValueRef** yields);
|
|
||||||
|
|
||||||
#endif // LLVM_EXPR_BUILD_H_
|
|
|
@ -1,31 +0,0 @@
|
||||||
|
|
||||||
#ifndef LLVM_TYPES_FUNCTION_TYPES_H_
|
|
||||||
#define LLVM_TYPES_FUNCTION_TYPES_H_
|
|
||||||
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
#include <llvm/types/structs.h>
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
enum IO_Qualifier_t {
|
|
||||||
Unspec,
|
|
||||||
In,
|
|
||||||
Out,
|
|
||||||
InOut
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct GemstoneParam_t {
|
|
||||||
const char* name;
|
|
||||||
enum IO_Qualifier_t qualifier;
|
|
||||||
GemstoneTypeRef typename;
|
|
||||||
} GemstoneParam;
|
|
||||||
|
|
||||||
typedef struct GemstoneFun_t {
|
|
||||||
const char* name;
|
|
||||||
GArray* params;
|
|
||||||
LLVMTypeRef llvm_signature;
|
|
||||||
LLVMValueRef llvm_function;
|
|
||||||
} GemstoneFun;
|
|
||||||
|
|
||||||
typedef GemstoneFun* GemstoneFunRef;
|
|
||||||
|
|
||||||
#endif // LLVM_TYPES_FUNCTION_TYPES_H_
|
|
|
@ -1,159 +0,0 @@
|
||||||
|
|
||||||
#include "codegen/backend.h"
|
|
||||||
#include "llvm/function/function-types.h"
|
|
||||||
#include "llvm/stmt/build.h"
|
|
||||||
#include <ast/ast.h>
|
|
||||||
#include <llvm-c/Core.h>
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
#include <llvm/types/scope.h>
|
|
||||||
#include <llvm/function/function.h>
|
|
||||||
#include <llvm/types/type.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
static enum IO_Qualifier_t io_qualifier_from_string(const char* str) {
|
|
||||||
if (strcmp(str, "in") == 0) {
|
|
||||||
return In;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum IO_Qualifier_t merge_qualifier(enum IO_Qualifier_t a, enum IO_Qualifier_t b) {
|
|
||||||
enum IO_Qualifier_t result = Unspec;
|
|
||||||
|
|
||||||
if (a == In && b == Out) {
|
|
||||||
result = InOut;
|
|
||||||
} else if (a == Out && b == In) {
|
|
||||||
result = InOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum IO_Qualifier_t io_qualifier_from_ast_list(const AST_NODE_PTR node) {
|
|
||||||
// node is expected to be a list
|
|
||||||
if (node->kind != AST_List) {
|
|
||||||
PANIC("Node must be of type AST_List: %s", AST_node_to_string(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
enum IO_Qualifier_t qualifier = Unspec;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < node->child_count; i++) {
|
|
||||||
|
|
||||||
AST_NODE_PTR qualifier_node = AST_get_node(node, i);
|
|
||||||
|
|
||||||
if (qualifier_node->kind != AST_Qualifyier) {
|
|
||||||
PANIC("Node must be of type AST_Qualifyier: %s", AST_node_to_string(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
enum IO_Qualifier_t local_qualifier = io_qualifier_from_string(qualifier_node->value);
|
|
||||||
|
|
||||||
if (qualifier == Unspec) {
|
|
||||||
qualifier = local_qualifier;
|
|
||||||
} else {
|
|
||||||
qualifier = merge_qualifier(qualifier, local_qualifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qualifier == Unspec)
|
|
||||||
qualifier = In;
|
|
||||||
|
|
||||||
return qualifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
GemstoneParam param_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node) {
|
|
||||||
GemstoneParam param;
|
|
||||||
|
|
||||||
// node is expected to be a parameter
|
|
||||||
if (node->kind != AST_Parameter) {
|
|
||||||
PANIC("Node must be of type AST_ParamList: %s", AST_node_to_string(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
AST_NODE_PTR qualifier_list = AST_get_node(node, 0);
|
|
||||||
param.qualifier = io_qualifier_from_ast_list(qualifier_list);
|
|
||||||
|
|
||||||
AST_NODE_PTR param_decl = AST_get_node(node, 1);
|
|
||||||
AST_NODE_PTR param_type = AST_get_node(param_decl, 0);
|
|
||||||
param.typename = get_type_from_ast(scope, param_type);
|
|
||||||
param.name = AST_get_node(param_decl, 1)->value;
|
|
||||||
|
|
||||||
return param;
|
|
||||||
}
|
|
||||||
|
|
||||||
GemstoneFunRef fun_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node) {
|
|
||||||
if (node->kind != AST_Fun) {
|
|
||||||
PANIC("Node must be of type AST_Fun: %s", AST_node_to_string(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
GemstoneFunRef function = malloc(sizeof(GemstoneFun));
|
|
||||||
function->name = AST_get_node(node, 0)->value;
|
|
||||||
function->params = g_array_new(FALSE, FALSE, sizeof(GemstoneParam));
|
|
||||||
|
|
||||||
AST_NODE_PTR list = AST_get_node(node, 1);
|
|
||||||
for (size_t i = 0; i < list->child_count; i++) {
|
|
||||||
AST_NODE_PTR param_list = AST_get_node(list, i);
|
|
||||||
|
|
||||||
for (size_t k = 0; k < param_list->child_count; k++) {
|
|
||||||
AST_NODE_PTR param = AST_get_node(param_list, k);
|
|
||||||
|
|
||||||
GemstoneParam par = param_from_ast(scope, param);
|
|
||||||
|
|
||||||
g_array_append_val(function->params, par);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: parse function body
|
|
||||||
return function;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fun_delete(const GemstoneFunRef fun) {
|
|
||||||
g_array_free(fun->params, TRUE);
|
|
||||||
free(fun);
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMTypeRef llvm_generate_function_signature(LLVMContextRef context, GemstoneFunRef function) {
|
|
||||||
unsigned int param_count = function->params->len;
|
|
||||||
|
|
||||||
LLVMTypeRef* params = malloc(sizeof(LLVMTypeRef));
|
|
||||||
|
|
||||||
for (size_t i = 0; i < param_count; i++) {
|
|
||||||
GemstoneParam* gem_param = ((GemstoneParam*) function->params->data) + i;
|
|
||||||
params[i] = llvm_type_from_gemstone_type(context, gem_param->typename);
|
|
||||||
}
|
|
||||||
|
|
||||||
return LLVMFunctionType(LLVMVoidType(), params, param_count, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BackendError llvm_generate_function_implementation(TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR node) {
|
|
||||||
LLVMContextRef context = LLVMGetModuleContext(module);
|
|
||||||
GemstoneFunRef gemstone_signature = fun_from_ast(scope, node);
|
|
||||||
|
|
||||||
gemstone_signature->llvm_signature = llvm_generate_function_signature(context, gemstone_signature);
|
|
||||||
gemstone_signature->llvm_function = LLVMAddFunction(module, gemstone_signature->name, gemstone_signature->llvm_signature);
|
|
||||||
|
|
||||||
type_scope_add_fun(scope, gemstone_signature);
|
|
||||||
|
|
||||||
LLVMBasicBlockRef llvm_body = LLVMAppendBasicBlock(gemstone_signature->llvm_function, "body");
|
|
||||||
LLVMBuilderRef llvm_builder = LLVMCreateBuilderInContext(context);
|
|
||||||
LLVMPositionBuilderAtEnd(llvm_builder, llvm_body);
|
|
||||||
|
|
||||||
// create new function local scope
|
|
||||||
TypeScopeRef local_scope = type_scope_new();
|
|
||||||
size_t local_scope_idx = type_scope_append_scope(scope, local_scope);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < node->child_count; i++) {
|
|
||||||
AST_NODE_PTR child_node = AST_get_node(node, i);
|
|
||||||
if (child_node->kind == AST_StmtList) {
|
|
||||||
llvm_build_statement_list(llvm_builder, local_scope, module, child_node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// automatic return at end of function
|
|
||||||
LLVMBuildRetVoid(llvm_builder);
|
|
||||||
|
|
||||||
// dispose function local scope
|
|
||||||
type_scope_remove_scope(scope, local_scope_idx);
|
|
||||||
type_scope_delete(local_scope);
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
|
|
||||||
#ifndef LLVM_FUNCTION_H_
|
|
||||||
#define LLVM_FUNCTION_H_
|
|
||||||
|
|
||||||
#include <codegen/backend.h>
|
|
||||||
#include <ast/ast.h>
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
#include <llvm/function/function-types.h>
|
|
||||||
#include <llvm/types/scope.h>
|
|
||||||
#include <llvm-c/Core.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert an AST node into a function parameter struct
|
|
||||||
*
|
|
||||||
* @param node the node starting a function parameter
|
|
||||||
* @return GemstoneParam
|
|
||||||
*/
|
|
||||||
GemstoneParam param_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert an AST node into a function
|
|
||||||
*
|
|
||||||
* @param node the node starting a function
|
|
||||||
* @return GemstoneFunRef
|
|
||||||
*/
|
|
||||||
GemstoneFunRef fun_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Delete the given function
|
|
||||||
*
|
|
||||||
* @param fun
|
|
||||||
*/
|
|
||||||
void fun_delete(const GemstoneFunRef fun);
|
|
||||||
|
|
||||||
LLVMTypeRef llvm_generate_function_signature(LLVMContextRef context, GemstoneFunRef function);
|
|
||||||
|
|
||||||
BackendError llvm_generate_function_implementation(TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR body);
|
|
||||||
|
|
||||||
#endif // LLVM_FUNCTION_H_
|
|
|
@ -1,89 +0,0 @@
|
||||||
|
|
||||||
#include "llvm/function/function-types.h"
|
|
||||||
#include <codegen/backend.h>
|
|
||||||
#include <llvm-c/Core.h>
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
#include <llvm/decl/variable.h>
|
|
||||||
#include <llvm/types/scope.h>
|
|
||||||
#include <ast/ast.h>
|
|
||||||
#include <llvm/stmt/build.h>
|
|
||||||
#include <llvm/expr/build.h>
|
|
||||||
#include <sys/log.h>
|
|
||||||
|
|
||||||
BackendError llvm_build_statement(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR stmt_node) {
|
|
||||||
switch (stmt_node->kind) {
|
|
||||||
case AST_Decl: {
|
|
||||||
GArray* decls = declaration_from_ast(scope, stmt_node);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < decls->len; i++) {
|
|
||||||
GemstoneDeclRef decl = ((GemstoneDeclRef*) decls->data)[i];
|
|
||||||
|
|
||||||
BackendError err = llvm_create_declaration(module, builder, decl, &decl->llvm_value);
|
|
||||||
|
|
||||||
if (err.kind != Success)
|
|
||||||
break;
|
|
||||||
|
|
||||||
type_scope_add_variable(scope, decl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: make sure all decls are freed later
|
|
||||||
g_array_free(decls, FALSE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AST_Assign: {
|
|
||||||
AST_NODE_PTR variable_name = AST_get_node(stmt_node, 0);
|
|
||||||
AST_NODE_PTR expression = AST_get_node(stmt_node, 1);
|
|
||||||
|
|
||||||
LLVMValueRef yield = NULL;
|
|
||||||
BackendError err = llvm_build_expression(builder, scope, module, expression, &yield);
|
|
||||||
|
|
||||||
GemstoneDeclRef variable = type_scope_get_variable(scope, variable_name->value);
|
|
||||||
|
|
||||||
LLVMBuildStore(builder, yield, variable->llvm_value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AST_Stmt:
|
|
||||||
llvm_build_statement(builder, scope, module, stmt_node);
|
|
||||||
break;
|
|
||||||
case AST_Call: {
|
|
||||||
AST_NODE_PTR name = AST_get_node(stmt_node, 0);
|
|
||||||
AST_NODE_PTR expr_list = AST_get_node_by_kind(stmt_node, AST_ExprList);
|
|
||||||
GemstoneFunRef function_signature = type_scope_get_fun_from_name(scope, name->value);
|
|
||||||
size_t arg_count = function_signature->params->len;
|
|
||||||
|
|
||||||
LLVMValueRef* args = NULL;
|
|
||||||
BackendError err = llvm_build_expression_list(builder, scope, module, expr_list, &args);
|
|
||||||
|
|
||||||
LLVMBuildCall2(builder, function_signature->llvm_signature, function_signature->llvm_function, args, arg_count, name->value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AST_Def:
|
|
||||||
// TODO: implement definition
|
|
||||||
break;
|
|
||||||
case AST_While:
|
|
||||||
// TODO: implement while
|
|
||||||
break;
|
|
||||||
case AST_If:
|
|
||||||
// TODO: implement if
|
|
||||||
break;
|
|
||||||
case AST_IfElse:
|
|
||||||
// TODO: implement else if
|
|
||||||
break;
|
|
||||||
case AST_Else:
|
|
||||||
// TODO: implement else
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERROR("Invalid AST node: %s", AST_node_to_string(stmt_node));
|
|
||||||
return new_backend_impl_error(Implementation, stmt_node, "AST is invalid");
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
BackendError llvm_build_statement_list(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR node) {
|
|
||||||
for (size_t i = 0; i < node->child_count; i++) {
|
|
||||||
AST_NODE_PTR stmt_node = AST_get_node(node, i);
|
|
||||||
|
|
||||||
llvm_build_statement(builder, scope, module, stmt_node);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#ifndef LLVM_STMT_BUILD_H_
|
|
||||||
#define LLVM_STMT_BUILD_H_
|
|
||||||
|
|
||||||
#include <llvm/types/scope.h>
|
|
||||||
#include <codegen/backend.h>
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
|
|
||||||
BackendError llvm_build_statement_list(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR node);
|
|
||||||
|
|
||||||
#endif // LLVM_STMT_BUILD_H_
|
|
|
@ -1,35 +0,0 @@
|
||||||
|
|
||||||
#ifndef LLVM_TYPES_COMPOSITE_TYPES_H_
|
|
||||||
#define LLVM_TYPES_COMPOSITE_TYPES_H_
|
|
||||||
|
|
||||||
#define BITS_PER_BYTE 8
|
|
||||||
|
|
||||||
enum Sign_t {
|
|
||||||
Signed = 1,
|
|
||||||
Unsigned = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Scale_t {
|
|
||||||
ATOM = 1,
|
|
||||||
HALF = 2,
|
|
||||||
SINGLE = 4,
|
|
||||||
DOUBLE = 8,
|
|
||||||
QUAD = 16,
|
|
||||||
OCTO = 32
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Primitive_t {
|
|
||||||
Int,
|
|
||||||
Float
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CompositeType_t {
|
|
||||||
enum Sign_t sign;
|
|
||||||
enum Scale_t scale;
|
|
||||||
enum Primitive_t prim;
|
|
||||||
} Composite;
|
|
||||||
|
|
||||||
typedef struct CompositeType_t* CompositeRef;
|
|
||||||
|
|
||||||
|
|
||||||
#endif // LLVM_TYPES_COMPOSITE_TYPES_H_
|
|
|
@ -1,163 +0,0 @@
|
||||||
|
|
||||||
#include "llvm/types/composite-types.h"
|
|
||||||
#include "llvm/types/scope.h"
|
|
||||||
#include "llvm/types/structs.h"
|
|
||||||
#include <llvm/types/composite.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
LLVMTypeRef llvm_type_from_composite(LLVMContextRef context, const CompositeRef composite) {
|
|
||||||
DEBUG("converting composite to LLVM type...");
|
|
||||||
|
|
||||||
LLVMTypeRef type = INVALID_COMPOSITE;
|
|
||||||
|
|
||||||
if (composite->prim == Int) {
|
|
||||||
DEBUG("generating integer LLVM type...");
|
|
||||||
|
|
||||||
type = LLVMIntTypeInContext(context, composite->scale * BITS_PER_BYTE);
|
|
||||||
} else if (composite->prim == Float && composite->sign == Signed) {
|
|
||||||
DEBUG("generating float LLVM type...");
|
|
||||||
|
|
||||||
switch (composite->scale) {
|
|
||||||
case HALF:
|
|
||||||
type = LLVMHalfTypeInContext(context);
|
|
||||||
break;
|
|
||||||
case SINGLE:
|
|
||||||
type = LLVMDoubleTypeInContext(context);
|
|
||||||
break;
|
|
||||||
case DOUBLE:
|
|
||||||
type = LLVMDoubleTypeInContext(context);
|
|
||||||
break;
|
|
||||||
case QUAD:
|
|
||||||
type = LLVMFP128TypeInContext(context);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERROR("Floating point of precision: %ld npt supported", composite->scale);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
double get_scale_factor(const char* keyword) {
|
|
||||||
if (strcmp(keyword, "half") == 0 || strcmp(keyword, "short") == 0) {
|
|
||||||
return 0.5;
|
|
||||||
} else if (strcmp(keyword, "double") == 0 || strcmp(keyword, "long") == 0) {
|
|
||||||
return 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PANIC("invalid scale factor: %s", keyword);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Scale_t collapse_scale_list(const AST_NODE_PTR list, double base) {
|
|
||||||
double sum = base;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < list->child_count; i++) {
|
|
||||||
AST_NODE_PTR scale = AST_get_node(list, i);
|
|
||||||
|
|
||||||
sum *= get_scale_factor(scale->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sum >= 1.0 && sum <= 32) {
|
|
||||||
return (enum Scale_t) sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
PANIC("invalid combination of scale factors");
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Sign_t string_to_sign(const char* keyword) {
|
|
||||||
if (strcmp(keyword, "signed") == 0) {
|
|
||||||
return Signed;
|
|
||||||
} else if (strcmp(keyword, "unsigned") == 0) {
|
|
||||||
return Unsigned;
|
|
||||||
}
|
|
||||||
|
|
||||||
PANIC("invalid sign: %s", keyword);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum Primitive_t resolve_primitive(const char* typename) {
|
|
||||||
|
|
||||||
if (strcmp(typename, "int") == 0) {
|
|
||||||
return Int;
|
|
||||||
} else if (strcmp(typename, "float") == 0) {
|
|
||||||
return Float;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: implement lookup of ident type
|
|
||||||
return Int;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CompositeType_t ast_type_to_composite(const TypeScopeRef scope, AST_NODE_PTR type) {
|
|
||||||
size_t count = type->child_count;
|
|
||||||
|
|
||||||
struct CompositeType_t composite;
|
|
||||||
composite.prim = Int;
|
|
||||||
composite.scale = SINGLE;
|
|
||||||
composite.sign = Signed;
|
|
||||||
|
|
||||||
if (count == 1) {
|
|
||||||
const char* typename = AST_get_node(type, 0)->value;
|
|
||||||
GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename);
|
|
||||||
|
|
||||||
if (known_type == NULL) {
|
|
||||||
// only other type given
|
|
||||||
composite.prim = resolve_primitive(typename);
|
|
||||||
} else if (known_type->type->kind == TypeComposite) {
|
|
||||||
return known_type->type->specs.composite;
|
|
||||||
} else {
|
|
||||||
PANIC("not a composite");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (count == 2) {
|
|
||||||
// either scale and type
|
|
||||||
// or sign and type
|
|
||||||
AST_NODE_PTR first_child = AST_get_node(type, 0);
|
|
||||||
|
|
||||||
const char* typename = AST_get_node(type, 1)->value;
|
|
||||||
GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename);
|
|
||||||
|
|
||||||
if (known_type == NULL) {
|
|
||||||
// only other type given
|
|
||||||
composite.prim = resolve_primitive(typename);
|
|
||||||
} else if (known_type->type->kind == TypeComposite) {
|
|
||||||
composite.prim = known_type->type->specs.composite.prim;
|
|
||||||
composite.scale = known_type->type->specs.composite.scale;
|
|
||||||
composite.sign = known_type->type->specs.composite.sign;
|
|
||||||
} else {
|
|
||||||
PANIC("not a composite");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (first_child->kind) {
|
|
||||||
case AST_List:
|
|
||||||
composite.scale = collapse_scale_list(first_child, (double) composite.scale);
|
|
||||||
break;
|
|
||||||
case AST_Sign:
|
|
||||||
composite.sign = string_to_sign(first_child->value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PANIC("unexpected node kind: %s", AST_node_to_string(first_child));
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (count == 3) {
|
|
||||||
const char* typename = AST_get_node(type, 2)->value;
|
|
||||||
GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename);
|
|
||||||
|
|
||||||
if (known_type == NULL) {
|
|
||||||
// only other type given
|
|
||||||
composite.prim = resolve_primitive(typename);
|
|
||||||
} else if (known_type->type->kind == TypeComposite) {
|
|
||||||
composite.prim = known_type->type->specs.composite.prim;
|
|
||||||
composite.scale = known_type->type->specs.composite.scale;
|
|
||||||
composite.sign = known_type->type->specs.composite.sign;
|
|
||||||
} else {
|
|
||||||
PANIC("not a composite");
|
|
||||||
}
|
|
||||||
|
|
||||||
// sign, scale and type
|
|
||||||
composite.sign = string_to_sign(AST_get_node(type, 0)->value);
|
|
||||||
composite.scale = collapse_scale_list(AST_get_node(type, 1), (double) composite.scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
return composite;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
|
|
||||||
#ifndef LLVM_TYPE_H_
|
|
||||||
#define LLVM_TYPE_H_
|
|
||||||
|
|
||||||
#include <ast/ast.h>
|
|
||||||
#include <sys/log.h>
|
|
||||||
#include <llvm-c/Core.h>
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
#include <llvm/types/composite-types.h>
|
|
||||||
#include <llvm/types/scope.h>
|
|
||||||
|
|
||||||
#define INVALID_COMPOSITE NULL
|
|
||||||
|
|
||||||
LLVMTypeRef llvm_type_from_composite(LLVMContextRef context, const CompositeRef composite);
|
|
||||||
|
|
||||||
struct CompositeType_t ast_type_to_composite(const TypeScopeRef scope, AST_NODE_PTR type);
|
|
||||||
|
|
||||||
#endif // LLVM_TYPE_H_
|
|
|
@ -1,119 +0,0 @@
|
||||||
|
|
||||||
#include <llvm/decl/variable.h>
|
|
||||||
#include <llvm/function/function-types.h>
|
|
||||||
#include <llvm/types/scope.h>
|
|
||||||
#include <llvm/types/type.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct TypeScope_t {
|
|
||||||
GArray *types;
|
|
||||||
GArray *scopes;
|
|
||||||
GArray *funcs;
|
|
||||||
GHashTable *vars;
|
|
||||||
TypeScopeRef parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
TypeScopeRef type_scope_new() {
|
|
||||||
TypeScopeRef scope = malloc(sizeof(TypeScope));
|
|
||||||
|
|
||||||
// neither zero termination no initialisazion to zero needed
|
|
||||||
scope->scopes = g_array_new(FALSE, FALSE, sizeof(TypeScopeRef));
|
|
||||||
scope->types = g_array_new(FALSE, FALSE, sizeof(GemstoneTypedefRef));
|
|
||||||
scope->funcs = g_array_new(FALSE, FALSE, sizeof(GemstoneFunRef));
|
|
||||||
scope->vars = g_hash_table_new(g_str_hash, g_str_equal);
|
|
||||||
scope->parent = NULL;
|
|
||||||
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
void type_scope_append_type(TypeScopeRef scope, GemstoneTypedefRef type) {
|
|
||||||
g_array_append_val(scope->types, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child) {
|
|
||||||
child->parent = scope;
|
|
||||||
g_array_append_val(scope->scopes, child);
|
|
||||||
|
|
||||||
return scope->scopes->len - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void type_scope_remove_scope(TypeScopeRef scope, size_t index) {
|
|
||||||
g_array_remove_index(scope->scopes, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
GemstoneTypedefRef type_scope_get_type(TypeScopeRef scope, size_t index) {
|
|
||||||
return ((GemstoneTypedefRef *)scope->types->data)[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t type_scope_types_len(TypeScopeRef scope) { return scope->types->len; }
|
|
||||||
|
|
||||||
size_t type_scope_scopes_len(TypeScopeRef scope) { return scope->scopes->len; }
|
|
||||||
|
|
||||||
GemstoneTypedefRef type_scope_get_type_from_name(TypeScopeRef scope,
|
|
||||||
const char *name) {
|
|
||||||
for (guint i = 0; i < scope->types->len; i++) {
|
|
||||||
GemstoneTypedefRef typeref = ((GemstoneTypedefRef *)scope->types->data)[i];
|
|
||||||
|
|
||||||
if (strcmp(typeref->name, name) == 0) {
|
|
||||||
return typeref;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scope->parent == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return type_scope_get_type_from_name(scope->parent, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void type_scope_delete(TypeScopeRef scope) {
|
|
||||||
|
|
||||||
for (guint i = 0; i < scope->scopes->len; i++) {
|
|
||||||
TypeScopeRef scoperef = ((TypeScopeRef *)scope->scopes->data)[i];
|
|
||||||
type_scope_delete(scoperef);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (guint i = 0; i < scope->types->len; i++) {
|
|
||||||
// TODO: free gemstone type
|
|
||||||
}
|
|
||||||
|
|
||||||
g_array_free(scope->scopes, TRUE);
|
|
||||||
g_array_free(scope->types, TRUE);
|
|
||||||
g_array_free(scope->funcs, TRUE);
|
|
||||||
g_hash_table_destroy(scope->vars);
|
|
||||||
|
|
||||||
free(scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
void type_scope_add_variable(TypeScopeRef scope, GemstoneDeclRef decl) {
|
|
||||||
g_hash_table_insert(scope->vars, (gpointer)decl->name, decl);
|
|
||||||
}
|
|
||||||
|
|
||||||
GemstoneDeclRef type_scope_get_variable(TypeScopeRef scope, const char *name) {
|
|
||||||
if (g_hash_table_contains(scope->vars, name)) {
|
|
||||||
return g_hash_table_lookup(scope->vars, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void type_scope_add_fun(TypeScopeRef scope, GemstoneFunRef function) {
|
|
||||||
g_array_append_val(scope->funcs, function);
|
|
||||||
}
|
|
||||||
|
|
||||||
GemstoneFunRef type_scope_get_fun_from_name(TypeScopeRef scope,
|
|
||||||
const char *name) {
|
|
||||||
for (guint i = 0; i < scope->funcs->len; i++) {
|
|
||||||
GemstoneFunRef funref = ((GemstoneFunRef *)scope->funcs->data)[i];
|
|
||||||
|
|
||||||
if (strcmp(funref->name, name) == 0) {
|
|
||||||
return funref;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scope->parent == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return type_scope_get_fun_from_name(scope->parent, name);
|
|
||||||
}
|
|
|
@ -1,132 +0,0 @@
|
||||||
|
|
||||||
#ifndef LLVM_TYPE_SCOPE_H_
|
|
||||||
#define LLVM_TYPE_SCOPE_H_
|
|
||||||
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
#include <llvm/function/function-types.h>
|
|
||||||
#include <glib.h>
|
|
||||||
#include <llvm/types/structs.h>
|
|
||||||
|
|
||||||
typedef enum StorageQualifier_t {
|
|
||||||
StorageQualifierLocal,
|
|
||||||
StorageQualifierStatic,
|
|
||||||
StorageQualifierGlobal
|
|
||||||
} StorageQualifier;
|
|
||||||
|
|
||||||
// Varaible declaration
|
|
||||||
typedef struct GemstoneDecl_t {
|
|
||||||
const char* name;
|
|
||||||
StorageQualifier storageQualifier;
|
|
||||||
GemstoneTypeRef type;
|
|
||||||
LLVMValueRef llvm_value;
|
|
||||||
} GemstoneDecl;
|
|
||||||
|
|
||||||
typedef GemstoneDecl* GemstoneDeclRef;
|
|
||||||
|
|
||||||
typedef struct TypeScope_t TypeScope;
|
|
||||||
|
|
||||||
typedef TypeScope* TypeScopeRef;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Allocate a new type scope
|
|
||||||
*
|
|
||||||
* @return TypeScopeRef
|
|
||||||
*/
|
|
||||||
[[nodiscard("heap allocation")]]
|
|
||||||
TypeScopeRef type_scope_new();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Add a new type to this scope
|
|
||||||
*
|
|
||||||
* @param scope
|
|
||||||
* @param type
|
|
||||||
*/
|
|
||||||
[[gnu::nonnull(1)]]
|
|
||||||
void type_scope_append_type(TypeScopeRef scope, GemstoneTypedefRef type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Add a new child scope to this scope
|
|
||||||
*
|
|
||||||
* @param scope
|
|
||||||
* @param child_scope
|
|
||||||
*/
|
|
||||||
[[gnu::nonnull(1), gnu::nonnull(2)]]
|
|
||||||
size_t type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child_scope);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remove a new child scope to this scope
|
|
||||||
*
|
|
||||||
* @param scope
|
|
||||||
* @param child_scope
|
|
||||||
*/
|
|
||||||
[[gnu::nonnull(1)]]
|
|
||||||
void type_scope_remove_scope(TypeScopeRef scope, size_t index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the type at the specified index in this scope level
|
|
||||||
*
|
|
||||||
* @param scope
|
|
||||||
* @param indx
|
|
||||||
*/
|
|
||||||
[[gnu::nonnull(1)]]
|
|
||||||
GemstoneTypedefRef type_scope_get_type(TypeScopeRef scope, size_t indx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the number of types in this scope level
|
|
||||||
*
|
|
||||||
* @param scope
|
|
||||||
* @return size_t
|
|
||||||
*/
|
|
||||||
[[gnu::nonnull(1)]]
|
|
||||||
size_t type_scope_types_len(TypeScopeRef scope);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the number of child scopes
|
|
||||||
*
|
|
||||||
* @param scope
|
|
||||||
* @return size_t
|
|
||||||
*/
|
|
||||||
[[gnu::nonnull(1)]]
|
|
||||||
size_t type_scope_scopes_len(TypeScopeRef scope);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Return a type inside this scope which matches the given name.
|
|
||||||
* @attention Returns NULL if no type by this name is found.
|
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
* @return GemstoneTypedefRef
|
|
||||||
*/
|
|
||||||
[[gnu::nonnull(1)]]
|
|
||||||
GemstoneTypedefRef type_scope_get_type_from_name(TypeScopeRef scope, const char* name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Delete the scope. Deallocates all child scopes
|
|
||||||
*
|
|
||||||
* @param scope
|
|
||||||
*/
|
|
||||||
[[gnu::nonnull(1)]]
|
|
||||||
void type_scope_delete(TypeScopeRef scope);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Add a function ot the type scope
|
|
||||||
*
|
|
||||||
* @param scope
|
|
||||||
* @param function
|
|
||||||
*/
|
|
||||||
void type_scope_add_fun(TypeScopeRef scope, GemstoneFunRef function);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Attempts to find a function by its name in the current scope
|
|
||||||
*
|
|
||||||
* @param scope
|
|
||||||
* @param name
|
|
||||||
* @return GemstoneFunRef
|
|
||||||
*/
|
|
||||||
[[gnu::nonnull(1), gnu::nonnull(2)]]
|
|
||||||
GemstoneFunRef type_scope_get_fun_from_name(TypeScopeRef scope, const char* name);
|
|
||||||
|
|
||||||
void type_scope_add_variable(TypeScopeRef scope, GemstoneDeclRef decl);
|
|
||||||
|
|
||||||
GemstoneDeclRef type_scope_get_variable(TypeScopeRef scope, const char *name);
|
|
||||||
|
|
||||||
#endif // LLVM_TYPE_SCOPE_H_
|
|
|
@ -1,36 +0,0 @@
|
||||||
|
|
||||||
#ifndef LLVM_TYPE_STRUCTS_H_
|
|
||||||
#define LLVM_TYPE_STRUCTS_H_
|
|
||||||
|
|
||||||
#include <llvm/types/composite-types.h>
|
|
||||||
|
|
||||||
enum GemstoneTypeKind_t {
|
|
||||||
TypeComposite,
|
|
||||||
TypeReference,
|
|
||||||
TypeBox
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GemstoneType_t;
|
|
||||||
|
|
||||||
typedef struct GemstoneRefType_t {
|
|
||||||
struct GemstoneType_t* type;
|
|
||||||
} GemstoneRefType;
|
|
||||||
|
|
||||||
typedef struct GemstoneType_t {
|
|
||||||
enum GemstoneTypeKind_t kind;
|
|
||||||
union GemstoneTypeSpecs_t {
|
|
||||||
Composite composite;
|
|
||||||
GemstoneRefType reference;
|
|
||||||
} specs;
|
|
||||||
} GemstoneType;
|
|
||||||
|
|
||||||
typedef GemstoneType* GemstoneTypeRef;
|
|
||||||
|
|
||||||
typedef struct GemstoneTypedef_t {
|
|
||||||
const char* name;
|
|
||||||
GemstoneTypeRef type;
|
|
||||||
} GemstoneTypedef;
|
|
||||||
|
|
||||||
typedef GemstoneTypedef* GemstoneTypedefRef;
|
|
||||||
|
|
||||||
#endif // LLVM_TYPE_STRUCTS_H_
|
|
|
@ -1,120 +0,0 @@
|
||||||
|
|
||||||
#include "llvm/types/composite-types.h"
|
|
||||||
#include "llvm/types/structs.h"
|
|
||||||
#include <llvm-c/Core.h>
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
#include <llvm/types/scope.h>
|
|
||||||
#include <llvm/types/composite.h>
|
|
||||||
#include <ast/ast.h>
|
|
||||||
#include <llvm/types/type.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
GemstoneTypeRef get_type_from_ast(const TypeScopeRef scope, const AST_NODE_PTR type_node) {
|
|
||||||
if (type_node->kind != AST_Type) {
|
|
||||||
PANIC("Node must be of type AST_Type: %s", AST_node_to_string(type_node));
|
|
||||||
}
|
|
||||||
|
|
||||||
GemstoneTypeRef type = malloc(sizeof(GemstoneType));
|
|
||||||
|
|
||||||
if (type_node->child_count > 1) {
|
|
||||||
// must be composite
|
|
||||||
type->kind = TypeComposite;
|
|
||||||
type->specs.composite = ast_type_to_composite(scope, type_node);
|
|
||||||
} else {
|
|
||||||
// either custom type or box
|
|
||||||
GemstoneTypedefRef resolved_type = type_scope_get_type_from_name(scope, AST_get_node(type_node, 0)->value);
|
|
||||||
|
|
||||||
if (resolved_type == NULL) {
|
|
||||||
type->kind = TypeComposite;
|
|
||||||
type->specs.composite = ast_type_to_composite(scope, type_node);
|
|
||||||
} else {
|
|
||||||
free(type);
|
|
||||||
type = resolved_type->type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
GemstoneTypedefRef new_typedefref(GemstoneTypeRef type, const char* name) {
|
|
||||||
GemstoneTypedefRef typedefref = malloc(sizeof(GemstoneTypedef));
|
|
||||||
|
|
||||||
typedefref->name = name;
|
|
||||||
typedefref->type = type;
|
|
||||||
|
|
||||||
return typedefref;
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete_type(GemstoneTypeRef typeref) {
|
|
||||||
switch(typeref->kind) {
|
|
||||||
case TypeReference:
|
|
||||||
delete_type(typeref->specs.reference.type);
|
|
||||||
break;
|
|
||||||
case TypeComposite:
|
|
||||||
break;
|
|
||||||
case TypeBox:
|
|
||||||
PANIC("NOT IMPLEMENTED");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(typeref);
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete_typedefref(GemstoneTypedefRef ref) {
|
|
||||||
delete_type(ref->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
GemstoneTypedefRef get_type_def_from_ast(const TypeScopeRef scope, const AST_NODE_PTR typdef) {
|
|
||||||
if (typdef->kind != AST_Typedef) {
|
|
||||||
PANIC("node must be of type AST_Typedef");
|
|
||||||
}
|
|
||||||
|
|
||||||
GemstoneTypeRef type = get_type_from_ast(scope, AST_get_node(typdef, 0));
|
|
||||||
const char* name = AST_get_node(typdef, 1)->value;
|
|
||||||
|
|
||||||
return new_typedefref(type, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMTypeRef llvm_type_from_gemstone_type(LLVMContextRef context, GemstoneTypeRef type) {
|
|
||||||
LLVMTypeRef llvmTypeRef = NULL;
|
|
||||||
|
|
||||||
switch (type->kind) {
|
|
||||||
case TypeComposite:
|
|
||||||
llvmTypeRef = llvm_type_from_composite(context, &type->specs.composite);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PANIC("NOT IMPLEMENTED");
|
|
||||||
}
|
|
||||||
|
|
||||||
return llvmTypeRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMValueRef llvm_default_value_of_composite(LLVMContextRef context, CompositeRef composite) {
|
|
||||||
LLVMTypeRef type = llvm_type_from_composite(context, composite);
|
|
||||||
LLVMValueRef value;
|
|
||||||
|
|
||||||
if (composite->prim == Int) {
|
|
||||||
value = LLVMConstInt(type, 0, 0);
|
|
||||||
} else if (composite->prim == Float) {
|
|
||||||
value = LLVMConstReal(type, 0.0);
|
|
||||||
} else {
|
|
||||||
PANIC("Invalid composite type: %d", composite->prim);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMValueRef llvm_default_value_of_type(LLVMContextRef context, GemstoneTypeRef ref) {
|
|
||||||
LLVMValueRef value = NULL;
|
|
||||||
|
|
||||||
switch (ref->kind) {
|
|
||||||
case TypeComposite:
|
|
||||||
value = llvm_default_value_of_composite(context, &ref->specs.composite);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PANIC("type not implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
|
|
||||||
#ifndef GEMSTONE_TYPE_H_
|
|
||||||
#define GEMSTONE_TYPE_H_
|
|
||||||
|
|
||||||
#include <ast/ast.h>
|
|
||||||
#include <llvm-c/Types.h>
|
|
||||||
#include <llvm/types/composite.h>
|
|
||||||
#include <llvm/types/structs.h>
|
|
||||||
#include <llvm/types/scope.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert a type declaration into a concrete type.
|
|
||||||
*
|
|
||||||
* @param type A type declaration (either identifier or composite)
|
|
||||||
* @return GemstoneType
|
|
||||||
*/
|
|
||||||
GemstoneTypeRef get_type_from_ast(const TypeScopeRef scope, const AST_NODE_PTR type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert the type definition AST into a typedef reference
|
|
||||||
*
|
|
||||||
* @param typdef
|
|
||||||
* @return GemstoneTypedefRef
|
|
||||||
*/
|
|
||||||
GemstoneTypedefRef get_type_def_from_ast(const TypeScopeRef scope, const AST_NODE_PTR typdef);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create an new typedefine reference
|
|
||||||
*
|
|
||||||
* @param type
|
|
||||||
* @param name
|
|
||||||
* @return GemstoneTypedefRef
|
|
||||||
*/
|
|
||||||
GemstoneTypedefRef new_typedefref(GemstoneTypeRef type, const char* name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create the LLVM function signature
|
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* @param type
|
|
||||||
* @return LLVMTypeRef
|
|
||||||
*/
|
|
||||||
LLVMTypeRef llvm_type_from_gemstone_type(LLVMContextRef context, GemstoneTypeRef type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Free the type definition reference and its underlying type
|
|
||||||
*
|
|
||||||
* @param ref
|
|
||||||
*/
|
|
||||||
void delete_typedefref(GemstoneTypedefRef ref);
|
|
||||||
|
|
||||||
LLVMValueRef llvm_default_value_of_type(LLVMContextRef context, GemstoneTypeRef ref);
|
|
||||||
|
|
||||||
#endif // GEMSTONE_TYPE_H_
|
|
Loading…
Reference in New Issue