From 88e1f061d8c4a32de65a6e6e40400ca708d62820 Mon Sep 17 00:00:00 2001 From: servostar Date: Fri, 12 Jul 2024 17:54:38 +0200 Subject: [PATCH] added: parameter access validation --- src/llvm/llvm-ir/expr.c | 55 ++++++++++++++++- src/llvm/llvm-ir/func.c | 7 +-- src/llvm/llvm-ir/func.h | 2 + src/llvm/llvm-ir/stmt.c | 4 ++ src/set/set.c | 129 ++++++++++++++++++++++++++-------------- src/set/types.h | 4 ++ 6 files changed, 149 insertions(+), 52 deletions(-) diff --git a/src/llvm/llvm-ir/expr.c b/src/llvm/llvm-ir/expr.c index 254a969..5ff4e9c 100644 --- a/src/llvm/llvm-ir/expr.c +++ b/src/llvm/llvm-ir/expr.c @@ -387,6 +387,49 @@ BackendError impl_variable_load(LLVMBackendCompileUnit *unit, LLVMLocalScope *sc return SUCCESS; } +BackendError impl_parameter_load(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, + LLVMBuilderRef builder, Parameter *parameter, + LLVMBool reference, + LLVMValueRef *llvm_result) { + + LLVMValueRef llvm_variable = NULL; + if (g_hash_table_contains(scope->func_scope->params, parameter->name)) { + llvm_variable = g_hash_table_lookup(scope->func_scope->params, parameter->name); + } + + Type* type; + + ParameterDeclaration decl; + + if (parameter->kind == ParameterDeclarationKind) { + decl = parameter->impl.definiton.declaration; + } else { + decl = parameter->impl.declaration; + } + type = decl.type; + + if (llvm_variable == NULL) { + return new_backend_impl_error(Implementation, NULL, "Variable not found"); + } + + if (decl.qualifier == In) { + *llvm_result = llvm_variable; + } else { + // no referencing, load value + LLVMTypeRef llvm_type; + + get_type_impl(unit, scope->func_scope->global_scope, type, &llvm_type); + + if (LLVMGetTypeKind(LLVMTypeOf(llvm_variable)) == LLVMPointerTypeKind) { + *llvm_result = LLVMBuildLoad2(builder, llvm_type, llvm_variable, ""); + } else { + *llvm_result = llvm_variable; + } + } + + return SUCCESS; +} + BackendError impl_address_of(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, LLVMBuilderRef builder, AddressOf* addressOf, LLVMValueRef *llvm_result) { @@ -405,7 +448,12 @@ BackendError impl_deref(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, LLVMValueRef *llvm_result) { BackendError err; - LLVMValueRef llvm_pointer = get_variable(scope, dereference->variable->impl.variable->name); + LLVMValueRef llvm_pointer = NULL; + err = impl_expr(unit, scope, builder, dereference->variable, TRUE, &llvm_pointer); + if (err.kind != Success) { + return err; + } + LLVMTypeRef llvm_deref_type = NULL; err = get_type_impl(unit, scope->func_scope->global_scope, dereference->variable->result->impl.reference, &llvm_deref_type); if (err.kind != Success) { @@ -454,6 +502,11 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, reference, llvm_result); break; + case ExpressionKindParameter: + err = impl_parameter_load(unit, scope, builder, expr->impl.parameter, + reference, + llvm_result); + break; case ExpressionKindAddressOf: err = impl_address_of(unit, scope, builder, &expr->impl.addressOf, llvm_result); diff --git a/src/llvm/llvm-ir/func.c b/src/llvm/llvm-ir/func.c index 473d6ad..63d9b39 100644 --- a/src/llvm/llvm-ir/func.c +++ b/src/llvm/llvm-ir/func.c @@ -26,7 +26,7 @@ void delete_local_scope(LLVMLocalScope* scope) { free(scope); } -static LLVMValueRef get_parameter(const LLVMFuncScope* scope, +LLVMValueRef get_parameter(const LLVMFuncScope* scope, const char* name) { if (g_hash_table_contains(scope->params, name)) { return g_hash_table_lookup(scope->params, name); @@ -44,11 +44,6 @@ LLVMValueRef get_variable(const LLVMLocalScope* scope, const char* name) { return get_variable(scope->parent_scope, name); } - LLVMValueRef param = get_parameter(scope->func_scope, name); - if (param != NULL) { - return param; - } - LLVMValueRef global_var = get_global_variable(scope->func_scope->global_scope, (char*) name); return global_var; } diff --git a/src/llvm/llvm-ir/func.h b/src/llvm/llvm-ir/func.h index 5ab4621..349135a 100644 --- a/src/llvm/llvm-ir/func.h +++ b/src/llvm/llvm-ir/func.h @@ -28,6 +28,8 @@ void delete_local_scope(LLVMLocalScope*); LLVMValueRef get_variable(const LLVMLocalScope* scope, const char* name); +LLVMValueRef get_parameter(const LLVMFuncScope* scope, const char* name); + LLVMBool is_parameter(const LLVMLocalScope* scope, const char* name); BackendError impl_function_types(LLVMBackendCompileUnit* unit, diff --git a/src/llvm/llvm-ir/stmt.c b/src/llvm/llvm-ir/stmt.c index c3f8fa2..697c4b8 100644 --- a/src/llvm/llvm-ir/stmt.c +++ b/src/llvm/llvm-ir/stmt.c @@ -27,6 +27,10 @@ BackendError impl_storage_expr( *storage_target = get_variable(scope, expr->impl.variable->name); break; + case StorageExprKindParameter: + *storage_target = + get_parameter(scope->func_scope, expr->impl.parameter->name); + break; case StorageExprKindDereference: LLVMValueRef index = NULL; diff --git a/src/set/set.c b/src/set/set.c index 1ad9652..67b6b9e 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -541,6 +541,18 @@ char* type_to_string(Type* type) { return string; } +int getParameter(const char *name, Parameter **parameter) { + // loop through all variable scope and find a variable + if (functionParameter != NULL) { + if (g_hash_table_contains(functionParameter, name)) { + *parameter = g_hash_table_lookup(functionParameter, name); + return SEMANTIC_OK; + } + } + + return SEMANTIC_ERROR; +} + int getVariableFromScope(const char *name, Variable **variable) { assert(name != NULL); assert(variable != NULL); @@ -548,13 +560,6 @@ int getVariableFromScope(const char *name, Variable **variable) { DEBUG("getting var from scope"); int found = 0; - // loop through all variable scope and find a variable - if (functionParameter != NULL) { - if (g_hash_table_contains(functionParameter, name)) { - *variable = g_hash_table_lookup(functionParameter, name); - found += 1; - } - } for (size_t i = 0; i < Scope->len; i++) { GHashTable *variable_table = g_array_index(Scope, GHashTable*, i); @@ -1435,6 +1440,14 @@ int createAddressOf(Expression *ParentExpression, AST_NODE_PTR currentNode) { return SEMANTIC_OK; } +IO_Qualifier getParameterQualifier(Parameter* parameter) { + if (parameter->kind == ParameterDeclarationKind) { + return parameter->impl.declaration.qualifier; + } else { + return parameter->impl.definiton.declaration.qualifier; + } +} + Expression *createExpression(AST_NODE_PTR currentNode) { DEBUG("create Expression"); Expression *expression = mem_alloc(MemoryNamespaceSet, sizeof(Expression)); @@ -1455,23 +1468,32 @@ Expression *createExpression(AST_NODE_PTR currentNode) { case AST_Ident: DEBUG("find var"); expression->kind = ExpressionKindVariable; - int status = getVariableFromScope(currentNode->value, &(expression->impl.variable)); + int status = getVariableFromScope(currentNode->value, &expression->impl.variable); if (status == SEMANTIC_ERROR) { - DEBUG("Identifier is not in current scope"); - print_diagnostic(¤tNode->location, Error, "Variable not found"); - return NULL; - } - switch (expression->impl.variable->kind) { - case VariableKindDeclaration: + expression->kind = ExpressionKindParameter; + status = getParameter(currentNode->value, &expression->impl.parameter); + if (status == SEMANTIC_ERROR) { + DEBUG("Identifier is not in current scope"); + print_diagnostic(¤tNode->location, Error, "Unknown identifier: `%s`", currentNode->value); + return NULL; + } + + if (getParameterQualifier(expression->impl.parameter) == Out) { + print_diagnostic(¤tNode->location, Error, "Parameter is write-only: `%s`", currentNode->value); + return NULL; + } + + if (expression->impl.parameter->kind == VariableKindDeclaration) { + expression->result = expression->impl.parameter->impl.declaration.type; + } else { + expression->result = expression->impl.parameter->impl.definiton.declaration.type; + } + } else { + if (expression->impl.variable->kind == VariableKindDeclaration) { expression->result = expression->impl.variable->impl.declaration.type; - DEBUG("%d", expression->impl.variable->impl.declaration.type->kind); - break; - case VariableKindDefinition: + } else { expression->result = expression->impl.variable->impl.definiton.declaration.type; - break; - default: - PANIC("current Variable should not be an BoxMember"); - break; + } } break; case AST_Add: @@ -1611,15 +1633,33 @@ Type* getVariableType(Variable* variable) { } } +Type* getParameterType(Parameter* parameter) { + if (parameter->kind == ParameterDeclarationKind) { + return parameter->impl.declaration.type; + } else { + return parameter->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->kind = StorageExprKindParameter; + status = getParameter(node->value, &expr->impl.parameter); + if (status == SEMANTIC_ERROR) { + print_diagnostic(&node->location, Error, "Unknown token: `%s`", node->value); + return SEMANTIC_ERROR; + } else { + expr->target_type = getParameterType(expr->impl.parameter); + } + + } else { + expr->target_type = getVariableType(expr->impl.variable); } - expr->target_type = getVariableType(expr->impl.variable); break; case AST_Dereference: expr->kind = StorageExprKindDereference; @@ -1656,11 +1696,19 @@ int createAssign(Statement *ParentStatement, AST_NODE_PTR currentNode) { assign.nodePtr = currentNode; assign.destination = mem_alloc(MemoryNamespaceSet, sizeof(StorageExpr)); - int status = createStorageExpr(assign.destination, AST_get_node(currentNode, 0)); + AST_NODE_PTR strg_expr = AST_get_node(currentNode, 0); + int status = createStorageExpr(assign.destination, strg_expr); if (status == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } + if (strg_expr->kind == StorageExprKindParameter) { + if (getParameterQualifier(assign.destination->impl.parameter) == In) { + print_diagnostic(¤tNode->location, Error, "Parameter is read-only: `%s`", assign.destination->impl.parameter->name); + return SEMANTIC_ERROR; + } + } + assign.value = createExpression(AST_get_node(currentNode, 1)); if (assign.value == NULL) { return SEMANTIC_ERROR; @@ -1682,7 +1730,8 @@ int fillBlock(Block *block, AST_NODE_PTR currentNode) { g_array_append_val(Scope, lowerScope); for (size_t i = 0; i < currentNode->children->len; i++) { - int signal = createStatement(block, AST_get_node(currentNode, i)); + AST_NODE_PTR stmt_node = AST_get_node(currentNode, i); + int signal = createStatement(block, stmt_node); if (signal) { return SEMANTIC_ERROR; } @@ -2003,30 +2052,20 @@ int createParam(GArray *Paramlist, AST_NODE_PTR currentNode) { if (set_get_type_impl(AST_get_node(paramdecl, 0), &(decl.type))) { return SEMANTIC_ERROR; } - Parameter param; - param.nodePtr = currentNode; - param.kind = ParameterDeclarationKind; - param.impl.declaration = decl; - param.name = AST_get_node(paramdecl, 1)->value; + Parameter* param = mem_alloc(MemoryNamespaceSet, sizeof(Parameter)); + param->nodePtr = currentNode; + param->kind = ParameterDeclarationKind; + param->impl.declaration = decl; + param->name = AST_get_node(paramdecl, 1)->value; - DEBUG("param name: %s", param.name); - g_array_append_val(Paramlist, param); + DEBUG("param name: %s", param->name); + g_array_append_val(Paramlist, *param); - DEBUG("create var for param"); - - Variable *paramvar = mem_alloc(MemoryNamespaceSet, sizeof(Variable)); - paramvar->kind = VariableKindDeclaration; - paramvar->name = param.name; - paramvar->nodePtr = currentNode; - paramvar->impl.declaration.nodePtr = currentNode; - paramvar->impl.declaration.qualifier = Local; - paramvar->impl.declaration.type = param.impl.declaration.type; - - if (g_hash_table_contains(functionParameter, param.name)) { - print_diagnostic(¶m.nodePtr->location, Error, "Names of function parameters must be unique: %s", param.name); + if (g_hash_table_contains(functionParameter, param->name)) { + print_diagnostic(¶m->nodePtr->location, Error, "Names of function parameters must be unique: %s", param->name); return SEMANTIC_ERROR; } - g_hash_table_insert(functionParameter, (gpointer) param.name, paramvar); + g_hash_table_insert(functionParameter, (gpointer) param->name, param); DEBUG("created param successfully"); return SEMANTIC_OK; diff --git a/src/set/types.h b/src/set/types.h index 2eb6e44..b030a12 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -432,6 +432,7 @@ typedef enum ExpressionKind_t { ExpressionKindTransmute, ExpressionKindConstant, ExpressionKindVariable, + ExpressionKindParameter, ExpressionKindDereference, ExpressionKindAddressOf, } ExpressionKind; @@ -446,6 +447,7 @@ typedef struct Expression_t { Transmute transmute; TypeValue constant; Variable* variable; + Parameter* parameter; Dereference dereference; AddressOf addressOf; } impl; @@ -526,6 +528,7 @@ typedef struct Branch_t { typedef enum StorageExprKind_t { StorageExprKindVariable, + StorageExprKindParameter, StorageExprKindBoxAccess, StorageExprKindDereference, } StorageExprKind; @@ -535,6 +538,7 @@ typedef struct StorageExpr_t { Type* target_type; union StorageExprImpl { Variable* variable; + Parameter* parameter; BoxAccess boxAccess; StorageDereference dereference; } impl;