added: parameter access validation

This commit is contained in:
Sven Vogel 2024-07-12 17:54:38 +02:00
parent 372c14c575
commit 88e1f061d8
6 changed files with 149 additions and 52 deletions

View File

@ -387,6 +387,49 @@ BackendError impl_variable_load(LLVMBackendCompileUnit *unit, LLVMLocalScope *sc
return SUCCESS; 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, BackendError impl_address_of(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
LLVMBuilderRef builder, AddressOf* addressOf, LLVMBuilderRef builder, AddressOf* addressOf,
LLVMValueRef *llvm_result) { LLVMValueRef *llvm_result) {
@ -405,7 +448,12 @@ BackendError impl_deref(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
LLVMValueRef *llvm_result) { LLVMValueRef *llvm_result) {
BackendError err; 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; LLVMTypeRef llvm_deref_type = NULL;
err = get_type_impl(unit, scope->func_scope->global_scope, dereference->variable->result->impl.reference, &llvm_deref_type); err = get_type_impl(unit, scope->func_scope->global_scope, dereference->variable->result->impl.reference, &llvm_deref_type);
if (err.kind != Success) { if (err.kind != Success) {
@ -454,6 +502,11 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
reference, reference,
llvm_result); llvm_result);
break; break;
case ExpressionKindParameter:
err = impl_parameter_load(unit, scope, builder, expr->impl.parameter,
reference,
llvm_result);
break;
case ExpressionKindAddressOf: case ExpressionKindAddressOf:
err = impl_address_of(unit, scope, builder, &expr->impl.addressOf, err = impl_address_of(unit, scope, builder, &expr->impl.addressOf,
llvm_result); llvm_result);

View File

@ -26,7 +26,7 @@ void delete_local_scope(LLVMLocalScope* scope) {
free(scope); free(scope);
} }
static LLVMValueRef get_parameter(const LLVMFuncScope* scope, LLVMValueRef get_parameter(const LLVMFuncScope* scope,
const char* name) { const char* name) {
if (g_hash_table_contains(scope->params, name)) { if (g_hash_table_contains(scope->params, name)) {
return g_hash_table_lookup(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); 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); LLVMValueRef global_var = get_global_variable(scope->func_scope->global_scope, (char*) name);
return global_var; return global_var;
} }

View File

@ -28,6 +28,8 @@ void delete_local_scope(LLVMLocalScope*);
LLVMValueRef get_variable(const LLVMLocalScope* scope, const char* name); 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); LLVMBool is_parameter(const LLVMLocalScope* scope, const char* name);
BackendError impl_function_types(LLVMBackendCompileUnit* unit, BackendError impl_function_types(LLVMBackendCompileUnit* unit,

View File

@ -27,6 +27,10 @@ BackendError impl_storage_expr(
*storage_target = *storage_target =
get_variable(scope, expr->impl.variable->name); get_variable(scope, expr->impl.variable->name);
break; break;
case StorageExprKindParameter:
*storage_target =
get_parameter(scope->func_scope, expr->impl.parameter->name);
break;
case StorageExprKindDereference: case StorageExprKindDereference:
LLVMValueRef index = NULL; LLVMValueRef index = NULL;

View File

@ -541,6 +541,18 @@ char* type_to_string(Type* type) {
return string; 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) { int getVariableFromScope(const char *name, Variable **variable) {
assert(name != NULL); assert(name != NULL);
assert(variable != NULL); assert(variable != NULL);
@ -548,13 +560,6 @@ int getVariableFromScope(const char *name, Variable **variable) {
DEBUG("getting var from scope"); DEBUG("getting var from scope");
int found = 0; 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++) { for (size_t i = 0; i < Scope->len; i++) {
GHashTable *variable_table = g_array_index(Scope, GHashTable*, 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; 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) { Expression *createExpression(AST_NODE_PTR currentNode) {
DEBUG("create Expression"); DEBUG("create Expression");
Expression *expression = mem_alloc(MemoryNamespaceSet, sizeof(Expression)); Expression *expression = mem_alloc(MemoryNamespaceSet, sizeof(Expression));
@ -1455,23 +1468,32 @@ Expression *createExpression(AST_NODE_PTR currentNode) {
case AST_Ident: case AST_Ident:
DEBUG("find var"); DEBUG("find var");
expression->kind = ExpressionKindVariable; expression->kind = ExpressionKindVariable;
int status = getVariableFromScope(currentNode->value, &(expression->impl.variable)); int status = getVariableFromScope(currentNode->value, &expression->impl.variable);
if (status == SEMANTIC_ERROR) { if (status == SEMANTIC_ERROR) {
DEBUG("Identifier is not in current scope"); expression->kind = ExpressionKindParameter;
print_diagnostic(&currentNode->location, Error, "Variable not found"); status = getParameter(currentNode->value, &expression->impl.parameter);
return NULL; if (status == SEMANTIC_ERROR) {
} DEBUG("Identifier is not in current scope");
switch (expression->impl.variable->kind) { print_diagnostic(&currentNode->location, Error, "Unknown identifier: `%s`", currentNode->value);
case VariableKindDeclaration: return NULL;
}
if (getParameterQualifier(expression->impl.parameter) == Out) {
print_diagnostic(&currentNode->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; expression->result = expression->impl.variable->impl.declaration.type;
DEBUG("%d", expression->impl.variable->impl.declaration.type->kind); } else {
break;
case VariableKindDefinition:
expression->result = expression->impl.variable->impl.definiton.declaration.type; expression->result = expression->impl.variable->impl.definiton.declaration.type;
break; }
default:
PANIC("current Variable should not be an BoxMember");
break;
} }
break; break;
case AST_Add: 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) { int createStorageExpr(StorageExpr* expr, AST_NODE_PTR node) {
switch (node->kind) { switch (node->kind) {
case AST_Ident: case AST_Ident:
expr->kind = StorageExprKindVariable; expr->kind = StorageExprKindVariable;
int status = getVariableFromScope(node->value, &expr->impl.variable); int status = getVariableFromScope(node->value, &expr->impl.variable);
if (status == SEMANTIC_ERROR) { 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; break;
case AST_Dereference: case AST_Dereference:
expr->kind = StorageExprKindDereference; expr->kind = StorageExprKindDereference;
@ -1656,11 +1696,19 @@ int createAssign(Statement *ParentStatement, AST_NODE_PTR currentNode) {
assign.nodePtr = currentNode; assign.nodePtr = currentNode;
assign.destination = mem_alloc(MemoryNamespaceSet, sizeof(StorageExpr)); 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) { if (status == SEMANTIC_ERROR) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
if (strg_expr->kind == StorageExprKindParameter) {
if (getParameterQualifier(assign.destination->impl.parameter) == In) {
print_diagnostic(&currentNode->location, Error, "Parameter is read-only: `%s`", assign.destination->impl.parameter->name);
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) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
@ -1682,7 +1730,8 @@ int fillBlock(Block *block, AST_NODE_PTR currentNode) {
g_array_append_val(Scope, lowerScope); g_array_append_val(Scope, lowerScope);
for (size_t i = 0; i < currentNode->children->len; i++) { 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) { if (signal) {
return SEMANTIC_ERROR; 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))) { if (set_get_type_impl(AST_get_node(paramdecl, 0), &(decl.type))) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
Parameter param; Parameter* param = mem_alloc(MemoryNamespaceSet, sizeof(Parameter));
param.nodePtr = currentNode; param->nodePtr = currentNode;
param.kind = ParameterDeclarationKind; param->kind = ParameterDeclarationKind;
param.impl.declaration = decl; param->impl.declaration = decl;
param.name = AST_get_node(paramdecl, 1)->value; param->name = AST_get_node(paramdecl, 1)->value;
DEBUG("param name: %s", param.name); DEBUG("param name: %s", param->name);
g_array_append_val(Paramlist, param); g_array_append_val(Paramlist, *param);
DEBUG("create var for param"); if (g_hash_table_contains(functionParameter, param->name)) {
print_diagnostic(&param->nodePtr->location, Error, "Names of function parameters must be unique: %s", param->name);
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(&param.nodePtr->location, Error, "Names of function parameters must be unique: %s", param.name);
return SEMANTIC_ERROR; 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"); DEBUG("created param successfully");
return SEMANTIC_OK; return SEMANTIC_OK;

View File

@ -432,6 +432,7 @@ typedef enum ExpressionKind_t {
ExpressionKindTransmute, ExpressionKindTransmute,
ExpressionKindConstant, ExpressionKindConstant,
ExpressionKindVariable, ExpressionKindVariable,
ExpressionKindParameter,
ExpressionKindDereference, ExpressionKindDereference,
ExpressionKindAddressOf, ExpressionKindAddressOf,
} ExpressionKind; } ExpressionKind;
@ -446,6 +447,7 @@ typedef struct Expression_t {
Transmute transmute; Transmute transmute;
TypeValue constant; TypeValue constant;
Variable* variable; Variable* variable;
Parameter* parameter;
Dereference dereference; Dereference dereference;
AddressOf addressOf; AddressOf addressOf;
} impl; } impl;
@ -526,6 +528,7 @@ typedef struct Branch_t {
typedef enum StorageExprKind_t { typedef enum StorageExprKind_t {
StorageExprKindVariable, StorageExprKindVariable,
StorageExprKindParameter,
StorageExprKindBoxAccess, StorageExprKindBoxAccess,
StorageExprKindDereference, StorageExprKindDereference,
} StorageExprKind; } StorageExprKind;
@ -535,6 +538,7 @@ typedef struct StorageExpr_t {
Type* target_type; Type* target_type;
union StorageExprImpl { union StorageExprImpl {
Variable* variable; Variable* variable;
Parameter* parameter;
BoxAccess boxAccess; BoxAccess boxAccess;
StorageDereference dereference; StorageDereference dereference;
} impl; } impl;