authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-02 16:31:43-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-02 16:31:43-04:00
logb3b6a98451a9703dc15a1ee5f48acde23de3c491
tree73f175e743d792e843adb60f9e33a4fad52c3a97
parentf07f09a373639ae8f1e46fb7beef239f7f85f57d
parentb2d94f9af2968e01bd3d8db38c9ae1992bbd3678
signaturelock-open Commit is signed but in an unrecognized format.

Merge remote-tracking branch 'origin/master' into rewrite-coroutines


20 files changed, 421 insertions(+), 142 deletions(-)

CMakeLists.txt+10-11
...@@ -209,7 +209,7 @@ else()...@@ -209,7 +209,7 @@ else()
209 else()209 else()
210 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Wno-comment")210 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Wno-comment")
211 if(MINGW)211 if(MINGW)
212 set(ZIG_LLD_COMPILE_FLAGS "${ZIG_LLD_COMPILE_FLAGS} -D__STDC_FORMAT_MACROS -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format")212 set(ZIG_LLD_COMPILE_FLAGS "${ZIG_LLD_COMPILE_FLAGS} -D__STDC_FORMAT_MACROS -D__USE_MINGW_ANSI_STDIO")
213 endif()213 endif()
214 endif()214 endif()
215 set_target_properties(embedded_lld_lib PROPERTIES215 set_target_properties(embedded_lld_lib PROPERTIES
...@@ -511,19 +511,23 @@ set(OPTIMIZED_C_FLAGS "-std=c99 -O3")...@@ -511,19 +511,23 @@ set(OPTIMIZED_C_FLAGS "-std=c99 -O3")
511511
512set(EXE_LDFLAGS " ")512set(EXE_LDFLAGS " ")
513if(MSVC)513if(MSVC)
514 set(EXE_LDFLAGS "/STACK:16777216")514 set(EXE_LDFLAGS "${EXE_LDFLAGS} /STACK:16777216")
515elseif(MINGW) 515elseif(MINGW)
516 set(EXE_LDFLAGS "${EXE_LDFLAGS} -Wl,--stack,16777216")516 set(EXE_LDFLAGS "${EXE_LDFLAGS} -Wl,--stack,16777216")
517endif()517endif()
518518
519if(ZIG_STATIC)519if(ZIG_STATIC)
520 if(APPLE)520 if(APPLE)
521 set(EXE_LDFLAGS "-static-libgcc -static-libstdc++")521 set(EXE_LDFLAGS "${EXE_LDFLAGS} -static-libgcc -static-libstdc++")
522 elseif(MINGW)522 elseif(MINGW)
523 set(EXE_LDFLAGS "-static-libgcc -static-libstdc++ -Wl,-Bstatic,--whole-archive -lwinpthread -lz3 -lz -lgomp -Wl,--no-whole-archive")523 set(EXE_LDFLAGS "${EXE_LDFLAGS} -static-libgcc -static-libstdc++ -Wl,-Bstatic, -lwinpthread -lz3 -lz -lgomp")
524 else()524 elseif(NOT MSVC)
525 set(EXE_LDFLAGS "-static")525 set(EXE_LDFLAGS "${EXE_LDFLAGS} -static")
526 endif()526 endif()
527else()
528 if(MINGW)
529 set(EXE_LDFLAGS "${EXE_LDFLAGS} -lz3")
530 endif()
527endif()531endif()
528532
529if(ZIG_TEST_COVERAGE)533if(ZIG_TEST_COVERAGE)
...@@ -559,11 +563,6 @@ if(NOT MSVC)...@@ -559,11 +563,6 @@ if(NOT MSVC)
559 target_link_libraries(compiler LINK_PUBLIC ${LIBXML2})563 target_link_libraries(compiler LINK_PUBLIC ${LIBXML2})
560endif()564endif()
561565
562if(MINGW)
563 find_library(Z3_LIBRARIES NAMES z3 z3.dll)
564 target_link_libraries(compiler LINK_PUBLIC ${Z3_LIBRARIES})
565endif()
566
567if(ZIG_DIA_GUIDS_LIB)566if(ZIG_DIA_GUIDS_LIB)
568 target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})567 target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
569endif()568endif()
src/all_types.hpp+2
...@@ -2529,6 +2529,7 @@ struct IrInstructionLoadPtrGen {...@@ -2529,6 +2529,7 @@ struct IrInstructionLoadPtrGen {
2529struct IrInstructionStorePtr {2529struct IrInstructionStorePtr {
2530 IrInstruction base;2530 IrInstruction base;
25312531
2532 bool allow_write_through_const;
2532 IrInstruction *ptr;2533 IrInstruction *ptr;
2533 IrInstruction *value;2534 IrInstruction *value;
2534};2535};
...@@ -3630,6 +3631,7 @@ enum ResultLocId {...@@ -3630,6 +3631,7 @@ enum ResultLocId {
3630struct ResultLoc {3631struct ResultLoc {
3631 ResultLocId id;3632 ResultLocId id;
3632 bool written;3633 bool written;
3634 bool allow_write_through_const;
3633 IrInstruction *resolved_loc; // result ptr 3635 IrInstruction *resolved_loc; // result ptr
3634 IrInstruction *source_instruction;3636 IrInstruction *source_instruction;
3635 IrInstruction *gen_instruction; // value to store to the result loc3637 IrInstruction *gen_instruction; // value to store to the result loc
src/codegen.cpp+7-1
...@@ -4355,8 +4355,14 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn...@@ -4355,8 +4355,14 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
4355 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");4355 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");
4356 }4356 }
43574357
4358 // When the cmpxchg is discarded, the result location will have no bits.
4359 if (!type_has_bits(instruction->result_loc->value.type)) {
4360 return nullptr;
4361 }
4362
4358 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);4363 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
4359 assert(type_has_bits(child_type));4364 src_assert(result_loc != nullptr, instruction->base.source_node);
4365 src_assert(type_has_bits(child_type), instruction->base.source_node);
43604366
4361 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");4367 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
4362 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");4368 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
src/ir.cpp+76-51
...@@ -188,7 +188,8 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -188,7 +188,8 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_
188static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr,188static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr,
189 ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime);189 ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime);
190static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,190static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,
191 ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime);191 ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime,
192 bool non_null_comptime, bool allow_discard);
192static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,193static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
193 IrInstruction *base_ptr, bool safety_check_on, bool initializing);194 IrInstruction *base_ptr, bool safety_check_on, bool initializing);
194static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,195static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,
...@@ -196,7 +197,7 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct...@@ -196,7 +197,7 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct
196static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,197static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
197 IrInstruction *base_ptr, bool initializing);198 IrInstruction *base_ptr, bool initializing);
198static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,199static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
199 IrInstruction *ptr, IrInstruction *uncasted_value);200 IrInstruction *ptr, IrInstruction *uncasted_value, bool allow_write_through_const);
200static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node,201static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node,
201 IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node,202 IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node,
202 LVal lval, ResultLoc *parent_result_loc);203 LVal lval, ResultLoc *parent_result_loc);
...@@ -1564,7 +1565,7 @@ static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode...@@ -1564,7 +1565,7 @@ static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode
1564 return &unreachable_instruction->base;1565 return &unreachable_instruction->base;
1565}1566}
15661567
1567static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,1568static IrInstructionStorePtr *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1568 IrInstruction *ptr, IrInstruction *value)1569 IrInstruction *ptr, IrInstruction *value)
1569{1570{
1570 IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, scope, source_node);1571 IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, scope, source_node);
...@@ -1576,7 +1577,7 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *...@@ -1576,7 +1577,7 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *
1576 ir_ref_instruction(ptr, irb->current_basic_block);1577 ir_ref_instruction(ptr, irb->current_basic_block);
1577 ir_ref_instruction(value, irb->current_basic_block);1578 ir_ref_instruction(value, irb->current_basic_block);
15781579
1579 return &instruction->base;1580 return instruction;
1580}1581}
15811582
1582static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,1583static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
...@@ -3792,12 +3793,20 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *no...@@ -3792,12 +3793,20 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *no
37923793
3793static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) {3794static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) {
3794 IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);3795 IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
3795 IrInstruction *rvalue = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);3796 if (lvalue == irb->codegen->invalid_instruction)
3797 return irb->codegen->invalid_instruction;
3798
3799 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
3800 result_loc_inst->base.id = ResultLocIdInstruction;
3801 result_loc_inst->base.source_instruction = lvalue;
3802 ir_ref_instruction(lvalue, irb->current_basic_block);
3803 ir_build_reset_result(irb, scope, node, &result_loc_inst->base);
37963804
3797 if (lvalue == irb->codegen->invalid_instruction || rvalue == irb->codegen->invalid_instruction)3805 IrInstruction *rvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op2, scope, LValNone,
3806 &result_loc_inst->base);
3807 if (rvalue == irb->codegen->invalid_instruction)
3798 return irb->codegen->invalid_instruction;3808 return irb->codegen->invalid_instruction;
37993809
3800 ir_build_store_ptr(irb, scope, node, lvalue, rvalue);
3801 return ir_build_const_void(irb, scope, node);3810 return ir_build_const_void(irb, scope, node);
3802}3811}
38033812
...@@ -5836,6 +5845,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A...@@ -5836,6 +5845,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
5836 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);5845 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
5837 result_loc_inst->base.id = ResultLocIdInstruction;5846 result_loc_inst->base.id = ResultLocIdInstruction;
5838 result_loc_inst->base.source_instruction = field_ptr;5847 result_loc_inst->base.source_instruction = field_ptr;
5848 result_loc_inst->base.allow_write_through_const = true;
5839 ir_ref_instruction(field_ptr, irb->current_basic_block);5849 ir_ref_instruction(field_ptr, irb->current_basic_block);
5840 ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);5850 ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);
58415851
...@@ -5874,6 +5884,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A...@@ -5874,6 +5884,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
5874 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);5884 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
5875 result_loc_inst->base.id = ResultLocIdInstruction;5885 result_loc_inst->base.id = ResultLocIdInstruction;
5876 result_loc_inst->base.source_instruction = elem_ptr;5886 result_loc_inst->base.source_instruction = elem_ptr;
5887 result_loc_inst->base.allow_write_through_const = true;
5877 ir_ref_instruction(elem_ptr, irb->current_basic_block);5888 ir_ref_instruction(elem_ptr, irb->current_basic_block);
5878 ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);5889 ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);
58795890
...@@ -6431,7 +6442,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -6431,7 +6442,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
64316442
6432 ir_set_cursor_at_end_and_append_block(irb, continue_block);6443 ir_set_cursor_at_end_and_append_block(irb, continue_block);
6433 IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false);6444 IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false);
6434 ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val));6445 ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val)->allow_write_through_const = true;
6435 ir_build_br(irb, child_scope, node, cond_block, is_comptime);6446 ir_build_br(irb, child_scope, node, cond_block, is_comptime);
64366447
6437 IrInstruction *else_result = nullptr;6448 IrInstruction *else_result = nullptr;
...@@ -10344,7 +10355,8 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc...@@ -10344,7 +10355,8 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
10344 }10355 }
1034510356
10346 if (result_loc == nullptr) result_loc = no_result_loc();10357 if (result_loc == nullptr) result_loc = no_result_loc();
10347 IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);10358 IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true,
10359 false, true);
10348 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {10360 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
10349 return result_loc_inst;10361 return result_loc_inst;
10350 }10362 }
...@@ -10804,7 +10816,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so...@@ -10804,7 +10816,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so
10804 }10816 }
10805 IrInstruction *result_loc_inst = nullptr;10817 IrInstruction *result_loc_inst = nullptr;
10806 if (result_loc != nullptr) {10818 if (result_loc != nullptr) {
10807 result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);10819 result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false, true);
10808 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {10820 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
10809 return result_loc_inst;10821 return result_loc_inst;
10810 }10822 }
...@@ -10847,7 +10859,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction...@@ -10847,7 +10859,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
10847 IrInstruction *result_loc_inst;10859 IrInstruction *result_loc_inst;
10848 if (handle_is_ptr(wanted_type)) {10860 if (handle_is_ptr(wanted_type)) {
10849 if (result_loc == nullptr) result_loc = no_result_loc();10861 if (result_loc == nullptr) result_loc = no_result_loc();
10850 result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);10862 result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false, true);
10851 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {10863 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
10852 return result_loc_inst;10864 return result_loc_inst;
10853 }10865 }
...@@ -10959,7 +10971,7 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so...@@ -10959,7 +10971,7 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
10959 IrInstruction *result_loc_inst;10971 IrInstruction *result_loc_inst;
10960 if (handle_is_ptr(wanted_type)) {10972 if (handle_is_ptr(wanted_type)) {
10961 if (result_loc == nullptr) result_loc = no_result_loc();10973 if (result_loc == nullptr) result_loc = no_result_loc();
10962 result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);10974 result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false, true);
10963 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {10975 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
10964 return result_loc_inst;10976 return result_loc_inst;
10965 }10977 }
...@@ -11032,7 +11044,8 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi...@@ -11032,7 +11044,8 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
1103211044
11033 IrInstruction *result_loc;11045 IrInstruction *result_loc;
11034 if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {11046 if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {
11035 result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value.type, nullptr, true, false);11047 result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value.type, nullptr, true,
11048 false, true);
11036 } else {11049 } else {
11037 result_loc = nullptr;11050 result_loc = nullptr;
11038 }11051 }
...@@ -11076,7 +11089,8 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s...@@ -11076,7 +11089,8 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
11076 if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);11089 if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);
1107711090
11078 if (result_loc == nullptr) result_loc = no_result_loc();11091 if (result_loc == nullptr) result_loc = no_result_loc();
11079 IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);11092 IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr,
11093 true, false, true);
11080 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {11094 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
11081 return result_loc_inst;11095 return result_loc_inst;
11082 }11096 }
...@@ -11732,7 +11746,8 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *...@@ -11732,7 +11746,8 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
11732 if (result_loc == nullptr) {11746 if (result_loc == nullptr) {
11733 result_loc = no_result_loc();11747 result_loc = no_result_loc();
11734 }11748 }
11735 IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, array_type, nullptr, true, false);11749 IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, array_type, nullptr,
11750 true, false, true);
11736 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {11751 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
11737 return result_loc_inst;11752 return result_loc_inst;
11738 }11753 }
...@@ -12334,7 +12349,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -12334,7 +12349,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
12334 IrInstruction *result_loc_inst;12349 IrInstruction *result_loc_inst;
12335 if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {12350 if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
12336 if (result_loc == nullptr) result_loc = no_result_loc();12351 if (result_loc == nullptr) result_loc = no_result_loc();
12337 result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, true, false);12352 result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr,
12353 true, false, true);
12338 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {12354 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
12339 return result_loc_inst;12355 return result_loc_inst;
12340 }12356 }
...@@ -14072,7 +14088,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -14072,7 +14088,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
14072 // instruction.14088 // instruction.
14073 assert(deref->value.special != ConstValSpecialRuntime);14089 assert(deref->value.special != ConstValSpecialRuntime);
14074 var_ptr->value.special = ConstValSpecialRuntime;14090 var_ptr->value.special = ConstValSpecialRuntime;
14075 ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref);14091 ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref, false);
14076 }14092 }
1407714093
14078 if (var_ptr->value.special == ConstValSpecialStatic && var->mem_slot_index != SIZE_MAX) {14094 if (var_ptr->value.special == ConstValSpecialStatic && var->mem_slot_index != SIZE_MAX) {
...@@ -14556,7 +14572,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -14556,7 +14572,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
1455614572
14557 if (peer_parent->peers.length == 1) {14573 if (peer_parent->peers.length == 1) {
14558 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,14574 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
14559 value_type, value, force_runtime, non_null_comptime);14575 value_type, value, force_runtime, non_null_comptime, true);
14560 result_peer->suspend_pos.basic_block_index = SIZE_MAX;14576 result_peer->suspend_pos.basic_block_index = SIZE_MAX;
14561 result_peer->suspend_pos.instruction_index = SIZE_MAX;14577 result_peer->suspend_pos.instruction_index = SIZE_MAX;
14562 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||14578 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
...@@ -14576,7 +14592,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -14576,7 +14592,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
14576 if (peer_parent->skipped) {14592 if (peer_parent->skipped) {
14577 if (non_null_comptime) {14593 if (non_null_comptime) {
14578 return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,14594 return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
14579 value_type, value, force_runtime, non_null_comptime);14595 value_type, value, force_runtime, non_null_comptime, true);
14580 }14596 }
14581 return nullptr;14597 return nullptr;
14582 }14598 }
...@@ -14594,7 +14610,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -14594,7 +14610,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
14594 }14610 }
1459514611
14596 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,14612 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
14597 peer_parent->resolved_type, nullptr, force_runtime, non_null_comptime);14613 peer_parent->resolved_type, nullptr, force_runtime, non_null_comptime, true);
14598 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||14614 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
14599 parent_result_loc->value.type->id == ZigTypeIdUnreachable)14615 parent_result_loc->value.type->id == ZigTypeIdUnreachable)
14600 {14616 {
...@@ -14644,7 +14660,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -14644,7 +14660,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
14644 }14660 }
1464514661
14646 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent,14662 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent,
14647 dest_type, bitcasted_value, force_runtime, non_null_comptime);14663 dest_type, bitcasted_value, force_runtime, non_null_comptime, true);
14648 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||14664 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
14649 parent_result_loc->value.type->id == ZigTypeIdUnreachable)14665 parent_result_loc->value.type->id == ZigTypeIdUnreachable)
14650 {14666 {
...@@ -14673,8 +14689,15 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -14673,8 +14689,15 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
1467314689
14674static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,14690static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,
14675 ResultLoc *result_loc_pass1, ZigType *value_type, IrInstruction *value, bool force_runtime,14691 ResultLoc *result_loc_pass1, ZigType *value_type, IrInstruction *value, bool force_runtime,
14676 bool non_null_comptime)14692 bool non_null_comptime, bool allow_discard)
14677{14693{
14694 if (!allow_discard && result_loc_pass1->id == ResultLocIdInstruction &&
14695 instr_is_comptime(result_loc_pass1->source_instruction) &&
14696 result_loc_pass1->source_instruction->value.type->id == ZigTypeIdPointer &&
14697 result_loc_pass1->source_instruction->value.data.x_ptr.special == ConstPtrSpecialDiscard)
14698 {
14699 result_loc_pass1 = no_result_loc();
14700 }
14678 IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type,14701 IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type,
14679 value, force_runtime, non_null_comptime);14702 value, force_runtime, non_null_comptime);
14680 if (result_loc == nullptr || (instr_is_unreachable(result_loc) || type_is_invalid(result_loc->value.type)))14703 if (result_loc == nullptr || (instr_is_unreachable(result_loc) || type_is_invalid(result_loc->value.type)))
...@@ -14729,7 +14752,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn...@@ -14729,7 +14752,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn
14729 if (type_is_invalid(implicit_elem_type))14752 if (type_is_invalid(implicit_elem_type))
14730 return ira->codegen->invalid_instruction;14753 return ira->codegen->invalid_instruction;
14731 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,14754 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
14732 implicit_elem_type, nullptr, false, true);14755 implicit_elem_type, nullptr, false, true, true);
14733 if (result_loc != nullptr)14756 if (result_loc != nullptr)
14734 return result_loc;14757 return result_loc;
1473514758
...@@ -14738,7 +14761,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn...@@ -14738,7 +14761,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn
14738 instruction->result_loc->id == ResultLocIdReturn)14761 instruction->result_loc->id == ResultLocIdReturn)
14739 {14762 {
14740 result_loc = ir_resolve_result(ira, &instruction->base, no_result_loc(),14763 result_loc = ir_resolve_result(ira, &instruction->base, no_result_loc(),
14741 implicit_elem_type, nullptr, false, true);14764 implicit_elem_type, nullptr, false, true, true);
14742 if (result_loc != nullptr &&14765 if (result_loc != nullptr &&
14743 (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)))14766 (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)))
14744 {14767 {
...@@ -14800,7 +14823,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc...@@ -14800,7 +14823,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc
1480014823
14801 ZigType *frame_type = get_coro_frame_type(ira->codegen, fn_entry);14824 ZigType *frame_type = get_coro_frame_type(ira->codegen, fn_entry);
14802 IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,14825 IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
14803 frame_type, nullptr, true, true);14826 frame_type, nullptr, true, true, false);
14804 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {14827 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {
14805 return result_loc;14828 return result_loc;
14806 }14829 }
...@@ -15015,7 +15038,7 @@ no_mem_slot:...@@ -15015,7 +15038,7 @@ no_mem_slot:
15015}15038}
1501615039
15017static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,15040static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
15018 IrInstruction *ptr, IrInstruction *uncasted_value)15041 IrInstruction *ptr, IrInstruction *uncasted_value, bool allow_write_through_const)
15019{15042{
15020 assert(ptr->value.type->id == ZigTypeIdPointer);15043 assert(ptr->value.type->id == ZigTypeIdPointer);
1502115044
...@@ -15031,7 +15054,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -15031,7 +15054,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
1503115054
15032 ZigType *child_type = ptr->value.type->data.pointer.child_type;15055 ZigType *child_type = ptr->value.type->data.pointer.child_type;
1503315056
15034 if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {15057 if (ptr->value.type->data.pointer.is_const && !allow_write_through_const) {
15035 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));15058 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
15036 return ira->codegen->invalid_instruction;15059 return ira->codegen->invalid_instruction;
15037 }15060 }
...@@ -15110,10 +15133,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -15110,10 +15133,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
15110 break;15133 break;
15111 }15134 }
1511215135
15113 IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,15136 IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope,
15114 ptr, value);15137 source_instr->source_node, ptr, value);
15115 result->value.type = ira->codegen->builtin_types.entry_void;15138 return &store_ptr->base;
15116 return result;
15117}15139}
1511815140
15119static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,15141static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
...@@ -15518,7 +15540,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15518,7 +15540,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
15518 IrInstruction *result_loc;15540 IrInstruction *result_loc;
15519 if (handle_is_ptr(impl_fn_type_id->return_type)) {15541 if (handle_is_ptr(impl_fn_type_id->return_type)) {
15520 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,15542 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
15521 impl_fn_type_id->return_type, nullptr, true, true);15543 impl_fn_type_id->return_type, nullptr, true, true, false);
15522 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) ||15544 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) ||
15523 instr_is_unreachable(result_loc)))15545 instr_is_unreachable(result_loc)))
15524 {15546 {
...@@ -15635,7 +15657,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15635,7 +15657,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
15635 IrInstruction *result_loc;15657 IrInstruction *result_loc;
15636 if (handle_is_ptr(return_type)) {15658 if (handle_is_ptr(return_type)) {
15637 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,15659 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
15638 return_type, nullptr, true, true);15660 return_type, nullptr, true, true, false);
15639 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {15661 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {
15640 return result_loc;15662 return result_loc;
15641 }15663 }
...@@ -16154,7 +16176,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -16154,7 +16176,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1615416176
16155 // In case resolving the parent activates a suspend, do it now16177 // In case resolving the parent activates a suspend, do it now
16156 IrInstruction *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base, peer_parent->parent,16178 IrInstruction *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base, peer_parent->parent,
16157 peer_parent->resolved_type, nullptr, false, false);16179 peer_parent->resolved_type, nullptr, false, false, true);
16158 if (parent_result_loc != nullptr &&16180 if (parent_result_loc != nullptr &&
16159 (type_is_invalid(parent_result_loc->value.type) || instr_is_unreachable(parent_result_loc)))16181 (type_is_invalid(parent_result_loc->value.type) || instr_is_unreachable(parent_result_loc)))
16160 {16182 {
...@@ -16611,6 +16633,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -16611,6 +16633,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
16611 return result;16633 return result;
16612 } else if (is_slice(array_type)) {16634 } else if (is_slice(array_type)) {
16613 ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index];16635 ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index];
16636 ir_assert(ptr_field != nullptr, &elem_ptr_instruction->base);
16614 if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {16637 if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
16615 IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,16638 IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
16616 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, false,16639 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, false,
...@@ -16797,7 +16820,7 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction...@@ -16797,7 +16820,7 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
16797 return ira->codegen->invalid_instruction;16820 return ira->codegen->invalid_instruction;
16798 if (type_is_invalid(struct_val->type))16821 if (type_is_invalid(struct_val->type))
16799 return ira->codegen->invalid_instruction;16822 return ira->codegen->invalid_instruction;
16800 if (struct_val->special == ConstValSpecialUndef && initializing) {16823 if (initializing && struct_val->special == ConstValSpecialUndef) {
16801 struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count);16824 struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count);
16802 struct_val->special = ConstValSpecialStatic;16825 struct_val->special = ConstValSpecialStatic;
16803 for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {16826 for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
...@@ -17395,7 +17418,7 @@ static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstruc...@@ -17395,7 +17418,7 @@ static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstruc
17395 if (type_is_invalid(value->value.type))17418 if (type_is_invalid(value->value.type))
17396 return ira->codegen->invalid_instruction;17419 return ira->codegen->invalid_instruction;
1739717420
17398 return ir_analyze_store_ptr(ira, &instruction->base, ptr, value);17421 return ir_analyze_store_ptr(ira, &instruction->base, ptr, value, instruction->allow_write_through_const);
17399}17422}
1740017423
17401static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) {17424static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) {
...@@ -17899,7 +17922,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr...@@ -17899,7 +17922,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
17899 if (optional_val == nullptr)17922 if (optional_val == nullptr)
17900 return ira->codegen->invalid_instruction;17923 return ira->codegen->invalid_instruction;
1790117924
17902 if (initializing && optional_val->special == ConstValSpecialUndef) {17925 if (initializing) {
17903 switch (type_has_one_possible_value(ira->codegen, child_type)) {17926 switch (type_has_one_possible_value(ira->codegen, child_type)) {
17904 case OnePossibleValueInvalid:17927 case OnePossibleValueInvalid:
17905 return ira->codegen->invalid_instruction;17928 return ira->codegen->invalid_instruction;
...@@ -18805,7 +18828,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -18805,7 +18828,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1880518828
18806 IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc,18829 IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc,
18807 container_type, true);18830 container_type, true);
18808 ir_analyze_store_ptr(ira, instruction, field_ptr, runtime_inst);18831 ir_analyze_store_ptr(ira, instruction, field_ptr, runtime_inst, false);
18809 if (instr_is_comptime(field_ptr) && field_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {18832 if (instr_is_comptime(field_ptr) && field_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
18810 const_ptrs.append(field_ptr);18833 const_ptrs.append(field_ptr);
18811 } else {18834 } else {
...@@ -18822,7 +18845,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -18822,7 +18845,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
18822 IrInstruction *field_result_loc = const_ptrs.at(i);18845 IrInstruction *field_result_loc = const_ptrs.at(i);
18823 IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr);18846 IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr);
18824 field_result_loc->value.special = ConstValSpecialRuntime;18847 field_result_loc->value.special = ConstValSpecialRuntime;
18825 ir_analyze_store_ptr(ira, field_result_loc, field_result_loc, deref);18848 ir_analyze_store_ptr(ira, field_result_loc, field_result_loc, deref, false);
18826 }18849 }
18827 }18850 }
18828 }18851 }
...@@ -18949,7 +18972,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,...@@ -18949,7 +18972,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
18949 assert(elem_result_loc->value.special == ConstValSpecialStatic);18972 assert(elem_result_loc->value.special == ConstValSpecialStatic);
18950 IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr);18973 IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr);
18951 elem_result_loc->value.special = ConstValSpecialRuntime;18974 elem_result_loc->value.special = ConstValSpecialRuntime;
18952 ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref);18975 ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref, false);
18953 }18976 }
18954 }18977 }
18955 }18978 }
...@@ -20646,7 +20669,7 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi...@@ -20646,7 +20669,7 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
20646 IrInstruction *result_loc;20669 IrInstruction *result_loc;
20647 if (handle_is_ptr(result_type)) {20670 if (handle_is_ptr(result_type)) {
20648 result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,20671 result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
20649 result_type, nullptr, true, false);20672 result_type, nullptr, true, false, true);
20650 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {20673 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
20651 return result_loc;20674 return result_loc;
20652 }20675 }
...@@ -20903,7 +20926,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru...@@ -20903,7 +20926,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
20903 }20926 }
2090420927
20905 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,20928 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
20906 dest_slice_type, nullptr, true, false);20929 dest_slice_type, nullptr, true, false, true);
20907 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {20930 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {
20908 return result_loc;20931 return result_loc;
20909 }20932 }
...@@ -20980,7 +21003,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct...@@ -20980,7 +21003,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
20980 }21003 }
2098121004
20982 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,21005 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
20983 dest_slice_type, nullptr, true, false);21006 dest_slice_type, nullptr, true, false, true);
20984 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {21007 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
20985 return result_loc;21008 return result_loc;
20986 }21009 }
...@@ -21722,7 +21745,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -21722,7 +21745,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
21722 }21745 }
2172321746
21724 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,21747 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
21725 return_type, nullptr, true, false);21748 return_type, nullptr, true, false, true);
21726 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {21749 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
21727 return result_loc;21750 return result_loc;
21728 }21751 }
...@@ -22405,7 +22428,7 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct...@@ -22405,7 +22428,7 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct
22405 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);22428 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
22406 if (err_union_val == nullptr)22429 if (err_union_val == nullptr)
22407 return ira->codegen->invalid_instruction;22430 return ira->codegen->invalid_instruction;
22408 if (err_union_val->special == ConstValSpecialUndef && initializing) {22431 if (initializing && err_union_val->special == ConstValSpecialUndef) {
22409 ConstExprValue *vals = create_const_vals(2);22432 ConstExprValue *vals = create_const_vals(2);
22410 ConstExprValue *err_set_val = &vals[0];22433 ConstExprValue *err_set_val = &vals[0];
22411 ConstExprValue *payload_val = &vals[1];22434 ConstExprValue *payload_val = &vals[1];
...@@ -23700,10 +23723,11 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op...@@ -23700,10 +23723,11 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op
23700 operand_type->data.integral.bit_count));23723 operand_type->data.integral.bit_count));
23701 return ira->codegen->builtin_types.entry_invalid;23724 return ira->codegen->builtin_types.entry_invalid;
23702 }23725 }
23703 if (operand_type->data.integral.bit_count > ira->codegen->pointer_size_bytes * 8) {23726 uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
23727 if (operand_type->data.integral.bit_count > max_atomic_bits) {
23704 ir_add_error(ira, op,23728 ir_add_error(ira, op,
23705 buf_sprintf("expected integer type pointer size or smaller, found %" PRIu32 "-bit integer type",23729 buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type",
23706 operand_type->data.integral.bit_count));23730 max_atomic_bits, operand_type->data.integral.bit_count));
23707 return ira->codegen->builtin_types.entry_invalid;23731 return ira->codegen->builtin_types.entry_invalid;
23708 }23732 }
23709 if (!is_power_of_2(operand_type->data.integral.bit_count)) {23733 if (!is_power_of_2(operand_type->data.integral.bit_count)) {
...@@ -24293,7 +24317,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct...@@ -24293,7 +24317,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
2429324317
24294 bool was_written = instruction->result_loc->written;24318 bool was_written = instruction->result_loc->written;
24295 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,24319 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
24296 value->value.type, value, false, false);24320 value->value.type, value, false, false, true);
24297 if (result_loc != nullptr) {24321 if (result_loc != nullptr) {
24298 if (type_is_invalid(result_loc->value.type))24322 if (type_is_invalid(result_loc->value.type))
24299 return ira->codegen->invalid_instruction;24323 return ira->codegen->invalid_instruction;
...@@ -24301,7 +24325,8 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct...@@ -24301,7 +24325,8 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
24301 return result_loc;24325 return result_loc;
2430224326
24303 if (!was_written) {24327 if (!was_written) {
24304 IrInstruction *store_ptr = ir_analyze_store_ptr(ira, &instruction->base, result_loc, value);24328 IrInstruction *store_ptr = ir_analyze_store_ptr(ira, &instruction->base, result_loc, value,
24329 instruction->result_loc->allow_write_through_const);
24305 if (type_is_invalid(store_ptr->value.type)) {24330 if (type_is_invalid(store_ptr->value.type)) {
24306 return ira->codegen->invalid_instruction;24331 return ira->codegen->invalid_instruction;
24307 }24332 }
...@@ -24325,7 +24350,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst...@@ -24325,7 +24350,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst
24325 return operand;24350 return operand;
2432624351
24327 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base,24352 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base,
24328 &instruction->result_loc_bit_cast->base, operand->value.type, operand, false, false);24353 &instruction->result_loc_bit_cast->base, operand->value.type, operand, false, false, true);
24329 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)))24354 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)))
24330 return result_loc;24355 return result_loc;
2433124356
src/target.cpp+66
...@@ -863,6 +863,71 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) {...@@ -863,6 +863,71 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) {
863 zig_unreachable();863 zig_unreachable();
864}864}
865865
866uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch) {
867 switch (arch) {
868 case ZigLLVM_UnknownArch:
869 zig_unreachable();
870
871 case ZigLLVM_avr:
872 case ZigLLVM_msp430:
873 return 16;
874
875 case ZigLLVM_arc:
876 case ZigLLVM_arm:
877 case ZigLLVM_armeb:
878 case ZigLLVM_hexagon:
879 case ZigLLVM_le32:
880 case ZigLLVM_mips:
881 case ZigLLVM_mipsel:
882 case ZigLLVM_nvptx:
883 case ZigLLVM_ppc:
884 case ZigLLVM_r600:
885 case ZigLLVM_riscv32:
886 case ZigLLVM_sparc:
887 case ZigLLVM_sparcel:
888 case ZigLLVM_tce:
889 case ZigLLVM_tcele:
890 case ZigLLVM_thumb:
891 case ZigLLVM_thumbeb:
892 case ZigLLVM_x86:
893 case ZigLLVM_xcore:
894 case ZigLLVM_amdil:
895 case ZigLLVM_hsail:
896 case ZigLLVM_spir:
897 case ZigLLVM_kalimba:
898 case ZigLLVM_lanai:
899 case ZigLLVM_shave:
900 case ZigLLVM_wasm32:
901 case ZigLLVM_renderscript32:
902 return 32;
903
904 case ZigLLVM_aarch64:
905 case ZigLLVM_aarch64_be:
906 case ZigLLVM_amdgcn:
907 case ZigLLVM_bpfel:
908 case ZigLLVM_bpfeb:
909 case ZigLLVM_le64:
910 case ZigLLVM_mips64:
911 case ZigLLVM_mips64el:
912 case ZigLLVM_nvptx64:
913 case ZigLLVM_ppc64:
914 case ZigLLVM_ppc64le:
915 case ZigLLVM_riscv64:
916 case ZigLLVM_sparcv9:
917 case ZigLLVM_systemz:
918 case ZigLLVM_amdil64:
919 case ZigLLVM_hsail64:
920 case ZigLLVM_spir64:
921 case ZigLLVM_wasm64:
922 case ZigLLVM_renderscript64:
923 return 64;
924
925 case ZigLLVM_x86_64:
926 return 128;
927 }
928 zig_unreachable();
929}
930
866uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {931uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
867 switch (target->os) {932 switch (target->os) {
868 case OsFreestanding:933 case OsFreestanding:
...@@ -1693,3 +1758,4 @@ bool target_supports_libunwind(const ZigTarget *target) {...@@ -1693,3 +1758,4 @@ bool target_supports_libunwind(const ZigTarget *target) {
1693 }1758 }
1694 return true;1759 return true;
1695}1760}
1761
src/target.hpp+1
...@@ -192,6 +192,7 @@ const char *target_arch_musl_name(ZigLLVM_ArchType arch);...@@ -192,6 +192,7 @@ const char *target_arch_musl_name(ZigLLVM_ArchType arch);
192bool target_supports_libunwind(const ZigTarget *target);192bool target_supports_libunwind(const ZigTarget *target);
193193
194uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);194uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);
195uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch);
195196
196size_t target_libc_count(void);197size_t target_libc_count(void);
197void target_libc_enum(size_t index, ZigTarget *out_target);198void target_libc_enum(size_t index, ZigTarget *out_target);
std/build.zig+1-1
...@@ -1802,7 +1802,7 @@ pub const LibExeObjStep = struct {...@@ -1802,7 +1802,7 @@ pub const LibExeObjStep = struct {
1802 try zig_args.append("--bundle-compiler-rt");1802 try zig_args.append("--bundle-compiler-rt");
1803 }1803 }
1804 if (self.disable_stack_probing) {1804 if (self.disable_stack_probing) {
1805 try zig_args.append("--disable-stack-probing");1805 try zig_args.append("-fno-stack-check");
1806 }1806 }
18071807
1808 switch (self.target) {1808 switch (self.target) {
std/coff.zig+46-6
...@@ -19,6 +19,7 @@ const IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;...@@ -19,6 +19,7 @@ const IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
19const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;19const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
2020
21const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;21const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
22const IMAGE_DEBUG_TYPE_CODEVIEW = 2;
22const DEBUG_DIRECTORY = 6;23const DEBUG_DIRECTORY = 6;
2324
24pub const CoffError = error{25pub const CoffError = error{
...@@ -28,6 +29,7 @@ pub const CoffError = error{...@@ -28,6 +29,7 @@ pub const CoffError = error{
28 MissingCoffSection,29 MissingCoffSection,
29};30};
3031
32// Official documentation of the format: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
31pub const Coff = struct {33pub const Coff = struct {
32 in_file: File,34 in_file: File,
33 allocator: *mem.Allocator,35 allocator: *mem.Allocator,
...@@ -120,16 +122,43 @@ pub const Coff = struct {...@@ -120,16 +122,43 @@ pub const Coff = struct {
120122
121 pub fn getPdbPath(self: *Coff, buffer: []u8) !usize {123 pub fn getPdbPath(self: *Coff, buffer: []u8) !usize {
122 try self.loadSections();124 try self.loadSections();
123 const header = (self.getSection(".rdata") orelse return error.MissingCoffSection).header;
124125
125 // The linker puts a chunk that contains the .pdb path right after the126 const header = blk: {
126 // debug_directory.127 if (self.getSection(".buildid")) |section| {
128 break :blk section.header;
129 } else if (self.getSection(".rdata")) |section| {
130 break :blk section.header;
131 } else {
132 return error.MissingCoffSection;
133 }
134 };
135
127 const debug_dir = &self.pe_header.data_directory[DEBUG_DIRECTORY];136 const debug_dir = &self.pe_header.data_directory[DEBUG_DIRECTORY];
128 const file_offset = debug_dir.virtual_address - header.virtual_address + header.pointer_to_raw_data;137 const file_offset = debug_dir.virtual_address - header.virtual_address + header.pointer_to_raw_data;
129 try self.in_file.seekTo(file_offset + debug_dir.size);
130138
131 var file_stream = self.in_file.inStream();139 var file_stream = self.in_file.inStream();
132 const in = &file_stream.stream;140 const in = &file_stream.stream;
141 try self.in_file.seekTo(file_offset);
142
143 // Find the correct DebugDirectoryEntry, and where its data is stored.
144 // It can be in any section.
145 const debug_dir_entry_count = debug_dir.size / @sizeOf(DebugDirectoryEntry);
146 var i: u32 = 0;
147 blk: while (i < debug_dir_entry_count) : (i += 1) {
148 const debug_dir_entry = try in.readStruct(DebugDirectoryEntry);
149 if (debug_dir_entry.type == IMAGE_DEBUG_TYPE_CODEVIEW) {
150 for (self.sections.toSlice()) |*section| {
151 const section_start = section.header.virtual_address;
152 const section_size = section.header.misc.virtual_size;
153 const rva = debug_dir_entry.address_of_raw_data;
154 const offset = rva - section_start;
155 if (section_start <= rva and offset < section_size and debug_dir_entry.size_of_data <= section_size - offset) {
156 try self.in_file.seekTo(section.header.pointer_to_raw_data + offset);
157 break :blk;
158 }
159 }
160 }
161 }
133162
134 var cv_signature: [4]u8 = undefined; // CodeView signature163 var cv_signature: [4]u8 = undefined; // CodeView signature
135 try in.readNoEof(cv_signature[0..]);164 try in.readNoEof(cv_signature[0..]);
...@@ -141,7 +170,7 @@ pub const Coff = struct {...@@ -141,7 +170,7 @@ pub const Coff = struct {
141170
142 // Finally read the null-terminated string.171 // Finally read the null-terminated string.
143 var byte = try in.readByte();172 var byte = try in.readByte();
144 var i: usize = 0;173 i = 0;
145 while (byte != 0 and i < buffer.len) : (i += 1) {174 while (byte != 0 and i < buffer.len) : (i += 1) {
146 buffer[i] = byte;175 buffer[i] = byte;
147 byte = try in.readByte();176 byte = try in.readByte();
...@@ -170,7 +199,7 @@ pub const Coff = struct {...@@ -170,7 +199,7 @@ pub const Coff = struct {
170 try self.sections.append(Section{199 try self.sections.append(Section{
171 .header = SectionHeader{200 .header = SectionHeader{
172 .name = name,201 .name = name,
173 .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) },202 .misc = SectionHeader.Misc{ .virtual_size = try in.readIntLittle(u32) },
174 .virtual_address = try in.readIntLittle(u32),203 .virtual_address = try in.readIntLittle(u32),
175 .size_of_raw_data = try in.readIntLittle(u32),204 .size_of_raw_data = try in.readIntLittle(u32),
176 .pointer_to_raw_data = try in.readIntLittle(u32),205 .pointer_to_raw_data = try in.readIntLittle(u32),
...@@ -214,6 +243,17 @@ const OptionalHeader = struct {...@@ -214,6 +243,17 @@ const OptionalHeader = struct {
214 data_directory: [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]DataDirectory,243 data_directory: [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]DataDirectory,
215};244};
216245
246const DebugDirectoryEntry = packed struct {
247 characteristiccs: u32,
248 time_date_stamp: u32,
249 major_version: u16,
250 minor_version: u16,
251 @"type": u32,
252 size_of_data: u32,
253 address_of_raw_data: u32,
254 pointer_to_raw_data: u32,
255};
256
217pub const Section = struct {257pub const Section = struct {
218 header: SectionHeader,258 header: SectionHeader,
219};259};
std/debug.zig+10-3
...@@ -375,7 +375,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres...@@ -375,7 +375,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
375 const obj_basename = fs.path.basename(mod.obj_file_name);375 const obj_basename = fs.path.basename(mod.obj_file_name);
376376
377 var symbol_i: usize = 0;377 var symbol_i: usize = 0;
378 const symbol_name = while (symbol_i != mod.symbols.len) {378 const symbol_name = if (!mod.populated) "???" else while (symbol_i != mod.symbols.len) {
379 const prefix = @ptrCast(*pdb.RecordPrefix, &mod.symbols[symbol_i]);379 const prefix = @ptrCast(*pdb.RecordPrefix, &mod.symbols[symbol_i]);
380 if (prefix.RecordLen < 2)380 if (prefix.RecordLen < 2)
381 return error.InvalidDebugInfo;381 return error.InvalidDebugInfo;
...@@ -858,8 +858,10 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -858,8 +858,10 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
858 const age = try pdb_stream.stream.readIntLittle(u32);858 const age = try pdb_stream.stream.readIntLittle(u32);
859 var guid: [16]u8 = undefined;859 var guid: [16]u8 = undefined;
860 try pdb_stream.stream.readNoEof(guid[0..]);860 try pdb_stream.stream.readNoEof(guid[0..]);
861 if (version != 20000404) // VC70, only value observed by LLVM team
862 return error.UnknownPDBVersion;
861 if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)863 if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)
862 return error.InvalidDebugInfo;864 return error.PDBMismatch;
863 // We validated the executable and pdb match.865 // We validated the executable and pdb match.
864866
865 const string_table_index = str_tab_index: {867 const string_table_index = str_tab_index: {
...@@ -903,13 +905,18 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -903,13 +905,18 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
903 return error.MissingDebugInfo;905 return error.MissingDebugInfo;
904 };906 };
905907
906 di.pdb.string_table = di.pdb.getStreamById(string_table_index) orelse return error.InvalidDebugInfo;908 di.pdb.string_table = di.pdb.getStreamById(string_table_index) orelse return error.MissingDebugInfo;
907 di.pdb.dbi = di.pdb.getStream(pdb.StreamType.Dbi) orelse return error.MissingDebugInfo;909 di.pdb.dbi = di.pdb.getStream(pdb.StreamType.Dbi) orelse return error.MissingDebugInfo;
908910
909 const dbi = di.pdb.dbi;911 const dbi = di.pdb.dbi;
910912
911 // Dbi Header913 // Dbi Header
912 const dbi_stream_header = try dbi.stream.readStruct(pdb.DbiStreamHeader);914 const dbi_stream_header = try dbi.stream.readStruct(pdb.DbiStreamHeader);
915 if (dbi_stream_header.VersionHeader != 19990903) // V70, only value observed by LLVM team
916 return error.UnknownPDBVersion;
917 if (dbi_stream_header.Age != age)
918 return error.UnmatchingPDB;
919
913 const mod_info_size = dbi_stream_header.ModInfoSize;920 const mod_info_size = dbi_stream_header.ModInfoSize;
914 const section_contrib_size = dbi_stream_header.SectionContributionSize;921 const section_contrib_size = dbi_stream_header.SectionContributionSize;
915922
std/fmt.zig+20-1
...@@ -371,9 +371,10 @@ pub fn formatType(...@@ -371,9 +371,10 @@ pub fn formatType(
371 return output(context, "{ ... }");371 return output(context, "{ ... }");
372 }372 }
373 comptime var field_i = 0;373 comptime var field_i = 0;
374 try output(context, "{");
374 inline while (field_i < @memberCount(T)) : (field_i += 1) {375 inline while (field_i < @memberCount(T)) : (field_i += 1) {
375 if (field_i == 0) {376 if (field_i == 0) {
376 try output(context, "{ .");377 try output(context, " .");
377 } else {378 } else {
378 try output(context, ", .");379 try output(context, ", .");
379 }380 }
...@@ -422,6 +423,9 @@ pub fn formatType(...@@ -422,6 +423,9 @@ pub fn formatType(
422 if (info.child == u8) {423 if (info.child == u8) {
423 return formatText(value, fmt, options, context, Errors, output);424 return formatText(value, fmt, options, context, Errors, output);
424 }425 }
426 if (value.len == 0) {
427 return format(context, Errors, output, "[0]{}", @typeName(T.Child));
428 }
425 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));429 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
426 },430 },
427 .Fn => {431 .Fn => {
...@@ -1436,6 +1440,21 @@ test "struct.self-referential" {...@@ -1436,6 +1440,21 @@ test "struct.self-referential" {
1436 try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", inst);1440 try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", inst);
1437}1441}
14381442
1443test "struct.zero-size" {
1444 const A = struct {
1445 fn foo() void {}
1446 };
1447 const B = struct {
1448 a: A,
1449 c: i32,
1450 };
1451
1452 const a = A{};
1453 const b = B{ .a = a, .c = 0 };
1454
1455 try testFmt("B{ .a = A{ }, .c = 0 }", "{}", b);
1456}
1457
1439test "bytes.hex" {1458test "bytes.hex" {
1440 const some_bytes = "\xCA\xFE\xBA\xBE";1459 const some_bytes = "\xCA\xFE\xBA\xBE";
1441 try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", some_bytes);1460 try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", some_bytes);
std/os.zig+16
...@@ -2053,6 +2053,22 @@ pub fn accessC(path: [*]const u8, mode: u32) AccessError!void {...@@ -2053,6 +2053,22 @@ pub fn accessC(path: [*]const u8, mode: u32) AccessError!void {
2053 }2053 }
2054}2054}
20552055
2056/// Call from Windows-specific code if you already have a UTF-16LE encoded, null terminated string.
2057/// Otherwise use `access` or `accessC`.
2058/// TODO currently this ignores `mode`.
2059pub fn accessW(path: [*]const u16, mode: u32) windows.GetFileAttributesError!void {
2060 const ret = try windows.GetFileAttributesW(path);
2061 if (ret != windows.INVALID_FILE_ATTRIBUTES) {
2062 return;
2063 }
2064 switch (windows.kernel32.GetLastError()) {
2065 windows.ERROR.FILE_NOT_FOUND => return error.FileNotFound,
2066 windows.ERROR.PATH_NOT_FOUND => return error.FileNotFound,
2067 windows.ERROR.ACCESS_DENIED => return error.PermissionDenied,
2068 else => |err| return windows.unexpectedError(err),
2069 }
2070}
2071
2056pub const PipeError = error{2072pub const PipeError = error{
2057 SystemFdQuotaExceeded,2073 SystemFdQuotaExceeded,
2058 ProcessFdQuotaExceeded,2074 ProcessFdQuotaExceeded,
std/pdb.zig+73-44
...@@ -499,45 +499,78 @@ const Msf = struct {...@@ -499,45 +499,78 @@ const Msf = struct {
499499
500 const superblock = try in.readStruct(SuperBlock);500 const superblock = try in.readStruct(SuperBlock);
501501
502 // Sanity checks
502 if (!mem.eql(u8, superblock.FileMagic, SuperBlock.file_magic))503 if (!mem.eql(u8, superblock.FileMagic, SuperBlock.file_magic))
503 return error.InvalidDebugInfo;504 return error.InvalidDebugInfo;
504505 if (superblock.FreeBlockMapBlock != 1 and superblock.FreeBlockMapBlock != 2)
506 return error.InvalidDebugInfo;
507 if (superblock.NumBlocks * superblock.BlockSize != try file.getEndPos())
508 return error.InvalidDebugInfo;
505 switch (superblock.BlockSize) {509 switch (superblock.BlockSize) {
506 // llvm only supports 4096 but we can handle any of these values510 // llvm only supports 4096 but we can handle any of these values
507 512, 1024, 2048, 4096 => {},511 512, 1024, 2048, 4096 => {},
508 else => return error.InvalidDebugInfo,512 else => return error.InvalidDebugInfo,
509 }513 }
510514
511 if (superblock.NumBlocks * superblock.BlockSize != try file.getEndPos())515 const dir_block_count = blockCountFromSize(superblock.NumDirectoryBytes, superblock.BlockSize);
512 return error.InvalidDebugInfo;516 if (dir_block_count > superblock.BlockSize / @sizeOf(u32))
517 return error.UnhandledBigDirectoryStream; // cf. BlockMapAddr comment.
513518
514 self.directory = try MsfStream.init(519 try file.seekTo(superblock.BlockSize * superblock.BlockMapAddr);
520 var dir_blocks = try allocator.alloc(u32, dir_block_count);
521 for (dir_blocks) |*b| {
522 b.* = try in.readIntLittle(u32);
523 }
524 self.directory = MsfStream.init(
515 superblock.BlockSize,525 superblock.BlockSize,
516 blockCountFromSize(superblock.NumDirectoryBytes, superblock.BlockSize),
517 superblock.BlockSize * superblock.BlockMapAddr,
518 file,526 file,
519 allocator,527 dir_blocks,
520 );528 );
521529
530 const begin = self.directory.pos;
522 const stream_count = try self.directory.stream.readIntLittle(u32);531 const stream_count = try self.directory.stream.readIntLittle(u32);
523
524 const stream_sizes = try allocator.alloc(u32, stream_count);532 const stream_sizes = try allocator.alloc(u32, stream_count);
525 for (stream_sizes) |*s| {533 defer allocator.free(stream_sizes);
534
535 // Microsoft's implementation uses u32(-1) for inexistant streams.
536 // These streams are not used, but still participate in the file
537 // and must be taken into account when resolving stream indices.
538 const Nil = 0xFFFFFFFF;
539 for (stream_sizes) |*s, i| {
526 const size = try self.directory.stream.readIntLittle(u32);540 const size = try self.directory.stream.readIntLittle(u32);
527 s.* = blockCountFromSize(size, superblock.BlockSize);541 s.* = if (size == Nil) 0 else blockCountFromSize(size, superblock.BlockSize);
528 }542 }
529543
530 self.streams = try allocator.alloc(MsfStream, stream_count);544 self.streams = try allocator.alloc(MsfStream, stream_count);
531 for (self.streams) |*stream, i| {545 for (self.streams) |*stream, i| {
532 stream.* = try MsfStream.init(546 const size = stream_sizes[i];
533 superblock.BlockSize,547 if (size == 0) {
534 stream_sizes[i],548 stream.* = MsfStream{
535 // MsfStream.init expects the file to be at the part where it reads [N]u32549 .blocks = [_]u32{},
536 try file.getPos(),550 };
537 file,551 } else {
538 allocator,552 var blocks = try allocator.alloc(u32, size);
539 );553 var j: u32 = 0;
554 while (j < size) : (j += 1) {
555 const block_id = try self.directory.stream.readIntLittle(u32);
556 const n = (block_id % superblock.BlockSize);
557 // 0 is for SuperBlock, 1 and 2 for FPMs.
558 if (block_id == 0 or n == 1 or n == 2 or block_id * superblock.BlockSize > try file.getEndPos())
559 return error.InvalidBlockIndex;
560 blocks[j] = block_id;
561 }
562
563 stream.* = MsfStream.init(
564 superblock.BlockSize,
565 file,
566 blocks,
567 );
568 }
540 }569 }
570
571 const end = self.directory.pos;
572 if (end - begin != superblock.NumDirectoryBytes)
573 return error.InvalidStreamDirectory;
541 }574 }
542};575};
543576
...@@ -574,7 +607,6 @@ const SuperBlock = packed struct {...@@ -574,7 +607,6 @@ const SuperBlock = packed struct {
574 NumDirectoryBytes: u32,607 NumDirectoryBytes: u32,
575608
576 Unknown: u32,609 Unknown: u32,
577
578 /// The index of a block within the MSF file. At this block is an array of610 /// The index of a block within the MSF file. At this block is an array of
579 /// ulittle32_t’s listing the blocks that the stream directory resides on.611 /// ulittle32_t’s listing the blocks that the stream directory resides on.
580 /// For large MSF files, the stream directory (which describes the block612 /// For large MSF files, the stream directory (which describes the block
...@@ -584,45 +616,41 @@ const SuperBlock = packed struct {...@@ -584,45 +616,41 @@ const SuperBlock = packed struct {
584 /// and the stream directory itself can be stitched together accordingly.616 /// and the stream directory itself can be stitched together accordingly.
585 /// The number of ulittle32_t’s in this array is given by617 /// The number of ulittle32_t’s in this array is given by
586 /// ceil(NumDirectoryBytes / BlockSize).618 /// ceil(NumDirectoryBytes / BlockSize).
619 // Note: microsoft-pdb code actually suggests this is a variable-length
620 // array. If the indices of blocks occupied by the Stream Directory didn't
621 // fit in one page, there would be other u32 following it.
622 // This would mean the Stream Directory is bigger than BlockSize / sizeof(u32)
623 // blocks. We're not even close to this with a 1GB pdb file, and LLVM didn't
624 // implement it so we're kind of safe making this assumption for now.
587 BlockMapAddr: u32,625 BlockMapAddr: u32,
588};626};
589627
590const MsfStream = struct {628const MsfStream = struct {
591 in_file: File,629 in_file: File = undefined,
592 pos: u64,630 pos: u64 = undefined,
593 blocks: []u32,631 blocks: []u32 = undefined,
594 block_size: u32,632 block_size: u32 = undefined,
595633
596 /// Implementation of InStream trait for Pdb.MsfStream634 /// Implementation of InStream trait for Pdb.MsfStream
597 stream: Stream,635 stream: Stream = undefined,
598636
599 pub const Error = @typeOf(read).ReturnType.ErrorSet;637 pub const Error = @typeOf(read).ReturnType.ErrorSet;
600 pub const Stream = io.InStream(Error);638 pub const Stream = io.InStream(Error);
601639
602 fn init(block_size: u32, block_count: u32, pos: u64, file: File, allocator: *mem.Allocator) !MsfStream {640 fn init(block_size: u32, file: File, blocks: []u32) MsfStream {
603 var stream = MsfStream{641 const stream = MsfStream{
604 .in_file = file,642 .in_file = file,
605 .pos = 0,643 .pos = 0,
606 .blocks = try allocator.alloc(u32, block_count),644 .blocks = blocks,
607 .block_size = block_size,645 .block_size = block_size,
608 .stream = Stream{ .readFn = readFn },646 .stream = Stream{ .readFn = readFn },
609 };647 };
610648
611 var file_stream = file.inStream();
612 const in = &file_stream.stream;
613 try file.seekTo(pos);
614
615 var i: u32 = 0;
616 while (i < block_count) : (i += 1) {
617 stream.blocks[i] = try in.readIntLittle(u32);
618 }
619
620 return stream;649 return stream;
621 }650 }
622651
623 fn readNullTermString(self: *MsfStream, allocator: *mem.Allocator) ![]u8 {652 fn readNullTermString(self: *MsfStream, allocator: *mem.Allocator) ![]u8 {
624 var list = ArrayList(u8).init(allocator);653 var list = ArrayList(u8).init(allocator);
625 defer list.deinit();
626 while (true) {654 while (true) {
627 const byte = try self.stream.readByte();655 const byte = try self.stream.readByte();
628 if (byte == 0) {656 if (byte == 0) {
...@@ -642,11 +670,12 @@ const MsfStream = struct {...@@ -642,11 +670,12 @@ const MsfStream = struct {
642 const in = &file_stream.stream;670 const in = &file_stream.stream;
643671
644 var size: usize = 0;672 var size: usize = 0;
645 for (buffer) |*byte| {673 var rem_buffer = buffer;
646 byte.* = try in.readByte();674 while (size < buffer.len) {
647675 const size_to_read = math.min(self.block_size - offset, rem_buffer.len);
648 offset += 1;676 size += try in.read(rem_buffer[0..size_to_read]);
649 size += 1;677 rem_buffer = buffer[size..];
678 offset += size_to_read;
650679
651 // If we're at the end of a block, go to the next one.680 // If we're at the end of a block, go to the next one.
652 if (offset == self.block_size) {681 if (offset == self.block_size) {
...@@ -657,8 +686,8 @@ const MsfStream = struct {...@@ -657,8 +686,8 @@ const MsfStream = struct {
657 }686 }
658 }687 }
659688
660 self.pos += size;689 self.pos += buffer.len;
661 return size;690 return buffer.len;
662 }691 }
663692
664 fn seekBy(self: *MsfStream, len: i64) !void {693 fn seekBy(self: *MsfStream, len: i64) !void {
std/rb.zig+2-1
...@@ -93,7 +93,8 @@ pub const Node = struct {...@@ -93,7 +93,8 @@ pub const Node = struct {
93 comptime {93 comptime {
94 assert(@alignOf(*Node) >= 2);94 assert(@alignOf(*Node) >= 2);
95 }95 }
96 return @intToPtr(*Node, node.parent_and_color & ~mask);96 const maybe_ptr = node.parent_and_color & ~mask;
97 return if (maybe_ptr == 0) null else @intToPtr(*Node, maybe_ptr);
97 }98 }
9899
99 fn setColor(node: *Node, color: Color) void {100 fn setColor(node: *Node, color: Color) void {
std/segmented_list.zig+18-11
...@@ -77,15 +77,19 @@ const Allocator = std.mem.Allocator;...@@ -77,15 +77,19 @@ const Allocator = std.mem.Allocator;
77pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type {77pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type {
78 return struct {78 return struct {
79 const Self = @This();79 const Self = @This();
80 const prealloc_exp = blk: {80 const ShelfIndex = std.math.Log2Int(usize);
81 // we don't use the prealloc_exp constant when prealloc_item_count is 0.
82 assert(prealloc_item_count != 0);
83 assert(std.math.isPowerOfTwo(prealloc_item_count));
8481
85 const value = std.math.log2_int(usize, prealloc_item_count);82 const prealloc_exp: ShelfIndex = blk: {
86 break :blk @typeOf(1)(value);83 // we don't use the prealloc_exp constant when prealloc_item_count is 0
84 // but lazy-init may still be triggered by other code so supply a value
85 if (prealloc_item_count == 0) {
86 break :blk 0;
87 } else {
88 assert(std.math.isPowerOfTwo(prealloc_item_count));
89 const value = std.math.log2_int(usize, prealloc_item_count);
90 break :blk value;
91 }
87 };92 };
88 const ShelfIndex = std.math.Log2Int(usize);
8993
90 prealloc_segment: [prealloc_item_count]T,94 prealloc_segment: [prealloc_item_count]T,
91 dynamic_segments: [][*]T,95 dynamic_segments: [][*]T,
...@@ -157,11 +161,12 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type...@@ -157,11 +161,12 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
157161
158 /// Grows or shrinks capacity to match usage.162 /// Grows or shrinks capacity to match usage.
159 pub fn setCapacity(self: *Self, new_capacity: usize) !void {163 pub fn setCapacity(self: *Self, new_capacity: usize) !void {
160 if (new_capacity <= usize(1) << (prealloc_exp + self.dynamic_segments.len)) {164 if (prealloc_item_count != 0) {
161 return self.shrinkCapacity(new_capacity);165 if (new_capacity <= usize(1) << (prealloc_exp + @intCast(ShelfIndex, self.dynamic_segments.len))) {
162 } else {166 return self.shrinkCapacity(new_capacity);
163 return self.growCapacity(new_capacity);167 }
164 }168 }
169 return self.growCapacity(new_capacity);
165 }170 }
166171
167 /// Only grows capacity, or retains current capacity172 /// Only grows capacity, or retains current capacity
...@@ -399,4 +404,6 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {...@@ -399,4 +404,6 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
399 testing.expect(item == i);404 testing.expect(item == i);
400 list.shrinkCapacity(list.len);405 list.shrinkCapacity(list.len);
401 }406 }
407
408 try list.setCapacity(0);
402}409}
std/special/start.zig+4-4
...@@ -35,13 +35,13 @@ nakedcc fn _start() noreturn {...@@ -35,13 +35,13 @@ nakedcc fn _start() noreturn {
3535
36 switch (builtin.arch) {36 switch (builtin.arch) {
37 .x86_64 => {37 .x86_64 => {
38 argc_ptr = asm ("lea (%%rsp), %[argc]"38 argc_ptr = asm (""
39 : [argc] "=r" (-> [*]usize)39 : [argc] "={rsp}" (-> [*]usize)
40 );40 );
41 },41 },
42 .i386 => {42 .i386 => {
43 argc_ptr = asm ("lea (%%esp), %[argc]"43 argc_ptr = asm (""
44 : [argc] "=r" (-> [*]usize)44 : [argc] "={esp}" (-> [*]usize)
45 );45 );
46 },46 },
47 .aarch64, .aarch64_be => {47 .aarch64, .aarch64_be => {
std/std.zig+1
...@@ -105,6 +105,7 @@ test "std" {...@@ -105,6 +105,7 @@ test "std" {
105 _ = @import("packed_int_array.zig");105 _ = @import("packed_int_array.zig");
106 _ = @import("priority_queue.zig");106 _ = @import("priority_queue.zig");
107 _ = @import("rand.zig");107 _ = @import("rand.zig");
108 _ = @import("rb.zig");
108 _ = @import("sort.zig");109 _ = @import("sort.zig");
109 _ = @import("testing.zig");110 _ = @import("testing.zig");
110 _ = @import("thread.zig");111 _ = @import("thread.zig");
test/compile_errors.zig+8-8
...@@ -219,7 +219,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -219,7 +219,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
219 \\ return error.OutOfMemory;219 \\ return error.OutOfMemory;
220 \\}220 \\}
221 ,221 ,
222 "tmp.zig:2:7: error: error is discarded",222 "tmp.zig:2:12: error: error is discarded",
223 );223 );
224224
225 cases.add(225 cases.add(
...@@ -2758,7 +2758,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2758,7 +2758,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2758 \\ 3 = 3;2758 \\ 3 = 3;
2759 \\}2759 \\}
2760 ,2760 ,
2761 "tmp.zig:2:7: error: cannot assign to constant",2761 "tmp.zig:2:9: error: cannot assign to constant",
2762 );2762 );
27632763
2764 cases.add(2764 cases.add(
...@@ -2768,7 +2768,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2768,7 +2768,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2768 \\ a = 4;2768 \\ a = 4;
2769 \\}2769 \\}
2770 ,2770 ,
2771 "tmp.zig:3:7: error: cannot assign to constant",2771 "tmp.zig:3:9: error: cannot assign to constant",
2772 );2772 );
27732773
2774 cases.add(2774 cases.add(
...@@ -2838,7 +2838,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2838,7 +2838,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2838 \\}2838 \\}
2839 \\export fn entry() void { f(); }2839 \\export fn entry() void { f(); }
2840 ,2840 ,
2841 "tmp.zig:3:7: error: cannot assign to constant",2841 "tmp.zig:3:9: error: cannot assign to constant",
2842 );2842 );
28432843
2844 cases.add(2844 cases.add(
...@@ -3901,7 +3901,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3901,7 +3901,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3901 \\3901 \\
3902 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }3902 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }
3903 ,3903 ,
3904 "tmp.zig:6:24: error: unable to evaluate constant expression",3904 "tmp.zig:6:26: error: unable to evaluate constant expression",
3905 "tmp.zig:4:17: note: called from here",3905 "tmp.zig:4:17: note: called from here",
3906 );3906 );
39073907
...@@ -4151,7 +4151,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4151,7 +4151,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4151 \\ cstr[0] = 'W';4151 \\ cstr[0] = 'W';
4152 \\}4152 \\}
4153 ,4153 ,
4154 "tmp.zig:3:11: error: cannot assign to constant",4154 "tmp.zig:3:13: error: cannot assign to constant",
4155 );4155 );
41564156
4157 cases.add(4157 cases.add(
...@@ -4161,7 +4161,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4161,7 +4161,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4161 \\ cstr[0] = 'W';4161 \\ cstr[0] = 'W';
4162 \\}4162 \\}
4163 ,4163 ,
4164 "tmp.zig:3:11: error: cannot assign to constant",4164 "tmp.zig:3:13: error: cannot assign to constant",
4165 );4165 );
41664166
4167 cases.add(4167 cases.add(
...@@ -4309,7 +4309,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4309,7 +4309,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4309 \\ f.field = 0;4309 \\ f.field = 0;
4310 \\}4310 \\}
4311 ,4311 ,
4312 "tmp.zig:6:13: error: cannot assign to constant",4312 "tmp.zig:6:15: error: cannot assign to constant",
4313 );4313 );
43144314
4315 cases.add(4315 cases.add(
test/stage1/behavior/atomics.zig+31
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
3const builtin = @import("builtin");4const builtin = @import("builtin");
4const AtomicRmwOp = builtin.AtomicRmwOp;5const AtomicRmwOp = builtin.AtomicRmwOp;
5const AtomicOrder = builtin.AtomicOrder;6const AtomicOrder = builtin.AtomicOrder;
...@@ -69,3 +70,33 @@ test "cmpxchg with ptr" {...@@ -69,3 +70,33 @@ test "cmpxchg with ptr" {
69 expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);70 expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
70 expect(x == &data2);71 expect(x == &data2);
71}72}
73
74// TODO this test is disabled until this issue is resolved:
75// https://github.com/ziglang/zig/issues/2883
76// otherwise cross compiling will result in:
77// lld: error: undefined symbol: __sync_val_compare_and_swap_16
78//test "128-bit cmpxchg" {
79// var x: u128 align(16) = 1234; // TODO: https://github.com/ziglang/zig/issues/2987
80// if (@cmpxchgWeak(u128, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
81// expect(x1 == 1234);
82// } else {
83// @panic("cmpxchg should have failed");
84// }
85//
86// while (@cmpxchgWeak(u128, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
87// expect(x1 == 1234);
88// }
89// expect(x == 5678);
90//
91// expect(@cmpxchgStrong(u128, &x, 5678, 42, .SeqCst, .SeqCst) == null);
92// expect(x == 42);
93//}
94
95test "cmpxchg with ignored result" {
96 var x: i32 = 1234;
97 var ptr = &x;
98
99 _ = @cmpxchgStrong(i32, &x, 1234, 5678, .Monotonic, .Monotonic);
100
101 expectEqual(i32(5678), x);
102}
test/stage1/behavior/eval.zig+10
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
3const builtin = @import("builtin");4const builtin = @import("builtin");
45
5test "compile time recursion" {6test "compile time recursion" {
...@@ -794,3 +795,12 @@ test "no undeclared identifier error in unanalyzed branches" {...@@ -794,3 +795,12 @@ test "no undeclared identifier error in unanalyzed branches" {
794 lol_this_doesnt_exist = nonsense;795 lol_this_doesnt_exist = nonsense;
795 }796 }
796}797}
798
799test "comptime assign int to optional int" {
800 comptime {
801 var x: ?i32 = null;
802 x = 2;
803 x.? *= 10;
804 expectEqual(20, x.?);
805 }
806}
test/stage1/behavior/fn.zig+19
...@@ -228,3 +228,22 @@ test "implicit cast fn call result to optional in field result" {...@@ -228,3 +228,22 @@ test "implicit cast fn call result to optional in field result" {
228 S.entry();228 S.entry();
229 comptime S.entry();229 comptime S.entry();
230}230}
231
232test "discard the result of a function that returns a struct" {
233 const S = struct {
234 fn entry() void {
235 _ = func();
236 }
237
238 fn func() Foo {
239 return undefined;
240 }
241
242 const Foo = struct {
243 a: u64,
244 b: u64,
245 };
246 };
247 S.entry();
248 comptime S.entry();
249}