From a9a6f77a1f0a6e173d85fee42aec0a8d5e22a64d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 20 Oct 2016 01:13:39 -0400 Subject: [PATCH] add variable declaration initialization IR --- src/analyze.cpp | 3 --- src/codegen.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++++- src/ir.cpp | 7 ++++--- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index f8c3f4c35e..7b0743a2d5 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3615,9 +3615,6 @@ static VariableTableEntry *add_local_var_shadowable(CodeGen *g, AstNode *source_ // TODO replace _anon with @anon and make sure all tests still pass buf_init_from_str(&variable_entry->name, "_anon"); } - if (context->fn_entry) { - context->fn_entry->variable_list.append(variable_entry); - } variable_entry->is_const = is_const; variable_entry->decl_node = source_node; diff --git a/src/codegen.cpp b/src/codegen.cpp index 2e232bacb7..cf412be0fc 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2811,6 +2811,59 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst zig_unreachable(); } +static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, + IrInstructionDeclVar *decl_var_instruction) +{ + VariableTableEntry *var = decl_var_instruction->var; + + if (!type_has_bits(var->type)) + return nullptr; + + IrInstruction *init_value = decl_var_instruction->init_value; + + bool have_init_expr = false; + bool want_zeroes = false; + + ConstExprValue *const_val = &init_value->static_value; + if (!const_val->ok || const_val->special == ConstValSpecialOther) + have_init_expr = true; + if (const_val->ok && const_val->special == ConstValSpecialZeroes) + want_zeroes = true; + + if (have_init_expr) { + gen_assign_raw(g, init_value->source_node, BinOpTypeAssign, var->value_ref, + ir_llvm_value(g, init_value), var->type, init_value->type_entry); + } else { + bool ignore_uninit = false; + // handle runtime stack allocation + bool want_safe = ir_want_debug_safety(g, &decl_var_instruction->base); + if (!ignore_uninit && (want_safe || want_zeroes)) { + TypeTableEntry *usize = g->builtin_types.entry_usize; + uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->type->type_ref); + uint64_t align_bytes = get_memcpy_align(g, var->type); + + // memset uninitialized memory to 0xa + LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); + LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), want_zeroes ? 0x00 : 0xaa, false); + LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, ""); + LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); + LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(), align_bytes, false); + LLVMValueRef params[] = { + dest_ptr, + fill_char, + byte_count, + align_in_bytes, + LLVMConstNull(LLVMInt1Type()), // is volatile + }; + + LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, ""); + } + } + + gen_var_debug_decl(g, var); + return nullptr; +} + static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) { set_debug_source_node(g, instruction->source_node); @@ -2821,7 +2874,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdReturn: return ir_render_return(g, executable, (IrInstructionReturn *)instruction); case IrInstructionIdDeclVar: - return nullptr; + return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction); case IrInstructionIdLoadVar: return ir_render_load_var(g, executable, (IrInstructionLoadVar *)instruction); case IrInstructionIdBinOp: diff --git a/src/ir.cpp b/src/ir.cpp index 4d9eacb6c3..b70360f1ad 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -586,9 +586,6 @@ static VariableTableEntry *ir_add_local_var(IrBuilder *irb, AstNode *node, Buf * // TODO replace _anon with @anon and make sure all tests still pass buf_init_from_str(&variable_entry->name, "_anon"); } - if (node->block_context->fn_entry) { - node->block_context->fn_entry->variable_list.append(variable_entry); - } variable_entry->is_const = is_const; variable_entry->decl_node = node; @@ -2177,6 +2174,10 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc } ir_build_var_decl_from(&ira->new_irb, &decl_var_instruction->base, var, var_type, casted_init_value); + BlockContext *scope = decl_var_instruction->base.source_node->block_context; + if (scope->fn_entry) + scope->fn_entry->variable_list.append(var); + return ira->codegen->builtin_types.entry_void; }