added: parameter access validation
This commit is contained in:
parent
372c14c575
commit
88e1f061d8
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
119
src/set/set.c
119
src/set/set.c
|
@ -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) {
|
||||||
|
expression->kind = ExpressionKindParameter;
|
||||||
|
status = getParameter(currentNode->value, &expression->impl.parameter);
|
||||||
if (status == SEMANTIC_ERROR) {
|
if (status == SEMANTIC_ERROR) {
|
||||||
DEBUG("Identifier is not in current scope");
|
DEBUG("Identifier is not in current scope");
|
||||||
print_diagnostic(¤tNode->location, Error, "Variable not found");
|
print_diagnostic(¤tNode->location, Error, "Unknown identifier: `%s`", currentNode->value);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
switch (expression->impl.variable->kind) {
|
|
||||||
case VariableKindDeclaration:
|
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;
|
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) {
|
||||||
|
|
||||||
|
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;
|
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(¤tNode->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(¶m->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(¶m.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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue