added: storage expr implementation
This commit is contained in:
parent
a1b6757635
commit
dcc999abbd
|
@ -12,6 +12,56 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <mem/cache.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(
|
BackendError impl_assign_stmt(
|
||||||
LLVMBackendCompileUnit *unit,
|
LLVMBackendCompileUnit *unit,
|
||||||
LLVMBuilderRef
|
LLVMBuilderRef
|
||||||
|
@ -20,28 +70,22 @@ BackendError impl_assign_stmt(
|
||||||
const Assignment *assignment
|
const Assignment *assignment
|
||||||
) {
|
) {
|
||||||
BackendError err = SUCCESS;
|
BackendError err = SUCCESS;
|
||||||
DEBUG("implementing assignment for variable: %s", assignment->variable->name);
|
DEBUG("implementing assignment for variable: %p", assignment);
|
||||||
|
|
||||||
LLVMValueRef llvm_value = NULL;
|
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) {
|
if (err.kind != Success) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (assignment->variable->kind) {
|
LLVMValueRef llvm_array = NULL;
|
||||||
case VariableKindDeclaration:
|
err = impl_storage_expr(unit, builder, scope, assignment->destination, &llvm_array);
|
||||||
case VariableKindDefinition:
|
if (err.kind != Success) {
|
||||||
LLVMValueRef llvm_ptr =
|
return err;
|
||||||
get_variable(scope, assignment->variable->name);
|
|
||||||
|
|
||||||
LLVMBuildStore(builder, llvm_value, llvm_ptr
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case VariableKindBoxMember:
|
|
||||||
// TODO: resolve LLVMValueRef from BoxAccess
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLVMBuildStore(builder, llvm_value, llvm_array);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <set/types.h>
|
#include <set/types.h>
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
#include <set/set.h>
|
#include <set/set.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <mem/cache.h>
|
#include <mem/cache.h>
|
||||||
|
|
||||||
#define BASE_BYTES 4
|
#define BASE_BYTES 4
|
||||||
|
@ -45,13 +46,16 @@ BackendError impl_reference_const(LLVMBackendCompileUnit* unit, LLVMBuilderRef b
|
||||||
// is string literal
|
// is string literal
|
||||||
LLVMValueRef string_value = LLVMConstString(value->value, strlen(value->value), false);
|
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);
|
LLVMValueRef string_global = LLVMAddGlobal(unit->module, LLVMTypeOf(string_value), uuid);
|
||||||
LLVMSetInitializer(string_global, string_value);
|
LLVMSetInitializer(string_global, string_value);
|
||||||
LLVMSetGlobalConstant(string_global, true);
|
LLVMSetGlobalConstant(string_global, true);
|
||||||
|
LLVMSetUnnamedAddress(string_global, LLVMGlobalUnnamedAddr);
|
||||||
|
LLVMSetAlignment(string_global, 1);
|
||||||
|
|
||||||
*llvm_value = LLVMGetNamedGlobal(unit->module, uuid);
|
*llvm_value = string_global;
|
||||||
} else {
|
} else {
|
||||||
err = new_backend_impl_error(Implementation, value->nodePtr, "reference initializer can only be string literals");
|
err = new_backend_impl_error(Implementation, value->nodePtr, "reference initializer can only be string literals");
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,7 +221,7 @@ static BackendError build_module(LLVMBackendCompileUnit* unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
char* error = NULL;
|
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);
|
print_message(Error, "Unable to compile due to: %s", error);
|
||||||
LLVMDisposeMessage(error);
|
LLVMDisposeMessage(error);
|
||||||
err = new_backend_impl_error(Implementation, NULL, "LLVM backend verification error, see stdout");
|
err = new_backend_impl_error(Implementation, NULL, "LLVM backend verification error, see stdout");
|
||||||
|
|
|
@ -1610,17 +1610,60 @@ bool compareTypes(Type *leftType, Type *rightType) {
|
||||||
return FALSE;
|
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) {
|
int createAssign(Statement *ParentStatement, AST_NODE_PTR currentNode) {
|
||||||
DEBUG("create Assign");
|
DEBUG("create Assign");
|
||||||
Assignment assign;
|
Assignment assign;
|
||||||
assign.nodePtr = currentNode;
|
assign.nodePtr = currentNode;
|
||||||
|
assign.destination = mem_alloc(MemoryNamespaceSet, sizeof(StorageExpr));
|
||||||
|
|
||||||
// TODO: get variable
|
int status = createStorageExpr(assign.destination, AST_get_node(currentNode, 0));
|
||||||
const char *varName = AST_get_node(currentNode, 0)->value;
|
|
||||||
int status = getVariableFromScope(varName, &assign.variable);
|
|
||||||
if (status) {
|
|
||||||
return SEMANTIC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
assign.value = createExpression(AST_get_node(currentNode, 1));
|
assign.value = createExpression(AST_get_node(currentNode, 1));
|
||||||
if (assign.value == NULL) {
|
if (assign.value == NULL) {
|
||||||
|
@ -1629,17 +1672,7 @@ int createAssign(Statement *ParentStatement, AST_NODE_PTR currentNode) {
|
||||||
|
|
||||||
Type *varType = NULL;
|
Type *varType = NULL;
|
||||||
|
|
||||||
if (assign.variable->kind == VariableKindDeclaration) {
|
// TODO: check assignment type compatability
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ParentStatement->impl.assignment = assign;
|
ParentStatement->impl.assignment = assign;
|
||||||
return SEMANTIC_OK;
|
return SEMANTIC_OK;
|
||||||
|
|
|
@ -287,6 +287,14 @@ typedef struct Dereference_t {
|
||||||
AST_NODE_PTR nodePtr;
|
AST_NODE_PTR nodePtr;
|
||||||
}Dereference;
|
}Dereference;
|
||||||
|
|
||||||
|
typedef struct StorageExpr_t StorageExpr;
|
||||||
|
|
||||||
|
typedef struct StorageDereference_t {
|
||||||
|
Expression* index;
|
||||||
|
StorageExpr* array;
|
||||||
|
AST_NODE_PTR nodePtr;
|
||||||
|
} StorageDereference;
|
||||||
|
|
||||||
typedef struct AddressOf_t {
|
typedef struct AddressOf_t {
|
||||||
Expression* variable;
|
Expression* variable;
|
||||||
AST_NODE_PTR node_ptr;
|
AST_NODE_PTR node_ptr;
|
||||||
|
@ -516,8 +524,24 @@ typedef struct Branch_t {
|
||||||
// | Statements |
|
// | 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;
|
Variable* variable;
|
||||||
|
BoxAccess boxAccess;
|
||||||
|
StorageDereference dereference;
|
||||||
|
} impl;
|
||||||
|
} StorageExpr;
|
||||||
|
|
||||||
|
typedef struct Assignment_t {
|
||||||
|
StorageExpr* destination;
|
||||||
Expression* value;
|
Expression* value;
|
||||||
AST_NODE_PTR nodePtr;
|
AST_NODE_PTR nodePtr;
|
||||||
} Assignment;
|
} Assignment;
|
||||||
|
|
Loading…
Reference in New Issue