added: storage expr implementation

This commit is contained in:
Sven Vogel 2024-07-02 16:17:26 +02:00
parent a1b6757635
commit dcc999abbd
5 changed files with 140 additions and 35 deletions

View File

@ -12,6 +12,56 @@
#include <assert.h>
#include <mem/cache.h>
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;
}

View File

@ -6,6 +6,7 @@
#include <set/types.h>
#include <sys/log.h>
#include <set/set.h>
#include <stdlib.h>
#include <mem/cache.h>
#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");
}

View File

@ -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");

View File

@ -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(&currentNode->location, Error, "Assignment expression has incompatible type");
return SEMANTIC_ERROR;
}
// TODO: check assignment type compatability
ParentStatement->impl.assignment = assign;
return SEMANTIC_OK;

View File

@ -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 struct Assignment_t {
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 {
StorageExpr* destination;
Expression* value;
AST_NODE_PTR nodePtr;
} Assignment;