added: storage expr implementation
This commit is contained in:
parent
a1b6757635
commit
dcc999abbd
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue