| author | |
| committer | |
| log | b3b6a98451a9703dc15a1ee5f48acde23de3c491 |
| tree | 73f175e743d792e843adb60f9e33a4fad52c3a97 |
| parent | f07f09a373639ae8f1e46fb7beef239f7f85f57d |
| parent | b2d94f9af2968e01bd3d8db38c9ae1992bbd3678 |
| signature | Commit is signed but in an unrecognized format. |
20 files changed, 421 insertions(+), 142 deletions(-)
CMakeLists.txt+10-11| ... | ... | @@ -209,7 +209,7 @@ else() |
| 209 | 209 | else() |
| 210 | 210 | set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Wno-comment") |
| 211 | 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 | 213 | endif() |
| 214 | 214 | endif() |
| 215 | 215 | set_target_properties(embedded_lld_lib PROPERTIES |
| ... | ... | @@ -511,19 +511,23 @@ set(OPTIMIZED_C_FLAGS "-std=c99 -O3") |
| 511 | 511 | |
| 512 | 512 | set(EXE_LDFLAGS " ") |
| 513 | 513 | if(MSVC) |
| 514 | set(EXE_LDFLAGS "/STACK:16777216") | |
| 514 | set(EXE_LDFLAGS "${EXE_LDFLAGS} /STACK:16777216") | |
| 515 | 515 | elseif(MINGW) |
| 516 | 516 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -Wl,--stack,16777216") |
| 517 | 517 | endif() |
| 518 | 518 | |
| 519 | 519 | if(ZIG_STATIC) |
| 520 | 520 | if(APPLE) |
| 521 | set(EXE_LDFLAGS "-static-libgcc -static-libstdc++") | |
| 521 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -static-libgcc -static-libstdc++") | |
| 522 | 522 | elseif(MINGW) |
| 523 | set(EXE_LDFLAGS "-static-libgcc -static-libstdc++ -Wl,-Bstatic,--whole-archive -lwinpthread -lz3 -lz -lgomp -Wl,--no-whole-archive") | |
| 524 | else() | |
| 525 | set(EXE_LDFLAGS "-static") | |
| 523 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -static-libgcc -static-libstdc++ -Wl,-Bstatic, -lwinpthread -lz3 -lz -lgomp") | |
| 524 | elseif(NOT MSVC) | |
| 525 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -static") | |
| 526 | 526 | endif() |
| 527 | else() | |
| 528 | if(MINGW) | |
| 529 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -lz3") | |
| 530 | endif() | |
| 527 | 531 | endif() |
| 528 | 532 | |
| 529 | 533 | if(ZIG_TEST_COVERAGE) |
| ... | ... | @@ -559,11 +563,6 @@ if(NOT MSVC) |
| 559 | 563 | target_link_libraries(compiler LINK_PUBLIC ${LIBXML2}) |
| 560 | 564 | endif() |
| 561 | 565 | |
| 562 | if(MINGW) | |
| 563 | find_library(Z3_LIBRARIES NAMES z3 z3.dll) | |
| 564 | target_link_libraries(compiler LINK_PUBLIC ${Z3_LIBRARIES}) | |
| 565 | endif() | |
| 566 | ||
| 567 | 566 | if(ZIG_DIA_GUIDS_LIB) |
| 568 | 567 | target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB}) |
| 569 | 568 | endif() |
src/all_types.hpp+2| ... | ... | @@ -2529,6 +2529,7 @@ struct IrInstructionLoadPtrGen { |
| 2529 | 2529 | struct IrInstructionStorePtr { |
| 2530 | 2530 | IrInstruction base; |
| 2531 | 2531 | |
| 2532 | bool allow_write_through_const; | |
| 2532 | 2533 | IrInstruction *ptr; |
| 2533 | 2534 | IrInstruction *value; |
| 2534 | 2535 | }; |
| ... | ... | @@ -3630,6 +3631,7 @@ enum ResultLocId { |
| 3630 | 3631 | struct ResultLoc { |
| 3631 | 3632 | ResultLocId id; |
| 3632 | 3633 | bool written; |
| 3634 | bool allow_write_through_const; | |
| 3633 | 3635 | IrInstruction *resolved_loc; // result ptr |
| 3634 | 3636 | IrInstruction *source_instruction; |
| 3635 | 3637 | 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 | 4355 | return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, ""); |
| 4356 | 4356 | } |
| 4357 | 4357 | |
| 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 | 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); | |
| 4360 | 4366 | |
| 4361 | 4367 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); |
| 4362 | 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 | 188 | static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, |
| 189 | 189 | ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime); |
| 190 | 190 | static 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); | |
| 192 | 193 | static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, |
| 193 | 194 | IrInstruction *base_ptr, bool safety_check_on, bool initializing); |
| 194 | 195 | static 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 | 197 | static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr, |
| 197 | 198 | IrInstruction *base_ptr, bool initializing); |
| 198 | 199 | static 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); | |
| 200 | 201 | static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 201 | 202 | IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node, |
| 202 | 203 | LVal lval, ResultLoc *parent_result_loc); |
| ... | ... | @@ -1564,7 +1565,7 @@ static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode |
| 1564 | 1565 | return &unreachable_instruction->base; |
| 1565 | 1566 | } |
| 1566 | 1567 | |
| 1567 | static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1568 | static IrInstructionStorePtr *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1568 | 1569 | IrInstruction *ptr, IrInstruction *value) |
| 1569 | 1570 | { |
| 1570 | 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 | 1577 | ir_ref_instruction(ptr, irb->current_basic_block); |
| 1577 | 1578 | ir_ref_instruction(value, irb->current_basic_block); |
| 1578 | 1579 | |
| 1579 | return &instruction->base; | |
| 1580 | return instruction; | |
| 1580 | 1581 | } |
| 1581 | 1582 | |
| 1582 | 1583 | static 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 | 3793 | |
| 3793 | 3794 | static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 3794 | 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); | |
| 3796 | 3804 | |
| 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 | 3808 | return irb->codegen->invalid_instruction; |
| 3799 | 3809 | |
| 3800 | ir_build_store_ptr(irb, scope, node, lvalue, rvalue); | |
| 3801 | 3810 | return ir_build_const_void(irb, scope, node); |
| 3802 | 3811 | } |
| 3803 | 3812 | |
| ... | ... | @@ -5836,6 +5845,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A |
| 5836 | 5845 | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); |
| 5837 | 5846 | result_loc_inst->base.id = ResultLocIdInstruction; |
| 5838 | 5847 | result_loc_inst->base.source_instruction = field_ptr; |
| 5848 | result_loc_inst->base.allow_write_through_const = true; | |
| 5839 | 5849 | ir_ref_instruction(field_ptr, irb->current_basic_block); |
| 5840 | 5850 | ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); |
| 5841 | 5851 | |
| ... | ... | @@ -5874,6 +5884,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A |
| 5874 | 5884 | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); |
| 5875 | 5885 | result_loc_inst->base.id = ResultLocIdInstruction; |
| 5876 | 5886 | result_loc_inst->base.source_instruction = elem_ptr; |
| 5887 | result_loc_inst->base.allow_write_through_const = true; | |
| 5877 | 5888 | ir_ref_instruction(elem_ptr, irb->current_basic_block); |
| 5878 | 5889 | ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); |
| 5879 | 5890 | |
| ... | ... | @@ -6431,7 +6442,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 6431 | 6442 | |
| 6432 | 6443 | ir_set_cursor_at_end_and_append_block(irb, continue_block); |
| 6433 | 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 | 6446 | ir_build_br(irb, child_scope, node, cond_block, is_comptime); |
| 6436 | 6447 | |
| 6437 | 6448 | IrInstruction *else_result = nullptr; |
| ... | ... | @@ -10344,7 +10355,8 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc |
| 10344 | 10355 | } |
| 10345 | 10356 | |
| 10346 | 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 | 10360 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 10349 | 10361 | return result_loc_inst; |
| 10350 | 10362 | } |
| ... | ... | @@ -10804,7 +10816,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so |
| 10804 | 10816 | } |
| 10805 | 10817 | IrInstruction *result_loc_inst = nullptr; |
| 10806 | 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 | 10820 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 10809 | 10821 | return result_loc_inst; |
| 10810 | 10822 | } |
| ... | ... | @@ -10847,7 +10859,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction |
| 10847 | 10859 | IrInstruction *result_loc_inst; |
| 10848 | 10860 | if (handle_is_ptr(wanted_type)) { |
| 10849 | 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 | 10863 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 10852 | 10864 | return result_loc_inst; |
| 10853 | 10865 | } |
| ... | ... | @@ -10959,7 +10971,7 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so |
| 10959 | 10971 | IrInstruction *result_loc_inst; |
| 10960 | 10972 | if (handle_is_ptr(wanted_type)) { |
| 10961 | 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 | 10975 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 10964 | 10976 | return result_loc_inst; |
| 10965 | 10977 | } |
| ... | ... | @@ -11032,7 +11044,8 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi |
| 11032 | 11044 | |
| 11033 | 11045 | IrInstruction *result_loc; |
| 11034 | 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 | 11049 | } else { |
| 11037 | 11050 | result_loc = nullptr; |
| 11038 | 11051 | } |
| ... | ... | @@ -11076,7 +11089,8 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s |
| 11076 | 11089 | if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false); |
| 11077 | 11090 | |
| 11078 | 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 | 11094 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 11081 | 11095 | return result_loc_inst; |
| 11082 | 11096 | } |
| ... | ... | @@ -11732,7 +11746,8 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction * |
| 11732 | 11746 | if (result_loc == nullptr) { |
| 11733 | 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 | 11751 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 11737 | 11752 | return result_loc_inst; |
| 11738 | 11753 | } |
| ... | ... | @@ -12334,7 +12349,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 12334 | 12349 | IrInstruction *result_loc_inst; |
| 12335 | 12350 | if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) { |
| 12336 | 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 | 12354 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 12339 | 12355 | return result_loc_inst; |
| 12340 | 12356 | } |
| ... | ... | @@ -14072,7 +14088,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, |
| 14072 | 14088 | // instruction. |
| 14073 | 14089 | assert(deref->value.special != ConstValSpecialRuntime); |
| 14074 | 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 | } |
| 14077 | 14093 | |
| 14078 | 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 | 14572 | |
| 14557 | 14573 | if (peer_parent->peers.length == 1) { |
| 14558 | 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 | 14576 | result_peer->suspend_pos.basic_block_index = SIZE_MAX; |
| 14561 | 14577 | result_peer->suspend_pos.instruction_index = SIZE_MAX; |
| 14562 | 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 | 14592 | if (peer_parent->skipped) { |
| 14577 | 14593 | if (non_null_comptime) { |
| 14578 | 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 | 14597 | return nullptr; |
| 14582 | 14598 | } |
| ... | ... | @@ -14594,7 +14610,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe |
| 14594 | 14610 | } |
| 14595 | 14611 | |
| 14596 | 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 | 14614 | if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || |
| 14599 | 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 | 14660 | } |
| 14645 | 14661 | |
| 14646 | 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 | 14664 | if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || |
| 14649 | 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 | 14689 | |
| 14674 | 14690 | static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr, |
| 14675 | 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 | 14701 | IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type, |
| 14679 | 14702 | value, force_runtime, non_null_comptime); |
| 14680 | 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 | 14752 | if (type_is_invalid(implicit_elem_type)) |
| 14730 | 14753 | return ira->codegen->invalid_instruction; |
| 14731 | 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 | 14756 | if (result_loc != nullptr) |
| 14734 | 14757 | return result_loc; |
| 14735 | 14758 | |
| ... | ... | @@ -14738,7 +14761,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn |
| 14738 | 14761 | instruction->result_loc->id == ResultLocIdReturn) |
| 14739 | 14762 | { |
| 14740 | 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 | 14765 | if (result_loc != nullptr && |
| 14743 | 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 | 14823 | |
| 14801 | 14824 | ZigType *frame_type = get_coro_frame_type(ira->codegen, fn_entry); |
| 14802 | 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 | 14827 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { |
| 14805 | 14828 | return result_loc; |
| 14806 | 14829 | } |
| ... | ... | @@ -15015,7 +15038,7 @@ no_mem_slot: |
| 15015 | 15038 | } |
| 15016 | 15039 | |
| 15017 | 15040 | static 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 | 15043 | assert(ptr->value.type->id == ZigTypeIdPointer); |
| 15021 | 15044 | |
| ... | ... | @@ -15031,7 +15054,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source |
| 15031 | 15054 | |
| 15032 | 15055 | ZigType *child_type = ptr->value.type->data.pointer.child_type; |
| 15033 | 15056 | |
| 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 | 15058 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); |
| 15036 | 15059 | return ira->codegen->invalid_instruction; |
| 15037 | 15060 | } |
| ... | ... | @@ -15110,10 +15133,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source |
| 15110 | 15133 | break; |
| 15111 | 15134 | } |
| 15112 | 15135 | |
| 15113 | IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, | |
| 15114 | ptr, value); | |
| 15115 | result->value.type = ira->codegen->builtin_types.entry_void; | |
| 15116 | return result; | |
| 15136 | IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope, | |
| 15137 | source_instr->source_node, ptr, value); | |
| 15138 | return &store_ptr->base; | |
| 15117 | 15139 | } |
| 15118 | 15140 | |
| 15119 | 15141 | static 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 | 15540 | IrInstruction *result_loc; |
| 15519 | 15541 | if (handle_is_ptr(impl_fn_type_id->return_type)) { |
| 15520 | 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 | 15544 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || |
| 15523 | 15545 | instr_is_unreachable(result_loc))) |
| 15524 | 15546 | { |
| ... | ... | @@ -15635,7 +15657,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c |
| 15635 | 15657 | IrInstruction *result_loc; |
| 15636 | 15658 | if (handle_is_ptr(return_type)) { |
| 15637 | 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 | 15661 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { |
| 15640 | 15662 | return result_loc; |
| 15641 | 15663 | } |
| ... | ... | @@ -16154,7 +16176,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh |
| 16154 | 16176 | |
| 16155 | 16177 | // In case resolving the parent activates a suspend, do it now |
| 16156 | 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 | 16180 | if (parent_result_loc != nullptr && |
| 16159 | 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 | 16633 | return result; |
| 16612 | 16634 | } else if (is_slice(array_type)) { |
| 16613 | 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 | 16637 | if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { |
| 16615 | 16638 | IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, |
| 16616 | 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 | 16820 | return ira->codegen->invalid_instruction; |
| 16798 | 16821 | if (type_is_invalid(struct_val->type)) |
| 16799 | 16822 | return ira->codegen->invalid_instruction; |
| 16800 | if (struct_val->special == ConstValSpecialUndef && initializing) { | |
| 16823 | if (initializing && struct_val->special == ConstValSpecialUndef) { | |
| 16801 | 16824 | struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count); |
| 16802 | 16825 | struct_val->special = ConstValSpecialStatic; |
| 16803 | 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 | 17418 | if (type_is_invalid(value->value.type)) |
| 17396 | 17419 | return ira->codegen->invalid_instruction; |
| 17397 | 17420 | |
| 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 | } |
| 17400 | 17423 | |
| 17401 | 17424 | static 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 | 17922 | if (optional_val == nullptr) |
| 17900 | 17923 | return ira->codegen->invalid_instruction; |
| 17901 | 17924 | |
| 17902 | if (initializing && optional_val->special == ConstValSpecialUndef) { | |
| 17925 | if (initializing) { | |
| 17903 | 17926 | switch (type_has_one_possible_value(ira->codegen, child_type)) { |
| 17904 | 17927 | case OnePossibleValueInvalid: |
| 17905 | 17928 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -18805,7 +18828,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 18805 | 18828 | |
| 18806 | 18829 | IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc, |
| 18807 | 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 | 18832 | if (instr_is_comptime(field_ptr) && field_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) { |
| 18810 | 18833 | const_ptrs.append(field_ptr); |
| 18811 | 18834 | } else { |
| ... | ... | @@ -18822,7 +18845,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 18822 | 18845 | IrInstruction *field_result_loc = const_ptrs.at(i); |
| 18823 | 18846 | IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr); |
| 18824 | 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 | 18972 | assert(elem_result_loc->value.special == ConstValSpecialStatic); |
| 18950 | 18973 | IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr); |
| 18951 | 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 | 20669 | IrInstruction *result_loc; |
| 20647 | 20670 | if (handle_is_ptr(result_type)) { |
| 20648 | 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 | 20673 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { |
| 20651 | 20674 | return result_loc; |
| 20652 | 20675 | } |
| ... | ... | @@ -20903,7 +20926,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru |
| 20903 | 20926 | } |
| 20904 | 20927 | |
| 20905 | 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 | 20930 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { |
| 20908 | 20931 | return result_loc; |
| 20909 | 20932 | } |
| ... | ... | @@ -20980,7 +21003,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct |
| 20980 | 21003 | } |
| 20981 | 21004 | |
| 20982 | 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 | 21007 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { |
| 20985 | 21008 | return result_loc; |
| 20986 | 21009 | } |
| ... | ... | @@ -21722,7 +21745,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 21722 | 21745 | } |
| 21723 | 21746 | |
| 21724 | 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 | 21749 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { |
| 21727 | 21750 | return result_loc; |
| 21728 | 21751 | } |
| ... | ... | @@ -22405,7 +22428,7 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct |
| 22405 | 22428 | ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); |
| 22406 | 22429 | if (err_union_val == nullptr) |
| 22407 | 22430 | return ira->codegen->invalid_instruction; |
| 22408 | if (err_union_val->special == ConstValSpecialUndef && initializing) { | |
| 22431 | if (initializing && err_union_val->special == ConstValSpecialUndef) { | |
| 22409 | 22432 | ConstExprValue *vals = create_const_vals(2); |
| 22410 | 22433 | ConstExprValue *err_set_val = &vals[0]; |
| 22411 | 22434 | ConstExprValue *payload_val = &vals[1]; |
| ... | ... | @@ -23700,10 +23723,11 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op |
| 23700 | 23723 | operand_type->data.integral.bit_count)); |
| 23701 | 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 | 23728 | ir_add_error(ira, op, |
| 23705 | buf_sprintf("expected integer type pointer size or smaller, found %" PRIu32 "-bit integer type", | |
| 23706 | operand_type->data.integral.bit_count)); | |
| 23729 | buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type", | |
| 23730 | max_atomic_bits, operand_type->data.integral.bit_count)); | |
| 23707 | 23731 | return ira->codegen->builtin_types.entry_invalid; |
| 23708 | 23732 | } |
| 23709 | 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 | 24317 | |
| 24294 | 24318 | bool was_written = instruction->result_loc->written; |
| 24295 | 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 | 24321 | if (result_loc != nullptr) { |
| 24298 | 24322 | if (type_is_invalid(result_loc->value.type)) |
| 24299 | 24323 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -24301,7 +24325,8 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct |
| 24301 | 24325 | return result_loc; |
| 24302 | 24326 | |
| 24303 | 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 | 24330 | if (type_is_invalid(store_ptr->value.type)) { |
| 24306 | 24331 | return ira->codegen->invalid_instruction; |
| 24307 | 24332 | } |
| ... | ... | @@ -24325,7 +24350,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst |
| 24325 | 24350 | return operand; |
| 24326 | 24351 | |
| 24327 | 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 | 24354 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) |
| 24330 | 24355 | return result_loc; |
| 24331 | 24356 |
src/target.cpp+66| ... | ... | @@ -863,6 +863,71 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) { |
| 863 | 863 | zig_unreachable(); |
| 864 | 864 | } |
| 865 | 865 | |
| 866 | uint32_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 | ||
| 866 | 931 | uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 867 | 932 | switch (target->os) { |
| 868 | 933 | case OsFreestanding: |
| ... | ... | @@ -1693,3 +1758,4 @@ bool target_supports_libunwind(const ZigTarget *target) { |
| 1693 | 1758 | } |
| 1694 | 1759 | return true; |
| 1695 | 1760 | } |
| 1761 |
src/target.hpp+1| ... | ... | @@ -192,6 +192,7 @@ const char *target_arch_musl_name(ZigLLVM_ArchType arch); |
| 192 | 192 | bool target_supports_libunwind(const ZigTarget *target); |
| 193 | 193 | |
| 194 | 194 | uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch); |
| 195 | uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch); | |
| 195 | 196 | |
| 196 | 197 | size_t target_libc_count(void); |
| 197 | 198 | void target_libc_enum(size_t index, ZigTarget *out_target); |
std/build.zig+1-1| ... | ... | @@ -1802,7 +1802,7 @@ pub const LibExeObjStep = struct { |
| 1802 | 1802 | try zig_args.append("--bundle-compiler-rt"); |
| 1803 | 1803 | } |
| 1804 | 1804 | if (self.disable_stack_probing) { |
| 1805 | try zig_args.append("--disable-stack-probing"); | |
| 1805 | try zig_args.append("-fno-stack-check"); | |
| 1806 | 1806 | } |
| 1807 | 1807 | |
| 1808 | 1808 | switch (self.target) { |
std/coff.zig+46-6| ... | ... | @@ -19,6 +19,7 @@ const IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b; |
| 19 | 19 | const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b; |
| 20 | 20 | |
| 21 | 21 | const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16; |
| 22 | const IMAGE_DEBUG_TYPE_CODEVIEW = 2; | |
| 22 | 23 | const DEBUG_DIRECTORY = 6; |
| 23 | 24 | |
| 24 | 25 | pub const CoffError = error{ |
| ... | ... | @@ -28,6 +29,7 @@ pub const CoffError = error{ |
| 28 | 29 | MissingCoffSection, |
| 29 | 30 | }; |
| 30 | 31 | |
| 32 | // Official documentation of the format: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format | |
| 31 | 33 | pub const Coff = struct { |
| 32 | 34 | in_file: File, |
| 33 | 35 | allocator: *mem.Allocator, |
| ... | ... | @@ -120,16 +122,43 @@ pub const Coff = struct { |
| 120 | 122 | |
| 121 | 123 | pub fn getPdbPath(self: *Coff, buffer: []u8) !usize { |
| 122 | 124 | try self.loadSections(); |
| 123 | const header = (self.getSection(".rdata") orelse return error.MissingCoffSection).header; | |
| 124 | 125 | |
| 125 | // The linker puts a chunk that contains the .pdb path right after the | |
| 126 | // debug_directory. | |
| 126 | const header = blk: { | |
| 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 | 136 | const debug_dir = &self.pe_header.data_directory[DEBUG_DIRECTORY]; |
| 128 | 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); | |
| 130 | 138 | |
| 131 | 139 | var file_stream = self.in_file.inStream(); |
| 132 | 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 | } | |
| 133 | 162 | |
| 134 | 163 | var cv_signature: [4]u8 = undefined; // CodeView signature |
| 135 | 164 | try in.readNoEof(cv_signature[0..]); |
| ... | ... | @@ -141,7 +170,7 @@ pub const Coff = struct { |
| 141 | 170 | |
| 142 | 171 | // Finally read the null-terminated string. |
| 143 | 172 | var byte = try in.readByte(); |
| 144 | var i: usize = 0; | |
| 173 | i = 0; | |
| 145 | 174 | while (byte != 0 and i < buffer.len) : (i += 1) { |
| 146 | 175 | buffer[i] = byte; |
| 147 | 176 | byte = try in.readByte(); |
| ... | ... | @@ -170,7 +199,7 @@ pub const Coff = struct { |
| 170 | 199 | try self.sections.append(Section{ |
| 171 | 200 | .header = SectionHeader{ |
| 172 | 201 | .name = name, |
| 173 | .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) }, | |
| 202 | .misc = SectionHeader.Misc{ .virtual_size = try in.readIntLittle(u32) }, | |
| 174 | 203 | .virtual_address = try in.readIntLittle(u32), |
| 175 | 204 | .size_of_raw_data = try in.readIntLittle(u32), |
| 176 | 205 | .pointer_to_raw_data = try in.readIntLittle(u32), |
| ... | ... | @@ -214,6 +243,17 @@ const OptionalHeader = struct { |
| 214 | 243 | data_directory: [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]DataDirectory, |
| 215 | 244 | }; |
| 216 | 245 | |
| 246 | const 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 | ||
| 217 | 257 | pub const Section = struct { |
| 218 | 258 | header: SectionHeader, |
| 219 | 259 | }; |
std/debug.zig+10-3| ... | ... | @@ -375,7 +375,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 375 | 375 | const obj_basename = fs.path.basename(mod.obj_file_name); |
| 376 | 376 | |
| 377 | 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 | 379 | const prefix = @ptrCast(*pdb.RecordPrefix, &mod.symbols[symbol_i]); |
| 380 | 380 | if (prefix.RecordLen < 2) |
| 381 | 381 | return error.InvalidDebugInfo; |
| ... | ... | @@ -858,8 +858,10 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 858 | 858 | const age = try pdb_stream.stream.readIntLittle(u32); |
| 859 | 859 | var guid: [16]u8 = undefined; |
| 860 | 860 | try pdb_stream.stream.readNoEof(guid[0..]); |
| 861 | if (version != 20000404) // VC70, only value observed by LLVM team | |
| 862 | return error.UnknownPDBVersion; | |
| 861 | 863 | if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age) |
| 862 | return error.InvalidDebugInfo; | |
| 864 | return error.PDBMismatch; | |
| 863 | 865 | // We validated the executable and pdb match. |
| 864 | 866 | |
| 865 | 867 | const string_table_index = str_tab_index: { |
| ... | ... | @@ -903,13 +905,18 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 903 | 905 | return error.MissingDebugInfo; |
| 904 | 906 | }; |
| 905 | 907 | |
| 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 | 909 | di.pdb.dbi = di.pdb.getStream(pdb.StreamType.Dbi) orelse return error.MissingDebugInfo; |
| 908 | 910 | |
| 909 | 911 | const dbi = di.pdb.dbi; |
| 910 | 912 | |
| 911 | 913 | // Dbi Header |
| 912 | 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 | 920 | const mod_info_size = dbi_stream_header.ModInfoSize; |
| 914 | 921 | const section_contrib_size = dbi_stream_header.SectionContributionSize; |
| 915 | 922 |
std/fmt.zig+20-1| ... | ... | @@ -371,9 +371,10 @@ pub fn formatType( |
| 371 | 371 | return output(context, "{ ... }"); |
| 372 | 372 | } |
| 373 | 373 | comptime var field_i = 0; |
| 374 | try output(context, "{"); | |
| 374 | 375 | inline while (field_i < @memberCount(T)) : (field_i += 1) { |
| 375 | 376 | if (field_i == 0) { |
| 376 | try output(context, "{ ."); | |
| 377 | try output(context, " ."); | |
| 377 | 378 | } else { |
| 378 | 379 | try output(context, ", ."); |
| 379 | 380 | } |
| ... | ... | @@ -422,6 +423,9 @@ pub fn formatType( |
| 422 | 423 | if (info.child == u8) { |
| 423 | 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 | 429 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value)); |
| 426 | 430 | }, |
| 427 | 431 | .Fn => { |
| ... | ... | @@ -1436,6 +1440,21 @@ test "struct.self-referential" { |
| 1436 | 1440 | try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", inst); |
| 1437 | 1441 | } |
| 1438 | 1442 | |
| 1443 | test "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 | ||
| 1439 | 1458 | test "bytes.hex" { |
| 1440 | 1459 | const some_bytes = "\xCA\xFE\xBA\xBE"; |
| 1441 | 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 | 2053 | } |
| 2054 | 2054 | } |
| 2055 | 2055 | |
| 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`. | |
| 2059 | pub 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 | ||
| 2056 | 2072 | pub const PipeError = error{ |
| 2057 | 2073 | SystemFdQuotaExceeded, |
| 2058 | 2074 | ProcessFdQuotaExceeded, |
std/pdb.zig+73-44| ... | ... | @@ -499,45 +499,78 @@ const Msf = struct { |
| 499 | 499 | |
| 500 | 500 | const superblock = try in.readStruct(SuperBlock); |
| 501 | 501 | |
| 502 | // Sanity checks | |
| 502 | 503 | if (!mem.eql(u8, superblock.FileMagic, SuperBlock.file_magic)) |
| 503 | 504 | return error.InvalidDebugInfo; |
| 504 | ||
| 505 | 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 | 509 | switch (superblock.BlockSize) { |
| 506 | 510 | // llvm only supports 4096 but we can handle any of these values |
| 507 | 511 | 512, 1024, 2048, 4096 => {}, |
| 508 | 512 | else => return error.InvalidDebugInfo, |
| 509 | 513 | } |
| 510 | 514 | |
| 511 | if (superblock.NumBlocks * superblock.BlockSize != try file.getEndPos()) | |
| 512 | return error.InvalidDebugInfo; | |
| 515 | const dir_block_count = blockCountFromSize(superblock.NumDirectoryBytes, superblock.BlockSize); | |
| 516 | if (dir_block_count > superblock.BlockSize / @sizeOf(u32)) | |
| 517 | return error.UnhandledBigDirectoryStream; // cf. BlockMapAddr comment. | |
| 513 | 518 | |
| 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 | 525 | superblock.BlockSize, |
| 516 | blockCountFromSize(superblock.NumDirectoryBytes, superblock.BlockSize), | |
| 517 | superblock.BlockSize * superblock.BlockMapAddr, | |
| 518 | 526 | file, |
| 519 | allocator, | |
| 527 | dir_blocks, | |
| 520 | 528 | ); |
| 521 | 529 | |
| 530 | const begin = self.directory.pos; | |
| 522 | 531 | const stream_count = try self.directory.stream.readIntLittle(u32); |
| 523 | ||
| 524 | 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 | 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 | } |
| 529 | 543 | |
| 530 | 544 | self.streams = try allocator.alloc(MsfStream, stream_count); |
| 531 | 545 | for (self.streams) |*stream, i| { |
| 532 | stream.* = try MsfStream.init( | |
| 533 | superblock.BlockSize, | |
| 534 | stream_sizes[i], | |
| 535 | // MsfStream.init expects the file to be at the part where it reads [N]u32 | |
| 536 | try file.getPos(), | |
| 537 | file, | |
| 538 | allocator, | |
| 539 | ); | |
| 546 | const size = stream_sizes[i]; | |
| 547 | if (size == 0) { | |
| 548 | stream.* = MsfStream{ | |
| 549 | .blocks = [_]u32{}, | |
| 550 | }; | |
| 551 | } else { | |
| 552 | var blocks = try allocator.alloc(u32, size); | |
| 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 | }; |
| 543 | 576 | |
| ... | ... | @@ -574,7 +607,6 @@ const SuperBlock = packed struct { |
| 574 | 607 | NumDirectoryBytes: u32, |
| 575 | 608 | |
| 576 | 609 | Unknown: u32, |
| 577 | ||
| 578 | 610 | /// The index of a block within the MSF file. At this block is an array of |
| 579 | 611 | /// ulittle32_t’s listing the blocks that the stream directory resides on. |
| 580 | 612 | /// For large MSF files, the stream directory (which describes the block |
| ... | ... | @@ -584,45 +616,41 @@ const SuperBlock = packed struct { |
| 584 | 616 | /// and the stream directory itself can be stitched together accordingly. |
| 585 | 617 | /// The number of ulittle32_t’s in this array is given by |
| 586 | 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 | 625 | BlockMapAddr: u32, |
| 588 | 626 | }; |
| 589 | 627 | |
| 590 | 628 | const MsfStream = struct { |
| 591 | in_file: File, | |
| 592 | pos: u64, | |
| 593 | blocks: []u32, | |
| 594 | block_size: u32, | |
| 629 | in_file: File = undefined, | |
| 630 | pos: u64 = undefined, | |
| 631 | blocks: []u32 = undefined, | |
| 632 | block_size: u32 = undefined, | |
| 595 | 633 | |
| 596 | 634 | /// Implementation of InStream trait for Pdb.MsfStream |
| 597 | stream: Stream, | |
| 635 | stream: Stream = undefined, | |
| 598 | 636 | |
| 599 | 637 | pub const Error = @typeOf(read).ReturnType.ErrorSet; |
| 600 | 638 | pub const Stream = io.InStream(Error); |
| 601 | 639 | |
| 602 | fn init(block_size: u32, block_count: u32, pos: u64, file: File, allocator: *mem.Allocator) !MsfStream { | |
| 603 | var stream = MsfStream{ | |
| 640 | fn init(block_size: u32, file: File, blocks: []u32) MsfStream { | |
| 641 | const stream = MsfStream{ | |
| 604 | 642 | .in_file = file, |
| 605 | 643 | .pos = 0, |
| 606 | .blocks = try allocator.alloc(u32, block_count), | |
| 644 | .blocks = blocks, | |
| 607 | 645 | .block_size = block_size, |
| 608 | 646 | .stream = Stream{ .readFn = readFn }, |
| 609 | 647 | }; |
| 610 | 648 | |
| 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 | 649 | return stream; |
| 621 | 650 | } |
| 622 | 651 | |
| 623 | 652 | fn readNullTermString(self: *MsfStream, allocator: *mem.Allocator) ![]u8 { |
| 624 | 653 | var list = ArrayList(u8).init(allocator); |
| 625 | defer list.deinit(); | |
| 626 | 654 | while (true) { |
| 627 | 655 | const byte = try self.stream.readByte(); |
| 628 | 656 | if (byte == 0) { |
| ... | ... | @@ -642,11 +670,12 @@ const MsfStream = struct { |
| 642 | 670 | const in = &file_stream.stream; |
| 643 | 671 | |
| 644 | 672 | var size: usize = 0; |
| 645 | for (buffer) |*byte| { | |
| 646 | byte.* = try in.readByte(); | |
| 647 | ||
| 648 | offset += 1; | |
| 649 | size += 1; | |
| 673 | var rem_buffer = buffer; | |
| 674 | while (size < buffer.len) { | |
| 675 | const size_to_read = math.min(self.block_size - offset, rem_buffer.len); | |
| 676 | size += try in.read(rem_buffer[0..size_to_read]); | |
| 677 | rem_buffer = buffer[size..]; | |
| 678 | offset += size_to_read; | |
| 650 | 679 | |
| 651 | 680 | // If we're at the end of a block, go to the next one. |
| 652 | 681 | if (offset == self.block_size) { |
| ... | ... | @@ -657,8 +686,8 @@ const MsfStream = struct { |
| 657 | 686 | } |
| 658 | 687 | } |
| 659 | 688 | |
| 660 | self.pos += size; | |
| 661 | return size; | |
| 689 | self.pos += buffer.len; | |
| 690 | return buffer.len; | |
| 662 | 691 | } |
| 663 | 692 | |
| 664 | 693 | fn seekBy(self: *MsfStream, len: i64) !void { |
std/rb.zig+2-1| ... | ... | @@ -93,7 +93,8 @@ pub const Node = struct { |
| 93 | 93 | comptime { |
| 94 | 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 | } |
| 98 | 99 | |
| 99 | 100 | fn setColor(node: *Node, color: Color) void { |
std/segmented_list.zig+18-11| ... | ... | @@ -77,15 +77,19 @@ const Allocator = std.mem.Allocator; |
| 77 | 77 | pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type { |
| 78 | 78 | return struct { |
| 79 | 79 | const Self = @This(); |
| 80 | const prealloc_exp = blk: { | |
| 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)); | |
| 80 | const ShelfIndex = std.math.Log2Int(usize); | |
| 84 | 81 | |
| 85 | const value = std.math.log2_int(usize, prealloc_item_count); | |
| 86 | break :blk @typeOf(1)(value); | |
| 82 | const prealloc_exp: ShelfIndex = blk: { | |
| 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); | |
| 89 | 93 | |
| 90 | 94 | prealloc_segment: [prealloc_item_count]T, |
| 91 | 95 | dynamic_segments: [][*]T, |
| ... | ... | @@ -157,11 +161,12 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 157 | 161 | |
| 158 | 162 | /// Grows or shrinks capacity to match usage. |
| 159 | 163 | pub fn setCapacity(self: *Self, new_capacity: usize) !void { |
| 160 | if (new_capacity <= usize(1) << (prealloc_exp + self.dynamic_segments.len)) { | |
| 161 | return self.shrinkCapacity(new_capacity); | |
| 162 | } else { | |
| 163 | return self.growCapacity(new_capacity); | |
| 164 | if (prealloc_item_count != 0) { | |
| 165 | if (new_capacity <= usize(1) << (prealloc_exp + @intCast(ShelfIndex, self.dynamic_segments.len))) { | |
| 166 | return self.shrinkCapacity(new_capacity); | |
| 167 | } | |
| 164 | 168 | } |
| 169 | return self.growCapacity(new_capacity); | |
| 165 | 170 | } |
| 166 | 171 | |
| 167 | 172 | /// Only grows capacity, or retains current capacity |
| ... | ... | @@ -399,4 +404,6 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void { |
| 399 | 404 | testing.expect(item == i); |
| 400 | 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 | 35 | |
| 36 | 36 | switch (builtin.arch) { |
| 37 | 37 | .x86_64 => { |
| 38 | argc_ptr = asm ("lea (%%rsp), %[argc]" | |
| 39 | : [argc] "=r" (-> [*]usize) | |
| 38 | argc_ptr = asm ("" | |
| 39 | : [argc] "={rsp}" (-> [*]usize) | |
| 40 | 40 | ); |
| 41 | 41 | }, |
| 42 | 42 | .i386 => { |
| 43 | argc_ptr = asm ("lea (%%esp), %[argc]" | |
| 44 | : [argc] "=r" (-> [*]usize) | |
| 43 | argc_ptr = asm ("" | |
| 44 | : [argc] "={esp}" (-> [*]usize) | |
| 45 | 45 | ); |
| 46 | 46 | }, |
| 47 | 47 | .aarch64, .aarch64_be => { |
std/std.zig+1| ... | ... | @@ -105,6 +105,7 @@ test "std" { |
| 105 | 105 | _ = @import("packed_int_array.zig"); |
| 106 | 106 | _ = @import("priority_queue.zig"); |
| 107 | 107 | _ = @import("rand.zig"); |
| 108 | _ = @import("rb.zig"); | |
| 108 | 109 | _ = @import("sort.zig"); |
| 109 | 110 | _ = @import("testing.zig"); |
| 110 | 111 | _ = @import("thread.zig"); |
test/compile_errors.zig+8-8| ... | ... | @@ -219,7 +219,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 219 | 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 | ); |
| 224 | 224 | |
| 225 | 225 | cases.add( |
| ... | ... | @@ -2758,7 +2758,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2758 | 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 | ); |
| 2763 | 2763 | |
| 2764 | 2764 | cases.add( |
| ... | ... | @@ -2768,7 +2768,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2768 | 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 | ); |
| 2773 | 2773 | |
| 2774 | 2774 | cases.add( |
| ... | ... | @@ -2838,7 +2838,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2838 | 2838 | \\} |
| 2839 | 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 | ); |
| 2843 | 2843 | |
| 2844 | 2844 | cases.add( |
| ... | ... | @@ -3901,7 +3901,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3901 | 3901 | \\ |
| 3902 | 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 | 3905 | "tmp.zig:4:17: note: called from here", |
| 3906 | 3906 | ); |
| 3907 | 3907 | |
| ... | ... | @@ -4151,7 +4151,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4151 | 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 | ); |
| 4156 | 4156 | |
| 4157 | 4157 | cases.add( |
| ... | ... | @@ -4161,7 +4161,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4161 | 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 | ); |
| 4166 | 4166 | |
| 4167 | 4167 | cases.add( |
| ... | ... | @@ -4309,7 +4309,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4309 | 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 | ); |
| 4314 | 4314 | |
| 4315 | 4315 | cases.add( |
test/stage1/behavior/atomics.zig+31| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const expect = std.testing.expect; |
| 3 | const expectEqual = std.testing.expectEqual; | |
| 3 | 4 | const builtin = @import("builtin"); |
| 4 | 5 | const AtomicRmwOp = builtin.AtomicRmwOp; |
| 5 | 6 | const AtomicOrder = builtin.AtomicOrder; |
| ... | ... | @@ -69,3 +70,33 @@ test "cmpxchg with ptr" { |
| 69 | 70 | expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); |
| 70 | 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 | ||
| 95 | test "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 | 1 | const std = @import("std"); |
| 2 | 2 | const expect = std.testing.expect; |
| 3 | const expectEqual = std.testing.expectEqual; | |
| 3 | 4 | const builtin = @import("builtin"); |
| 4 | 5 | |
| 5 | 6 | test "compile time recursion" { |
| ... | ... | @@ -794,3 +795,12 @@ test "no undeclared identifier error in unanalyzed branches" { |
| 794 | 795 | lol_this_doesnt_exist = nonsense; |
| 795 | 796 | } |
| 796 | 797 | } |
| 798 | ||
| 799 | test "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 | 228 | S.entry(); |
| 229 | 229 | comptime S.entry(); |
| 230 | 230 | } |
| 231 | ||
| 232 | test "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 | } |