| ... | @@ -1036,7 +1036,7 @@ static LLVMValueRef get_write_register_fn_val(CodeGen *g) { | ... | @@ -1036,7 +1036,7 @@ static LLVMValueRef get_write_register_fn_val(CodeGen *g) { |
| 1036 | // !0 = !{!"sp\00"} | 1036 | // !0 = !{!"sp\00"} |
| 1037 | | 1037 | |
| 1038 | LLVMTypeRef param_types[] = { | 1038 | LLVMTypeRef param_types[] = { |
| 1039 | LLVMMetadataTypeInContext(LLVMGetGlobalContext()), | 1039 | LLVMMetadataTypeInContext(LLVMGetGlobalContext()), |
| 1040 | LLVMIntType(g->pointer_size_bytes * 8), | 1040 | LLVMIntType(g->pointer_size_bytes * 8), |
| 1041 | }; | 1041 | }; |
| 1042 | | 1042 | |
| ... | @@ -3491,6 +3491,15 @@ static bool want_valgrind_support(CodeGen *g) { | ... | @@ -3491,6 +3491,15 @@ static bool want_valgrind_support(CodeGen *g) { |
| 3491 | zig_unreachable(); | 3491 | zig_unreachable(); |
| 3492 | } | 3492 | } |
| 3493 | | 3493 | |
| | 3494 | static void gen_valgrind_undef(CodeGen *g, LLVMValueRef dest_ptr, LLVMValueRef byte_count) { |
| | 3495 | static const uint32_t VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; |
| | 3496 | ZigType *usize = g->builtin_types.entry_usize; |
| | 3497 | LLVMValueRef zero = LLVMConstInt(usize->llvm_type, 0, false); |
| | 3498 | LLVMValueRef req = LLVMConstInt(usize->llvm_type, VG_USERREQ__MAKE_MEM_UNDEFINED, false); |
| | 3499 | LLVMValueRef ptr_as_usize = LLVMBuildPtrToInt(g->builder, dest_ptr, usize->llvm_type, ""); |
| | 3500 | gen_valgrind_client_request(g, zero, req, ptr_as_usize, byte_count, zero, zero, zero); |
| | 3501 | } |
| | 3502 | |
| 3494 | static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) { | 3503 | static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) { |
| 3495 | assert(type_has_bits(value_type)); | 3504 | assert(type_has_bits(value_type)); |
| 3496 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, value_type)); | 3505 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, value_type)); |
| ... | @@ -3505,11 +3514,7 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_ | ... | @@ -3505,11 +3514,7 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_ |
| 3505 | ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false); | 3514 | ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false); |
| 3506 | // then tell valgrind that the memory is undefined even though we just memset it | 3515 | // then tell valgrind that the memory is undefined even though we just memset it |
| 3507 | if (want_valgrind_support(g)) { | 3516 | if (want_valgrind_support(g)) { |
| 3508 | static const uint32_t VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; | 3517 | gen_valgrind_undef(g, dest_ptr, byte_count); |
| 3509 | LLVMValueRef zero = LLVMConstInt(usize->llvm_type, 0, false); | | |
| 3510 | LLVMValueRef req = LLVMConstInt(usize->llvm_type, VG_USERREQ__MAKE_MEM_UNDEFINED, false); | | |
| 3511 | LLVMValueRef ptr_as_usize = LLVMBuildPtrToInt(g->builder, dest_ptr, usize->llvm_type, ""); | | |
| 3512 | gen_valgrind_client_request(g, zero, req, ptr_as_usize, byte_count, zero, zero, zero); | | |
| 3513 | } | 3518 | } |
| 3514 | } | 3519 | } |
| 3515 | | 3520 | |
| ... | @@ -3519,14 +3524,14 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir | ... | @@ -3519,14 +3524,14 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir |
| 3519 | if (!type_has_bits(ptr_type)) | 3524 | if (!type_has_bits(ptr_type)) |
| 3520 | return nullptr; | 3525 | return nullptr; |
| 3521 | | 3526 | |
| 3522 | bool have_init_expr = !value_is_all_undef(&instruction->value->value); | 3527 | bool have_init_expr = !value_is_all_undef(&instruction->value->value); |
| 3523 | if (have_init_expr) { | 3528 | if (have_init_expr) { |
| 3524 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); | 3529 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); |
| 3525 | LLVMValueRef value = ir_llvm_value(g, instruction->value); | 3530 | LLVMValueRef value = ir_llvm_value(g, instruction->value); |
| 3526 | gen_assign_raw(g, ptr, ptr_type, value); | 3531 | gen_assign_raw(g, ptr, ptr_type, value); |
| 3527 | } else if (ir_want_runtime_safety(g, &instruction->base)) { | 3532 | } else if (ir_want_runtime_safety(g, &instruction->base)) { |
| 3528 | gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type, | 3533 | gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type, |
| 3529 | ir_llvm_value(g, instruction->ptr)); | 3534 | ir_llvm_value(g, instruction->ptr)); |
| 3530 | } | 3535 | } |
| 3531 | return nullptr; | 3536 | return nullptr; |
| 3532 | } | 3537 | } |
| ... | @@ -3729,7 +3734,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3729,7 +3734,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3729 | } | 3734 | } |
| 3730 | FnWalk fn_walk = {}; | 3735 | FnWalk fn_walk = {}; |
| 3731 | fn_walk.id = FnWalkIdCall; | 3736 | fn_walk.id = FnWalkIdCall; |
| 3732 | fn_walk.data.call.inst = instruction; | 3737 | fn_walk.data.call.inst = instruction; |
| 3733 | fn_walk.data.call.is_var_args = is_var_args; | 3738 | fn_walk.data.call.is_var_args = is_var_args; |
| 3734 | fn_walk.data.call.gen_param_values = &gen_param_values; | 3739 | fn_walk.data.call.gen_param_values = &gen_param_values; |
| 3735 | walk_function_params(g, fn_type, &fn_walk); | 3740 | walk_function_params(g, fn_type, &fn_walk); |
| ... | @@ -3749,7 +3754,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3749,7 +3754,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3749 | | 3754 | |
| 3750 | LLVMCallConv llvm_cc = get_llvm_cc(g, cc); | 3755 | LLVMCallConv llvm_cc = get_llvm_cc(g, cc); |
| 3751 | LLVMValueRef result; | 3756 | LLVMValueRef result; |
| 3752 | | 3757 | |
| 3753 | if (instruction->new_stack == nullptr) { | 3758 | if (instruction->new_stack == nullptr) { |
| 3754 | result = ZigLLVMBuildCall(g->builder, fn_val, | 3759 | result = ZigLLVMBuildCall(g->builder, fn_val, |
| 3755 | gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, ""); | 3760 | gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, ""); |
| ... | @@ -4229,7 +4234,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { | ... | @@ -4229,7 +4234,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { |
| 4229 | LLVMTypeRef tag_int_llvm_type = get_llvm_type(g, tag_int_type); | 4234 | LLVMTypeRef tag_int_llvm_type = get_llvm_type(g, tag_int_type); |
| 4230 | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(get_llvm_type(g, u8_slice_type), 0), | 4235 | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(get_llvm_type(g, u8_slice_type), 0), |
| 4231 | &tag_int_llvm_type, 1, false); | 4236 | &tag_int_llvm_type, 1, false); |
| 4232 | | 4237 | |
| 4233 | Buf *fn_name = get_mangled_name(g, buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name)), false); | 4238 | Buf *fn_name = get_mangled_name(g, buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name)), false); |
| 4234 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); | 4239 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); |
| 4235 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); | 4240 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); |
| ... | @@ -4529,17 +4534,27 @@ static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -4529,17 +4534,27 @@ static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrI |
| 4529 | | 4534 | |
| 4530 | static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrInstructionMemset *instruction) { | 4535 | static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrInstructionMemset *instruction) { |
| 4531 | LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr); | 4536 | LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr); |
| 4532 | LLVMValueRef char_val = ir_llvm_value(g, instruction->byte); | | |
| 4533 | LLVMValueRef len_val = ir_llvm_value(g, instruction->count); | 4537 | LLVMValueRef len_val = ir_llvm_value(g, instruction->count); |
| 4534 | | 4538 | |
| 4535 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | 4539 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 4536 | | | |
| 4537 | LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, ""); | 4540 | LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, ""); |
| 4538 | | 4541 | |
| 4539 | ZigType *ptr_type = instruction->dest_ptr->value.type; | 4542 | ZigType *ptr_type = instruction->dest_ptr->value.type; |
| 4540 | assert(ptr_type->id == ZigTypeIdPointer); | 4543 | assert(ptr_type->id == ZigTypeIdPointer); |
| 4541 | | 4544 | |
| 4542 | ZigLLVMBuildMemSet(g->builder, dest_ptr_casted, char_val, len_val, get_ptr_align(g, ptr_type), ptr_type->data.pointer.is_volatile); | 4545 | bool val_is_undef = value_is_all_undef(&instruction->byte->value); |
| | 4546 | LLVMValueRef fill_char; |
| | 4547 | if (val_is_undef) { |
| | 4548 | fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); |
| | 4549 | } else { |
| | 4550 | fill_char = ir_llvm_value(g, instruction->byte); |
| | 4551 | } |
| | 4552 | ZigLLVMBuildMemSet(g->builder, dest_ptr_casted, fill_char, len_val, get_ptr_align(g, ptr_type), |
| | 4553 | ptr_type->data.pointer.is_volatile); |
| | 4554 | |
| | 4555 | if (val_is_undef && want_valgrind_support(g)) { |
| | 4556 | gen_valgrind_undef(g, dest_ptr_casted, len_val); |
| | 4557 | } |
| 4543 | return nullptr; | 4558 | return nullptr; |
| 4544 | } | 4559 | } |
| 4545 | | 4560 | |
| ... | @@ -6944,7 +6959,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6944,7 +6959,7 @@ static void do_code_gen(CodeGen *g) { |
| 6944 | ir_render(g, fn_table_entry); | 6959 | ir_render(g, fn_table_entry); |
| 6945 | | 6960 | |
| 6946 | } | 6961 | } |
| 6947 | | 6962 | |
| 6948 | assert(!g->errors.length); | 6963 | assert(!g->errors.length); |
| 6949 | | 6964 | |
| 6950 | if (buf_len(&g->global_asm) != 0) { | 6965 | if (buf_len(&g->global_asm) != 0) { |
| ... | @@ -7752,7 +7767,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { | ... | @@ -7752,7 +7767,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7752 | assert(ContainerLayoutAuto == 0); | 7767 | assert(ContainerLayoutAuto == 0); |
| 7753 | assert(ContainerLayoutExtern == 1); | 7768 | assert(ContainerLayoutExtern == 1); |
| 7754 | assert(ContainerLayoutPacked == 2); | 7769 | assert(ContainerLayoutPacked == 2); |
| 7755 | | 7770 | |
| 7756 | assert(CallingConventionUnspecified == 0); | 7771 | assert(CallingConventionUnspecified == 0); |
| 7757 | assert(CallingConventionC == 1); | 7772 | assert(CallingConventionC == 1); |
| 7758 | assert(CallingConventionCold == 2); | 7773 | assert(CallingConventionCold == 2); |