| ... | ... | @@ -2811,6 +2811,59 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst |
| 2811 | 2811 | zig_unreachable(); |
| 2812 | 2812 | } |
| 2813 | 2813 | |
| 2814 | static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| 2815 | IrInstructionDeclVar *decl_var_instruction) |
| 2816 | { |
| 2817 | VariableTableEntry *var = decl_var_instruction->var; |
| 2818 | |
| 2819 | if (!type_has_bits(var->type)) |
| 2820 | return nullptr; |
| 2821 | |
| 2822 | IrInstruction *init_value = decl_var_instruction->init_value; |
| 2823 | |
| 2824 | bool have_init_expr = false; |
| 2825 | bool want_zeroes = false; |
| 2826 | |
| 2827 | ConstExprValue *const_val = &init_value->static_value; |
| 2828 | if (!const_val->ok || const_val->special == ConstValSpecialOther) |
| 2829 | have_init_expr = true; |
| 2830 | if (const_val->ok && const_val->special == ConstValSpecialZeroes) |
| 2831 | want_zeroes = true; |
| 2832 | |
| 2833 | if (have_init_expr) { |
| 2834 | gen_assign_raw(g, init_value->source_node, BinOpTypeAssign, var->value_ref, |
| 2835 | ir_llvm_value(g, init_value), var->type, init_value->type_entry); |
| 2836 | } else { |
| 2837 | bool ignore_uninit = false; |
| 2838 | // handle runtime stack allocation |
| 2839 | bool want_safe = ir_want_debug_safety(g, &decl_var_instruction->base); |
| 2840 | if (!ignore_uninit && (want_safe || want_zeroes)) { |
| 2841 | TypeTableEntry *usize = g->builtin_types.entry_usize; |
| 2842 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->type->type_ref); |
| 2843 | uint64_t align_bytes = get_memcpy_align(g, var->type); |
| 2844 | |
| 2845 | // memset uninitialized memory to 0xa |
| 2846 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 2847 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), want_zeroes ? 0x00 : 0xaa, false); |
| 2848 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, ""); |
| 2849 | LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); |
| 2850 | LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(), align_bytes, false); |
| 2851 | LLVMValueRef params[] = { |
| 2852 | dest_ptr, |
| 2853 | fill_char, |
| 2854 | byte_count, |
| 2855 | align_in_bytes, |
| 2856 | LLVMConstNull(LLVMInt1Type()), // is volatile |
| 2857 | }; |
| 2858 | |
| 2859 | LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, ""); |
| 2860 | } |
| 2861 | } |
| 2862 | |
| 2863 | gen_var_debug_decl(g, var); |
| 2864 | return nullptr; |
| 2865 | } |
| 2866 | |
| 2814 | 2867 | static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) { |
| 2815 | 2868 | set_debug_source_node(g, instruction->source_node); |
| 2816 | 2869 | |
| ... | ... | @@ -2821,7 +2874,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 2821 | 2874 | case IrInstructionIdReturn: |
| 2822 | 2875 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
| 2823 | 2876 | case IrInstructionIdDeclVar: |
| 2824 | | return nullptr; |
| 2877 | return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction); |
| 2825 | 2878 | case IrInstructionIdLoadVar: |
| 2826 | 2879 | return ir_render_load_var(g, executable, (IrInstructionLoadVar *)instruction); |
| 2827 | 2880 | case IrInstructionIdBinOp: |