aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/check_decl.cpp5
-rw-r--r--src/check_expr.cpp3
-rw-r--r--src/check_stmt.cpp3
-rw-r--r--src/checker.hpp2
-rw-r--r--src/llvm_abi.cpp4
-rw-r--r--src/llvm_backend.hpp2
-rw-r--r--src/llvm_backend_expr.cpp2
-rw-r--r--src/llvm_backend_general.cpp4
-rw-r--r--src/llvm_backend_proc.cpp76
9 files changed, 84 insertions, 17 deletions
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index bb56749af..0e41dbbb5 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -1544,8 +1544,12 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty
// NOTE(bill): Don't err here
}
+ GB_ASSERT(decl->defer_use_checked == false);
+
check_stmt_list(ctx, bs->stmts, Stmt_CheckScopeDecls);
+ decl->defer_use_checked = true;
+
for_array(i, bs->stmts) {
Ast *stmt = bs->stmts[i];
if (stmt->kind == Ast_ValueDecl) {
@@ -1580,6 +1584,7 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty
}
}
}
+
}
check_close_scope(ctx);
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index c7585b51c..9846199f8 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -6763,6 +6763,9 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *pr
if (initial_entity != nullptr && initial_entity->kind == Entity_Procedure) {
if (initial_entity->Procedure.deferred_procedure.entity != nullptr) {
call->viral_state_flags |= ViralStateFlag_ContainsDeferredProcedure;
+ if (c->decl) {
+ c->decl->defer_used += 1;
+ }
}
}
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index 9cacb4a35..502eed57e 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -2018,6 +2018,9 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
ctx->in_defer = true;
check_stmt(ctx, ds->stmt, 0);
ctx->in_defer = out_in_defer;
+ if (ctx->decl) {
+ ctx->decl->defer_used += 1;
+ }
}
case_end;
diff --git a/src/checker.hpp b/src/checker.hpp
index badcd93d5..37232ea95 100644
--- a/src/checker.hpp
+++ b/src/checker.hpp
@@ -158,6 +158,8 @@ struct DeclInfo {
bool is_using;
bool where_clauses_evaluated;
bool proc_checked;
+ isize defer_used;
+ bool defer_use_checked;
CommentGroup *comment;
CommentGroup *docs;
diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp
index c35affad5..166fcb3ee 100644
--- a/src/llvm_abi.cpp
+++ b/src/llvm_abi.cpp
@@ -1426,7 +1426,9 @@ LB_ABI_INFO(lb_get_abi_info_internal) {
switch (build_context.metrics.arch) {
case TargetArch_amd64:
- if (build_context.metrics.os == TargetOs_windows || build_context.metrics.abi == TargetABI_Win64) {
+ if (build_context.metrics.os == TargetOs_windows) {
+ return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
+ } else if (build_context.metrics.abi == TargetABI_Win64) {
return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
} else if (build_context.metrics.abi == TargetABI_SysV) {
return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp
index 59881735d..911c915a8 100644
--- a/src/llvm_backend.hpp
+++ b/src/llvm_backend.hpp
@@ -398,7 +398,7 @@ lbContextData *lb_push_context_onto_stack_from_implicit_parameter(lbProcedure *p
lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value={}, Entity **entity_=nullptr);
-lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e=nullptr, bool zero_init=true, i32 param_index=0, bool force_no_init=false);
+lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e=nullptr, bool zero_init=true, bool force_no_init=false);
void lb_add_foreign_library_path(lbModule *m, Entity *e);
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index 389bfb151..2c1bfecd6 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -134,7 +134,7 @@ lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, Type *type)
Type *elem_type = base_array_type(type);
// NOTE(bill): Doesn't need to be zero because it will be initialized in the loops
- lbAddr res_addr = lb_add_local(p, type, nullptr, false, 0, true);
+ lbAddr res_addr = lb_add_local(p, type, nullptr, false, true);
lbValue res = lb_addr_get_ptr(p, res_addr);
bool inline_array_arith = lb_can_try_to_inline_array_arith(type);
diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp
index 9fef5b05e..777755794 100644
--- a/src/llvm_backend_general.cpp
+++ b/src/llvm_backend_general.cpp
@@ -2868,7 +2868,7 @@ lbValue lb_build_cond(lbProcedure *p, Ast *cond, lbBlock *true_block, lbBlock *f
}
-lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e, bool zero_init, i32 param_index, bool force_no_init) {
+lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e, bool zero_init, bool force_no_init) {
GB_ASSERT(p->decl_block != p->curr_block);
LLVMPositionBuilderAtEnd(p->builder, p->decl_block->block);
@@ -2922,7 +2922,7 @@ lbAddr lb_add_local_generated(lbProcedure *p, Type *type, bool zero_init) {
}
lbAddr lb_add_local_generated_temp(lbProcedure *p, Type *type, i64 min_alignment) {
- lbAddr res = lb_add_local(p, type, nullptr, false, 0, true);
+ lbAddr res = lb_add_local(p, type, nullptr, false, true);
lb_try_update_alignment(res.addr, cast(unsigned)min_alignment);
return res;
}
diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp
index f14fc8a8c..f8dffa9b6 100644
--- a/src/llvm_backend_proc.cpp
+++ b/src/llvm_backend_proc.cpp
@@ -1,4 +1,3 @@
-
LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLVMValueRef* args, unsigned arg_count, LLVMTypeRef* types, unsigned type_count)
{
unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
@@ -596,16 +595,69 @@ void lb_begin_procedure_body(lbProcedure *p) {
if (e->token.string != "") {
GB_ASSERT(!is_blank_ident(e->token));
- // NOTE(bill): Don't even bother trying to optimize this with the return ptr value
- // This will violate the defer rules if you do:
- // foo :: proc() -> (x, y: T) {
- // defer x = ... // defer is executed after the `defer`
- // return // the values returned should be zeroed
- // }
- // NOTE(bill): REALLY, don't even bother.
- //
- // IMPORTANT NOTE(bill): REALLY, don't even bother!!!!!!
- lbAddr res = lb_add_local(p, e->type, e);
+ lbAddr res = {};
+ if (p->entity && p->entity->decl_info &&
+ p->entity->decl_info->defer_use_checked &&
+ p->entity->decl_info->defer_used == 0) {
+
+ // NOTE(bill): this is a bodge to get around the issue of the problem BELOW
+ // We check to see if we ever use a defer statement ever within a procedure and if it
+ // if it never happens, see if you can possibly do take the return value pointer
+ //
+ // NOTE(bill): this could be buggy in that I have missed a case where `defer` was used
+ //
+ // TODO(bill): This could be optimized to check to see where a `defer` only uses
+ // the variable in question
+
+ bool has_return_ptr = p->return_ptr.addr.value != nullptr;
+ lbValue ptr = {};
+
+ if (ft->multiple_return_original_type != nullptr) {
+ isize the_offset = -1;
+ if (i+1 < results->variables.count) {
+ the_offset = cast(isize)param_offset + ft->original_arg_count + i;
+ } else if (has_return_ptr) {
+ GB_ASSERT(i+1 == results->variables.count);
+ the_offset = 0;
+ }
+ if (the_offset >= 0) {
+ lbValue ptr = {};
+ ptr.value = LLVMGetParam(p->value, cast(unsigned)the_offset);
+ ptr.type = alloc_type_pointer(e->type);
+
+
+ }
+ } else if (has_return_ptr) {
+ lbValue ptr = p->return_ptr.addr;
+
+ if (results->variables.count > 1) {
+ ptr = lb_emit_tuple_ep(p, ptr, cast(i32)i);
+ }
+ GB_ASSERT(is_type_pointer(ptr.type));
+ GB_ASSERT(are_types_identical(type_deref(ptr.type), e->type));
+ }
+
+ if (ptr.value != nullptr) {
+ lb_add_entity(p->module, e, ptr);
+ lb_add_debug_local_variable(p, ptr.value, e->type, e->token);
+ // NOTE(bill): no need to zero on the callee side as it is zeroed on the caller side
+
+ res = lb_addr(ptr);
+ }
+ }
+
+ if (res.addr.type == nullptr) {
+ // NOTE(bill): Don't even bother trying to optimize this with the return ptr value
+ // This will violate the defer rules if you do:
+ // foo :: proc() -> (x, y: T) {
+ // defer x = ... // defer is executed after the `defer`
+ // return // the values returned should be zeroed
+ // }
+ // NOTE(bill): REALLY, don't even bother.
+ //
+ // IMPORTANT NOTE(bill): REALLY, don't even bother!!!!!!
+ res = lb_add_local(p, e->type, e);
+ }
if (e->Variable.param_value.kind != ParameterValue_Invalid) {
lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos);
@@ -1006,7 +1058,7 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args,
GB_ASSERT(rt->kind == Type_Tuple);
for (isize j = 0; j < rt->Tuple.variables.count-1; j++) {
Type *partial_return_type = rt->Tuple.variables[j]->type;
- lbValue partial_return_ptr = lb_add_local_generated(p, partial_return_type, true).addr;
+ lbValue partial_return_ptr = lb_add_local(p, partial_return_type, nullptr, true, false).addr;
array_add(&processed_args, partial_return_ptr);
}
rt = reduce_tuple_to_single_type(rt->Tuple.variables[rt->Tuple.variables.count-1]->type);