diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/all_types.hpp | 2 | ||||
| -rw-r--r-- | src/analyze.cpp | 21 | ||||
| -rw-r--r-- | src/codegen.cpp | 13 |
3 files changed, 29 insertions, 7 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp index 6cf27163b7..c6baee6a4b 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -474,6 +474,7 @@ struct AstNodeWhileExpr { // populated by semantic analyzer bool condition_always_true; bool contains_break; + bool contains_continue; Expr resolved_expr; BlockContext *block_context; }; @@ -486,6 +487,7 @@ struct AstNodeForExpr { // populated by semantic analyzer bool contains_break; + bool contains_continue; Expr resolved_expr; VariableTableEntry *elem_var; VariableTableEntry *index_var; diff --git a/src/analyze.cpp b/src/analyze.cpp index 5aad26cf34..38bc656a1f 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3354,6 +3354,7 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl } BlockContext *child_context = new_block_context(node, context); + child_context->parent_loop_node = node; AstNode *elem_var_node = node->data.for_expr.elem_node; elem_var_node->block_context = child_context; @@ -3385,8 +3386,13 @@ static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, AstNode *loop_node = context->parent_loop_node; if (loop_node) { - assert(loop_node->type == NodeTypeWhileExpr); - loop_node->data.while_expr.contains_break = true; + if (loop_node->type == NodeTypeWhileExpr) { + loop_node->data.while_expr.contains_break = true; + } else if (loop_node->type == NodeTypeForExpr) { + loop_node->data.for_expr.contains_break = true; + } else { + zig_unreachable(); + } } else { add_node_error(g, node, buf_sprintf("'break' expression outside loop")); } @@ -3396,7 +3402,16 @@ static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, static TypeTableEntry *analyze_continue_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, TypeTableEntry *expected_type, AstNode *node) { - if (!context->parent_loop_node) { + AstNode *loop_node = context->parent_loop_node; + if (loop_node) { + if (loop_node->type == NodeTypeWhileExpr) { + loop_node->data.while_expr.contains_continue = true; + } else if (loop_node->type == NodeTypeForExpr) { + loop_node->data.for_expr.contains_continue = true; + } else { + zig_unreachable(); + } + } else { add_node_error(g, node, buf_sprintf("'continue' expression outside loop")); } return g->builtin_types.entry_unreachable; diff --git a/src/codegen.cpp b/src/codegen.cpp index 7dd91b6a66..5c07b34097 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2089,6 +2089,7 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) { LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForCond"); LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForBody"); LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForEnd"); + LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForContinue"); LLVMValueRef array_val = gen_array_base_ptr(g, node->data.for_expr.array_expr); add_debug_source_node(g, node); @@ -2122,17 +2123,21 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) { gen_assign_raw(g, node, BinOpTypeAssign, elem_var->value_ref, elem_val, elem_var->type, child_type); g->break_block_stack.append(end_block); - g->continue_block_stack.append(cond_block); + g->continue_block_stack.append(continue_block); gen_expr(g, node->data.for_expr.body); g->break_block_stack.pop(); g->continue_block_stack.pop(); if (get_expr_type(node->data.for_expr.body)->id != TypeTableEntryIdUnreachable) { add_debug_source_node(g, node); - LLVMValueRef new_index_val = LLVMBuildAdd(g->builder, index_val, one_const, ""); - LLVMBuildStore(g->builder, new_index_val, index_ptr); - LLVMBuildBr(g->builder, cond_block); + LLVMBuildBr(g->builder, continue_block); } + LLVMPositionBuilderAtEnd(g->builder, continue_block); + add_debug_source_node(g, node); + LLVMValueRef new_index_val = LLVMBuildAdd(g->builder, index_val, one_const, ""); + LLVMBuildStore(g->builder, new_index_val, index_ptr); + LLVMBuildBr(g->builder, cond_block); + LLVMPositionBuilderAtEnd(g->builder, end_block); return nullptr; } |
