diff --git a/src/llvm/llvm-ir/stmt.c b/src/llvm/llvm-ir/stmt.c index 21dfaf3..6a3f41a 100644 --- a/src/llvm/llvm-ir/stmt.c +++ b/src/llvm/llvm-ir/stmt.c @@ -12,6 +12,56 @@ #include #include +BackendError impl_storage_expr( + LLVMBackendCompileUnit *unit, + LLVMBuilderRef + builder, + LLVMLocalScope *scope, + const StorageExpr *expr, + LLVMValueRef* storage_target) { + + BackendError err = SUCCESS; + + switch (expr->kind) { + case StorageExprKindVariable: + *storage_target = + get_variable(scope, expr->impl.variable->name); + break; + case StorageExprKindDereference: + + LLVMValueRef index = NULL; + err = impl_expr(unit, scope, builder, expr->impl.dereference.index, false, &index); + if (err.kind != Success) { + return err; + } + + LLVMValueRef array = NULL; + err = impl_storage_expr(unit, builder, scope, expr->impl.dereference.array, &array); + if (err.kind != Success) { + return err; + } + + LLVMTypeRef deref_type = NULL; + err = get_type_impl(unit, scope->func_scope->global_scope, expr->target_type, &deref_type); + if (err.kind != Success) { + return err; + } + + if (expr->target_type->kind == TypeKindReference) { + array = LLVMBuildLoad2(builder, deref_type, array, "strg.deref.indirect-load"); + } + + *storage_target = LLVMBuildGEP2(builder, deref_type, array, &index, 1, "strg.deref"); + + break; + case StorageExprKindBoxAccess: + // TODO: resolve LLVMValueRef from BoxAccess + break; + } + + return err; +} + BackendError impl_assign_stmt( LLVMBackendCompileUnit *unit, LLVMBuilderRef @@ -20,28 +70,22 @@ BackendError impl_assign_stmt( const Assignment *assignment ) { BackendError err = SUCCESS; - DEBUG("implementing assignment for variable: %s", assignment->variable->name); + DEBUG("implementing assignment for variable: %p", assignment); LLVMValueRef llvm_value = NULL; - err = impl_expr(unit, scope, builder, assignment->value, FALSE, &llvm_value); + err = impl_expr(unit, scope, builder, assignment->value, TRUE, &llvm_value); if (err.kind != Success) { return err; } - switch (assignment->variable->kind) { - case VariableKindDeclaration: - case VariableKindDefinition: - LLVMValueRef llvm_ptr = - get_variable(scope, assignment->variable->name); - - LLVMBuildStore(builder, llvm_value, llvm_ptr - ); - break; - case VariableKindBoxMember: - // TODO: resolve LLVMValueRef from BoxAccess - break; + LLVMValueRef llvm_array = NULL; + err = impl_storage_expr(unit, builder, scope, assignment->destination, &llvm_array); + if (err.kind != Success) { + return err; } + LLVMBuildStore(builder, llvm_value, llvm_array); + return err; } diff --git a/src/llvm/llvm-ir/types.c b/src/llvm/llvm-ir/types.c index b94a1d9..e1aba0c 100644 --- a/src/llvm/llvm-ir/types.c +++ b/src/llvm/llvm-ir/types.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #define BASE_BYTES 4 @@ -45,13 +46,16 @@ BackendError impl_reference_const(LLVMBackendCompileUnit* unit, LLVMBuilderRef b // is string literal LLVMValueRef string_value = LLVMConstString(value->value, strlen(value->value), false); - char* uuid = guid(); + char uuid[9]; + sprintf(uuid, "%08x", g_str_hash(value->value)); LLVMValueRef string_global = LLVMAddGlobal(unit->module, LLVMTypeOf(string_value), uuid); LLVMSetInitializer(string_global, string_value); LLVMSetGlobalConstant(string_global, true); + LLVMSetUnnamedAddress(string_global, LLVMGlobalUnnamedAddr); + LLVMSetAlignment(string_global, 1); - *llvm_value = LLVMGetNamedGlobal(unit->module, uuid); + *llvm_value = string_global; } else { err = new_backend_impl_error(Implementation, value->nodePtr, "reference initializer can only be string literals"); } diff --git a/src/llvm/parser.c b/src/llvm/parser.c index 374b081..9f07ae8 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -221,7 +221,7 @@ static BackendError build_module(LLVMBackendCompileUnit* unit, } char* error = NULL; - if (LLVMVerifyModule(unit->module, LLVMAbortProcessAction, &error)) { + if (LLVMVerifyModule(unit->module, LLVMReturnStatusAction, &error)) { print_message(Error, "Unable to compile due to: %s", error); LLVMDisposeMessage(error); err = new_backend_impl_error(Implementation, NULL, "LLVM backend verification error, see stdout"); diff --git a/src/set/set.c b/src/set/set.c index 666eac4..47a6bec 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -1610,17 +1610,60 @@ bool compareTypes(Type *leftType, Type *rightType) { return FALSE; } +Type* getVariableType(Variable* variable) { + if (variable->kind == VariableKindDeclaration) { + return variable->impl.declaration.type; + } else { + return variable->impl.definiton.declaration.type; + } +} + +int createStorageExpr(StorageExpr* expr, AST_NODE_PTR node) { + switch (node->kind) { + case AST_Ident: + expr->kind = StorageExprKindVariable; + int status = getVariableFromScope(node->value, &expr->impl.variable); + if (status == SEMANTIC_ERROR) { + return SEMANTIC_ERROR; + } + expr->target_type = getVariableType(expr->impl.variable); + break; + case AST_Dereference: + expr->kind = StorageExprKindDereference; + + AST_NODE_PTR array_node = AST_get_node(node, 0); + AST_NODE_PTR index_node = AST_get_node(node, 1); + + expr->impl.dereference.index = createExpression(index_node); + expr->impl.dereference.array = mem_alloc(MemoryNamespaceSet, sizeof(StorageExpr)); + if (createStorageExpr(expr->impl.dereference.array, array_node) == SEMANTIC_ERROR){ + return SEMANTIC_ERROR; + } + + if (expr->impl.dereference.array->target_type->kind == TypeKindReference) { + expr->target_type = expr->impl.dereference.array->target_type->impl.reference; + } else { + print_diagnostic(&array_node->location, Error, "Cannot dereference non reference type: %s", + type_to_string(expr->impl.dereference.array->target_type)); + return SEMANTIC_ERROR; + }; + break; + default: + print_message(Error, "Unimplemented"); + return SEMANTIC_ERROR; + break; + } + + return SEMANTIC_OK; +} + int createAssign(Statement *ParentStatement, AST_NODE_PTR currentNode) { DEBUG("create Assign"); Assignment assign; assign.nodePtr = currentNode; + assign.destination = mem_alloc(MemoryNamespaceSet, sizeof(StorageExpr)); - // TODO: get variable - const char *varName = AST_get_node(currentNode, 0)->value; - int status = getVariableFromScope(varName, &assign.variable); - if (status) { - return SEMANTIC_ERROR; - } + int status = createStorageExpr(assign.destination, AST_get_node(currentNode, 0)); assign.value = createExpression(AST_get_node(currentNode, 1)); if (assign.value == NULL) { @@ -1629,17 +1672,7 @@ int createAssign(Statement *ParentStatement, AST_NODE_PTR currentNode) { Type *varType = NULL; - if (assign.variable->kind == VariableKindDeclaration) { - varType = assign.variable->impl.declaration.type; - } else if (assign.variable->kind == VariableKindDefinition) { - varType = assign.variable->impl.definiton.declaration.type; - } - - bool result = compareTypes(varType, assign.value->result); - if (result == FALSE) { - print_diagnostic(¤tNode->location, Error, "Assignment expression has incompatible type"); - return SEMANTIC_ERROR; - } + // TODO: check assignment type compatability ParentStatement->impl.assignment = assign; return SEMANTIC_OK; diff --git a/src/set/types.h b/src/set/types.h index c91058b..2eb6e44 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -287,6 +287,14 @@ typedef struct Dereference_t { AST_NODE_PTR nodePtr; }Dereference; +typedef struct StorageExpr_t StorageExpr; + +typedef struct StorageDereference_t { + Expression* index; + StorageExpr* array; + AST_NODE_PTR nodePtr; +} StorageDereference; + typedef struct AddressOf_t { Expression* variable; AST_NODE_PTR node_ptr; @@ -516,8 +524,24 @@ typedef struct Branch_t { // | Statements | // '------------------------------------------------' +typedef enum StorageExprKind_t { + StorageExprKindVariable, + StorageExprKindBoxAccess, + StorageExprKindDereference, +} StorageExprKind; + +typedef struct StorageExpr_t { + StorageExprKind kind; + Type* target_type; + union StorageExprImpl { + Variable* variable; + BoxAccess boxAccess; + StorageDereference dereference; + } impl; +} StorageExpr; + typedef struct Assignment_t { - Variable* variable; + StorageExpr* destination; Expression* value; AST_NODE_PTR nodePtr; } Assignment;