diff --git a/src/llvm/llvm-ir/expr.c b/src/llvm/llvm-ir/expr.c index 5ff4e9c..d3a3c66 100644 --- a/src/llvm/llvm-ir/expr.c +++ b/src/llvm/llvm-ir/expr.c @@ -412,7 +412,7 @@ BackendError impl_parameter_load(LLVMBackendCompileUnit *unit, LLVMLocalScope *s return new_backend_impl_error(Implementation, NULL, "Variable not found"); } - if (decl.qualifier == In) { + if (decl.qualifier == In || reference) { *llvm_result = llvm_variable; } else { // no referencing, load value diff --git a/src/llvm/llvm-ir/stmt.c b/src/llvm/llvm-ir/stmt.c index 697c4b8..edd84a1 100644 --- a/src/llvm/llvm-ir/stmt.c +++ b/src/llvm/llvm-ir/stmt.c @@ -12,6 +12,27 @@ #include #include +BackendError impl_param_load( + LLVMBackendCompileUnit *unit, + LLVMBuilderRef builder, + LLVMLocalScope *scope, + const StorageExpr *expr, + LLVMValueRef* storage_target) { + BackendError err = SUCCESS; + + if (expr->impl.parameter->impl.declaration.qualifier == Out || expr->impl.parameter->impl.declaration.qualifier == InOut) { + LLVMTypeRef llvm_type = NULL; + err = get_type_impl(unit, scope->func_scope->global_scope, expr->impl.parameter->impl.declaration.type, &llvm_type); + if (err.kind != Success) { + return err; + } + + *storage_target = LLVMBuildLoad2(builder, llvm_type, *storage_target, "strg.param.out.load"); + } + + return err; +} + BackendError impl_storage_expr( LLVMBackendCompileUnit *unit, LLVMBuilderRef @@ -45,6 +66,13 @@ BackendError impl_storage_expr( return err; } + if (expr->impl.dereference.array->kind == StorageExprKindParameter) { + err = impl_param_load(unit, builder, scope, expr->impl.dereference.array, &array); + if (err.kind != Success) { + return err; + } + } + if (expr->impl.dereference.array->kind == StorageExprKindDereference) { LLVMTypeRef deref_type = NULL; err = get_type_impl(unit, scope->func_scope->global_scope, expr->impl.dereference.array->target_type, &deref_type); @@ -216,21 +244,24 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit, param_list = call->function->impl.declaration.parameter; } - LLVMBool reference = FALSE; - Parameter parameter = g_array_index(param_list, Parameter, i); - if (is_parameter_out(¶meter)) { - reference = TRUE; - } else if (parameter.impl.declaration.type->kind == TypeKindReference) { - reference = TRUE; - } + Parameter param = g_array_index(param_list, Parameter, i); LLVMValueRef llvm_arg = NULL; - err = impl_expr(unit, scope, builder, arg, reference, &llvm_arg); + err = impl_expr(unit, scope, builder, arg, is_parameter_out(¶m), &llvm_arg); if (err.kind != Success) { break; } + if (is_parameter_out(¶m)) { + if ((arg->kind == ExpressionKindParameter && !is_parameter_out(arg->impl.parameter)) || arg->kind != ExpressionKindParameter) { + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), 0, false); + LLVMTypeRef llvm_type = NULL; + get_type_impl(unit, scope->func_scope->global_scope, param.impl.declaration.type, &llvm_type); + llvm_arg = LLVMBuildGEP2(builder, llvm_type, llvm_arg, &index, 1, ""); + } + } + arguments[i] = llvm_arg; }