Commit 4815c03caa

Andrew Kelley <superjoe30@gmail.com>
2016-04-28 02:34:53
better parameter codegen
* ability to take address of a parameter (closes #97) * debug symbols work for parameters
1 parent 09042f1
src/all_types.hpp
@@ -1268,7 +1268,6 @@ struct VariableTableEntry {
     TypeTableEntry *type;
     LLVMValueRef value_ref;
     bool is_const;
-    bool is_ptr; // if true, value_ref is a pointer
     // which node is the declaration of the variable
     AstNode *decl_node;
     // which node contains the ConstExprValue for this variable's value
@@ -1277,6 +1276,7 @@ struct VariableTableEntry {
     int src_arg_index;
     int gen_arg_index;
     BlockContext *block_context;
+    LLVMValueRef param_value_ref;
 };
 
 struct ErrorTableEntry {
src/analyze.cpp
@@ -1081,6 +1081,10 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
     if (!fn_table_entry->is_extern) {
         LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoUnwindAttribute);
     }
+    if (!g->is_release_build) {
+        ZigLLVMAddFunctionAttr(fn_table_entry->fn_value, "no-frame-pointer-elim", "true");
+        ZigLLVMAddFunctionAttr(fn_table_entry->fn_value, "no-frame-pointer-elim-non-leaf", nullptr);
+    }
 
     if (fn_table_entry->fn_def_node) {
         // Add debug info.
@@ -3369,7 +3373,6 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Impor
     }
 
     variable_entry->is_const = is_const;
-    variable_entry->is_ptr = true;
     variable_entry->decl_node = source_node;
     variable_entry->val_node = val_node;
 
src/codegen.cpp
@@ -226,9 +226,13 @@ static TypeTableEntry *get_type_for_type_node(AstNode *node) {
     return const_val->data.x_type;
 }
 
-static void add_debug_source_node(CodeGen *g, AstNode *node) {
+static void set_debug_source_node(CodeGen *g, AstNode *node) {
     assert(node->block_context);
-    LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, node->block_context->di_scope);
+    ZigLLVMSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, node->block_context->di_scope);
+}
+
+static void clear_debug_source_node(CodeGen *g) {
+    ZigLLVMClearCurrentDebugLocation(g->builder);
 }
 
 static TypeTableEntry *get_expr_type(AstNode *node) {
@@ -325,7 +329,7 @@ static LLVMValueRef get_handle_value(CodeGen *g, AstNode *source_node, LLVMValue
     if (handle_is_ptr(type)) {
         return ptr;
     } else {
-        add_debug_source_node(g, source_node);
+        set_debug_source_node(g, source_node);
         return LLVMBuildLoad(g->builder, ptr, "");
     }
 }
@@ -347,7 +351,7 @@ static void add_bounds_check(CodeGen *g, AstNode *source_node, LLVMValueRef targ
         upper_value = nullptr;
     }
 
-    add_debug_source_node(g, source_node);
+    set_debug_source_node(g, source_node);
 
     LLVMBasicBlockRef bounds_check_fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoundsCheckFail");
     LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoundsCheckOk");
@@ -382,7 +386,7 @@ static LLVMValueRef gen_err_name(CodeGen *g, AstNode *node) {
 
     AstNode *err_val_node = node->data.fn_call_expr.params.at(0);
     LLVMValueRef err_val = gen_expr(g, err_val_node);
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
 
     if (want_debug_safety(g, node)) {
         LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val));
@@ -425,7 +429,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
                     operand,
                     LLVMConstNull(LLVMInt1Type()),
                 };
-                add_debug_source_node(g, node);
+                set_debug_source_node(g, node);
                 return LLVMBuildCall(g->builder, fn_val, params, 2, "");
             }
         case BuiltinFnIdAddWithOverflow:
@@ -457,7 +461,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
                     op2,
                 };
 
-                add_debug_source_node(g, node);
+                set_debug_source_node(g, node);
                 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
                 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
                 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
@@ -479,7 +483,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
 
                 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
 
-                add_debug_source_node(g, node);
+                set_debug_source_node(g, node);
                 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
                 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, "");
 
@@ -510,7 +514,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
 
                 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
 
-                add_debug_source_node(g, node);
+                set_debug_source_node(g, node);
                 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
 
                 uint64_t align_in_bytes = get_memcpy_align(g, dest_type->data.pointer.child_type);
@@ -540,7 +544,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
         case BuiltinFnIdErrName:
             return gen_err_name(g, node);
         case BuiltinFnIdBreakpoint:
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
     }
     zig_unreachable();
@@ -570,7 +574,7 @@ static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntr
         LLVMValueRef tmp_struct_ptr = node->data.field_access_expr.resolved_struct_val_expr.ptr;
 
         // populate the new tag value
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
         LLVMBuildStore(g->builder, tag_value, tag_field_ptr);
 
@@ -610,14 +614,14 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
         return expr_val;
     } else if (actual_bits < wanted_bits) {
         if (actual_type->id == TypeTableEntryIdFloat) {
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             return LLVMBuildFPExt(g->builder, expr_val, wanted_type->type_ref, "");
         } else if (actual_type->id == TypeTableEntryIdInt) {
             if (actual_type->data.integral.is_signed) {
-                add_debug_source_node(g, source_node);
+                set_debug_source_node(g, source_node);
                 return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, "");
             } else {
-                add_debug_source_node(g, source_node);
+                set_debug_source_node(g, source_node);
                 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
             }
         } else {
@@ -625,10 +629,10 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
         }
     } else if (actual_bits > wanted_bits) {
         if (actual_type->id == TypeTableEntryIdFloat) {
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");
         } else if (actual_type->id == TypeTableEntryIdInt) {
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
         } else {
             zig_unreachable();
@@ -675,12 +679,12 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
                 {
                     return expr_val;
                 } else {
-                    add_debug_source_node(g, node);
+                    set_debug_source_node(g, node);
                     LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 0, "");
                     gen_assign_raw(g, node, BinOpTypeAssign,
                             val_ptr, expr_val, child_type, actual_type);
 
-                    add_debug_source_node(g, node);
+                    set_debug_source_node(g, node);
                     LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 1, "");
                     LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr);
                 }
@@ -700,7 +704,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
                     assert(wanted_type->id == TypeTableEntryIdErrorUnion);
                     assert(actual_type);
 
-                    add_debug_source_node(g, node);
+                    set_debug_source_node(g, node);
                     LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 0, "");
                     LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr);
 
@@ -720,13 +724,13 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
                 zig_panic("TODO");
             }
         case CastOpPtrToInt:
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
         case CastOpIntToPtr:
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, "");
         case CastOpPointerReinterpret:
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
         case CastOpWidenOrShorten:
             return gen_widen_or_shorten(g, node, actual_type, wanted_type, expr_val);
@@ -738,7 +742,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
 
                 TypeTableEntry *pointer_type = wanted_type->data.structure.fields[0].type_entry;
 
-                add_debug_source_node(g, node);
+                set_debug_source_node(g, node);
 
                 int ptr_index = wanted_type->data.structure.fields[0].gen_index;
                 if (ptr_index >= 0) {
@@ -758,26 +762,26 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
         case CastOpIntToFloat:
             assert(actual_type->id == TypeTableEntryIdInt);
             if (actual_type->data.integral.is_signed) {
-                add_debug_source_node(g, node);
+                set_debug_source_node(g, node);
                 return LLVMBuildSIToFP(g->builder, expr_val, wanted_type->type_ref, "");
             } else {
-                add_debug_source_node(g, node);
+                set_debug_source_node(g, node);
                 return LLVMBuildUIToFP(g->builder, expr_val, wanted_type->type_ref, "");
             }
         case CastOpFloatToInt:
             assert(wanted_type->id == TypeTableEntryIdInt);
             if (wanted_type->data.integral.is_signed) {
-                add_debug_source_node(g, node);
+                set_debug_source_node(g, node);
                 return LLVMBuildFPToSI(g->builder, expr_val, wanted_type->type_ref, "");
             } else {
-                add_debug_source_node(g, node);
+                set_debug_source_node(g, node);
                 return LLVMBuildFPToUI(g->builder, expr_val, wanted_type->type_ref, "");
             }
 
         case CastOpBoolToInt:
             assert(wanted_type->id == TypeTableEntryIdInt);
             assert(actual_type->id == TypeTableEntryIdBool);
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
 
     }
@@ -850,7 +854,7 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
         }
     }
 
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     LLVMValueRef result = LLVMZigBuildCall(g->builder, fn_val,
             gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, "");
 
@@ -873,7 +877,7 @@ static LLVMValueRef gen_array_base_ptr(CodeGen *g, AstNode *node) {
         array_ptr = gen_field_access_expr(g, node, true);
         if (type_entry->id == TypeTableEntryIdPointer) {
             // we have a double pointer so we must dereference it once
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             array_ptr = LLVMBuildLoad(g->builder, array_ptr, "");
         }
     } else {
@@ -904,14 +908,14 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal
             LLVMConstNull(g->builtin_types.entry_isize->type_ref),
             subscript_value
         };
-        add_debug_source_node(g, source_node);
+        set_debug_source_node(g, source_node);
         return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
     } else if (array_type->id == TypeTableEntryIdPointer) {
         assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
         LLVMValueRef indices[] = {
             subscript_value
         };
-        add_debug_source_node(g, source_node);
+        set_debug_source_node(g, source_node);
         return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, "");
     } else if (array_type->id == TypeTableEntryIdStruct) {
         assert(array_type->data.structure.is_slice);
@@ -919,7 +923,7 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal
         assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
 
         if (want_debug_safety(g, source_node)) {
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             int len_index = array_type->data.structure.fields[1].gen_index;
             assert(len_index >= 0);
             LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, "");
@@ -927,7 +931,7 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal
             add_bounds_check(g, source_node, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len);
         }
 
-        add_debug_source_node(g, source_node);
+        set_debug_source_node(g, source_node);
         int ptr_index = array_type->data.structure.fields[0].gen_index;
         assert(ptr_index >= 0);
         LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");
@@ -960,8 +964,8 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
         VariableTableEntry *var = get_resolved_expr(struct_expr_node)->variable;
         assert(var);
 
-        if (var->is_ptr && var->type->id == TypeTableEntryIdPointer) {
-            add_debug_source_node(g, node);
+        if (var->type->id == TypeTableEntryIdPointer) {
+            set_debug_source_node(g, node);
             struct_ptr = LLVMBuildLoad(g->builder, var->value_ref, "");
         } else {
             struct_ptr = var->value_ref;
@@ -971,7 +975,7 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
         TypeTableEntry *field_type = get_expr_type(struct_expr_node);
         if (field_type->id == TypeTableEntryIdPointer) {
             // we have a double pointer so we must dereference it once
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             struct_ptr = LLVMBuildLoad(g->builder, struct_ptr, "");
         }
     } else {
@@ -986,7 +990,7 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
 
     *out_type_entry = node->data.field_access_expr.type_struct_field->type_entry;
 
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     return LLVMBuildStructGEP(g->builder, struct_ptr, gen_field_index, "");
 }
 
@@ -1017,7 +1021,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
             }
         }
 
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
         LLVMValueRef indices[] = {
             LLVMConstNull(g->builtin_types.entry_isize->type_ref),
@@ -1039,7 +1043,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
             add_bounds_check(g, node, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
         }
 
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
         LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
         LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
@@ -1061,7 +1065,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
 
         LLVMValueRef prev_end = nullptr;
         if (!node->data.slice_expr.end || want_debug_safety(g, node)) {
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, "");
             prev_end = LLVMBuildLoad(g->builder, src_len_ptr, "");
         }
@@ -1082,7 +1086,7 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
             }
         }
 
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");
         LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, "");
         LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, ptr_index, "");
@@ -1122,7 +1126,7 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva
     if (is_lvalue || !ptr || handle_is_ptr(child_type)) {
         return ptr;
     } else {
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         return LLVMBuildLoad(g->builder, ptr, "");
     }
 }
@@ -1130,11 +1134,9 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva
 static LLVMValueRef gen_variable(CodeGen *g, AstNode *source_node, VariableTableEntry *variable) {
     if (!type_has_bits(variable->type)) {
         return nullptr;
-    } else if (variable->is_ptr) {
+    } else {
         assert(variable->value_ref);
         return get_handle_value(g, source_node, variable->value_ref, variable->type);
-    } else {
-        return variable->value_ref;
     }
 }
 
@@ -1157,7 +1159,7 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva
         if (is_lvalue || handle_is_ptr(type_entry)) {
             return ptr;
         } else {
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             return LLVMBuildLoad(g->builder, ptr, "");
         }
     } else if (struct_type->id == TypeTableEntryIdMetaType) {
@@ -1233,10 +1235,10 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
             {
                 LLVMValueRef expr = gen_expr(g, expr_node);
                 if (expr_type->id == TypeTableEntryIdInt) {
-                    add_debug_source_node(g, node);
+                    set_debug_source_node(g, node);
                     return LLVMBuildNeg(g->builder, expr, "");
                 } else if (expr_type->id == TypeTableEntryIdFloat) {
-                    add_debug_source_node(g, node);
+                    set_debug_source_node(g, node);
                     return LLVMBuildFNeg(g->builder, expr, "");
                 } else {
                     zig_unreachable();
@@ -1246,13 +1248,13 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
             {
                 LLVMValueRef expr = gen_expr(g, expr_node);
                 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
-                add_debug_source_node(g, node);
+                set_debug_source_node(g, node);
                 return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, "");
             }
         case PrefixOpBinNot:
             {
                 LLVMValueRef expr = gen_expr(g, expr_node);
-                add_debug_source_node(g, node);
+                set_debug_source_node(g, node);
                 return LLVMBuildNot(g->builder, expr, "");
             }
         case PrefixOpAddressOf:
@@ -1291,13 +1293,13 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
                 if (want_debug_safety(g, node)) {
                     LLVMValueRef err_val;
                     if (type_has_bits(child_type)) {
-                        add_debug_source_node(g, node);
+                        set_debug_source_node(g, node);
                         LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
                         err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
                     } else {
                         err_val = expr_val;
                     }
-                    add_debug_source_node(g, node);
+                    set_debug_source_node(g, node);
                     LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
                     LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
                     LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
@@ -1327,7 +1329,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
                 TypeTableEntry *child_type = expr_type->data.maybe.child_type;
 
                 if (want_debug_safety(g, node)) {
-                    add_debug_source_node(g, node);
+                    set_debug_source_node(g, node);
                     LLVMValueRef cond_val;
                     if (child_type->id == TypeTableEntryIdPointer ||
                         child_type->id == TypeTableEntryIdFn)
@@ -1356,7 +1358,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
                 {
                     return expr_val;
                 } else {
-                    add_debug_source_node(g, node);
+                    set_debug_source_node(g, node);
                     LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
                     return get_handle_value(g, node, maybe_field_ptr, child_type);
                 }
@@ -1375,26 +1377,26 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
     switch (bin_op) {
         case BinOpTypeBinOr:
         case BinOpTypeAssignBitOr:
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             return LLVMBuildOr(g->builder, val1, val2, "");
         case BinOpTypeBinXor:
         case BinOpTypeAssignBitXor:
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             return LLVMBuildXor(g->builder, val1, val2, "");
         case BinOpTypeBinAnd:
         case BinOpTypeAssignBitAnd:
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             return LLVMBuildAnd(g->builder, val1, val2, "");
         case BinOpTypeBitShiftLeft:
         case BinOpTypeAssignBitShiftLeft:
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             return LLVMBuildShl(g->builder, val1, val2, "");
         case BinOpTypeBitShiftRight:
         case BinOpTypeAssignBitShiftRight:
             assert(op1_type->id == TypeTableEntryIdInt);
             assert(op2_type->id == TypeTableEntryIdInt);
 
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             if (op1_type->data.integral.is_signed) {
                 return LLVMBuildAShr(g->builder, val1, val2, "");
             } else {
@@ -1402,7 +1404,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
             }
         case BinOpTypeAdd:
         case BinOpTypeAssignPlus:
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             if (op1_type->id == TypeTableEntryIdFloat) {
                 return LLVMBuildFAdd(g->builder, val1, val2, "");
             } else {
@@ -1410,7 +1412,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
             }
         case BinOpTypeSub:
         case BinOpTypeAssignMinus:
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             if (op1_type->id == TypeTableEntryIdFloat) {
                 return LLVMBuildFSub(g->builder, val1, val2, "");
             } else {
@@ -1418,7 +1420,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
             }
         case BinOpTypeMult:
         case BinOpTypeAssignTimes:
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             if (op1_type->id == TypeTableEntryIdFloat) {
                 return LLVMBuildFMul(g->builder, val1, val2, "");
             } else {
@@ -1426,7 +1428,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
             }
         case BinOpTypeDiv:
         case BinOpTypeAssignDiv:
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             if (op1_type->id == TypeTableEntryIdFloat) {
                 return LLVMBuildFDiv(g->builder, val1, val2, "");
             } else {
@@ -1439,7 +1441,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
             }
         case BinOpTypeMod:
         case BinOpTypeAssignMod:
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             if (op1_type->id == TypeTableEntryIdFloat) {
                 return LLVMBuildFRem(g->builder, val1, val2, "");
             } else {
@@ -1528,7 +1530,7 @@ static LLVMValueRef gen_cmp_expr(CodeGen *g, AstNode *node) {
     TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2);
     assert(op1_type == op2_type);
 
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     if (op1_type->id == TypeTableEntryIdFloat) {
         LLVMRealPredicate pred = cmp_op_to_real_predicate(node->data.bin_op_expr.bin_op);
         return LLVMBuildFCmp(g->builder, pred, val1, val2, "");
@@ -1565,18 +1567,18 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {
     // block for when val1 == false (don't even evaluate the second part)
     LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndFalse");
 
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     LLVMBuildCondBr(g->builder, val1, true_block, false_block);
 
     LLVMPositionBuilderAtEnd(g->builder, true_block);
     LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
     LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
 
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     LLVMBuildBr(g->builder, false_block);
 
     LLVMPositionBuilderAtEnd(g->builder, false_block);
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
     LLVMValueRef incoming_values[2] = {val1, val2};
     LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};
@@ -1596,7 +1598,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
     // block for when val1 == true (don't even evaluate the second part)
     LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrTrue");
 
-    add_debug_source_node(g, expr_node);
+    set_debug_source_node(g, expr_node);
     LLVMBuildCondBr(g->builder, val1, true_block, false_block);
 
     LLVMPositionBuilderAtEnd(g->builder, false_block);
@@ -1604,11 +1606,11 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
 
     LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
 
-    add_debug_source_node(g, expr_node);
+    set_debug_source_node(g, expr_node);
     LLVMBuildBr(g->builder, true_block);
 
     LLVMPositionBuilderAtEnd(g->builder, true_block);
-    add_debug_source_node(g, expr_node);
+    set_debug_source_node(g, expr_node);
     LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
     LLVMValueRef incoming_values[2] = {val1, val2};
     LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};
@@ -1624,7 +1626,7 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValu
 
     LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
 
-    add_debug_source_node(g, source_node);
+    set_debug_source_node(g, source_node);
     LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, src, ptr_u8, "");
     LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, dest, ptr_u8, "");
 
@@ -1661,13 +1663,13 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
 
     if (bin_op != BinOpTypeAssign) {
         assert(source_node->type == NodeTypeBinOpExpr);
-        add_debug_source_node(g, source_node->data.bin_op_expr.op1);
+        set_debug_source_node(g, source_node->data.bin_op_expr.op1);
         LLVMValueRef left_value = LLVMBuildLoad(g->builder, target_ref, "");
 
         value = gen_arithmetic_bin_op(g, source_node, left_value, value, op1_type, op2_type, bin_op);
     }
 
-    add_debug_source_node(g, source_node);
+    set_debug_source_node(g, source_node);
     LLVMBuildStore(g->builder, value, target_ref);
     return nullptr;
 }
@@ -1698,7 +1700,7 @@ static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef may
     {
         return maybe_struct_ref;
     } else {
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 0, "");
         return get_handle_value(g, node, maybe_field_ptr, child_type);
     }
@@ -1724,7 +1726,7 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
         cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, maybe_struct_ref,
                 LLVMConstNull(child_type->type_ref), "");
     } else {
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 1, "");
         cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");
     }
@@ -1739,21 +1741,21 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
 
     LLVMPositionBuilderAtEnd(g->builder, non_null_block);
     LLVMValueRef non_null_result = gen_unwrap_maybe(g, op1_node, maybe_struct_ref);
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     LLVMBuildBr(g->builder, end_block);
     LLVMBasicBlockRef post_non_null_result_block = LLVMGetInsertBlock(g->builder);
 
     LLVMPositionBuilderAtEnd(g->builder, null_block);
     LLVMValueRef null_result = gen_expr(g, op2_node);
     if (null_reachable) {
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMBuildBr(g->builder, end_block);
     }
     LLVMBasicBlockRef post_null_result_block = LLVMGetInsertBlock(g->builder);
 
     LLVMPositionBuilderAtEnd(g->builder, end_block);
     if (null_reachable) {
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(non_null_result), "");
         LLVMValueRef incoming_values[2] = {non_null_result, null_result};
         LLVMBasicBlockRef incoming_blocks[2] = {post_non_null_result_block, post_null_result_block};
@@ -1826,7 +1828,7 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
     assert(expr_type->id == TypeTableEntryIdErrorUnion);
     TypeTableEntry *child_type = expr_type->data.error.child_type;
     LLVMValueRef err_val;
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     if (handle_is_ptr(expr_type)) {
         LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
         err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
@@ -1852,7 +1854,7 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
         LLVMBuildStore(g->builder, err_val, var->value_ref);
     }
     LLVMValueRef err_result = gen_expr(g, op2);
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     if (have_end_block) {
         LLVMBuildBr(g->builder, end_block);
     } else if (err_reachable) {
@@ -1927,10 +1929,10 @@ static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef va
     if (handle_is_ptr(return_type)) {
         assert(g->cur_ret_ptr);
         gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type);
-        add_debug_source_node(g, source_node);
+        set_debug_source_node(g, source_node);
         LLVMBuildRetVoid(g->builder);
     } else {
-        add_debug_source_node(g, source_node);
+        set_debug_source_node(g, source_node);
         LLVMBuildRet(g->builder, value);
     }
     return nullptr;
@@ -1972,7 +1974,7 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
                 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetReturn");
                 LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetContinue");
 
-                add_debug_source_node(g, node);
+                set_debug_source_node(g, node);
                 LLVMValueRef err_val;
                 if (type_has_bits(child_type)) {
                     LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
@@ -1992,7 +1994,7 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
                     if (type_has_bits(return_type->data.error.child_type)) {
                         assert(g->cur_ret_ptr);
 
-                        add_debug_source_node(g, node);
+                        set_debug_source_node(g, node);
                         LLVMValueRef tag_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 0, "");
                         LLVMBuildStore(g->builder, err_val, tag_ptr);
                         LLVMBuildRetVoid(g->builder);
@@ -2005,7 +2007,7 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
 
                 LLVMPositionBuilderAtEnd(g->builder, continue_block);
                 if (type_has_bits(child_type)) {
-                    add_debug_source_node(g, node);
+                    set_debug_source_node(g, node);
                     LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
                     return get_handle_value(g, node, val_ptr, child_type);
                 } else {
@@ -2040,7 +2042,7 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
         endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");
     }
 
-    add_debug_source_node(g, source_node);
+    set_debug_source_node(g, source_node);
     LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);
 
     LLVMPositionBuilderAtEnd(g->builder, then_block);
@@ -2115,7 +2117,7 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
     {
         cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), "");
     } else {
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, init_val, 1, "");
         cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");
     }
@@ -2271,7 +2273,7 @@ static LLVMValueRef gen_asm_expr(CodeGen *g, AstNode *node) {
     LLVMValueRef asm_fn = LLVMConstInlineAsm(function_type, buf_ptr(&llvm_template),
             buf_ptr(&constraint_buf), is_volatile, false);
 
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, "");
 }
 
@@ -2313,7 +2315,7 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
             }
             assert(buf_eql_buf(type_struct_field->name, &field_node->data.struct_val_field.name));
 
-            add_debug_source_node(g, field_node);
+            set_debug_source_node(g, field_node);
             LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, "");
             AstNode *expr_node = field_node->data.struct_val_field.expr;
             LLVMValueRef value = gen_expr(g, expr_node);
@@ -2324,7 +2326,7 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
         return tmp_struct_ptr;
     } else if (type_entry->id == TypeTableEntryIdUnreachable) {
         assert(node->data.container_init_expr.entries.length == 0);
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         if (want_debug_safety(g, node)) {
             LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
         }
@@ -2350,7 +2352,7 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
                 LLVMConstNull(g->builtin_types.entry_isize->type_ref),
                 LLVMConstInt(g->builtin_types.entry_isize->type_ref, i, false),
             };
-            add_debug_source_node(g, field_node);
+            set_debug_source_node(g, field_node);
             LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, "");
             gen_assign_raw(g, field_node, BinOpTypeAssign, elem_ptr, elem_val,
                     child_type, get_expr_type(field_node));
@@ -2382,7 +2384,7 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
             end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
         }
 
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMBuildBr(g->builder, body_block);
 
         if (continue_expr_node) {
@@ -2390,7 +2392,7 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
 
             gen_expr(g, continue_expr_node);
 
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             LLVMBuildBr(g->builder, body_block);
         }
 
@@ -2402,7 +2404,7 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
         g->continue_block_stack.pop();
 
         if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             LLVMBuildBr(g->builder, continue_block);
         }
 
@@ -2418,7 +2420,7 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
             LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileContinue") : cond_block;
         LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
 
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMBuildBr(g->builder, cond_block);
 
         if (continue_expr_node) {
@@ -2426,13 +2428,13 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
 
             gen_expr(g, continue_expr_node);
 
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             LLVMBuildBr(g->builder, cond_block);
         }
 
         LLVMPositionBuilderAtEnd(g->builder, cond_block);
         LLVMValueRef cond_val = gen_expr(g, node->data.while_expr.condition);
-        add_debug_source_node(g, node->data.while_expr.condition);
+        set_debug_source_node(g, node->data.while_expr.condition);
         LLVMBuildCondBr(g->builder, cond_val, body_block, end_block);
 
         LLVMPositionBuilderAtEnd(g->builder, body_block);
@@ -2442,7 +2444,7 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
         g->break_block_stack.pop();
         g->continue_block_stack.pop();
         if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             LLVMBuildBr(g->builder, continue_block);
         }
 
@@ -2454,7 +2456,7 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
 
 static void gen_var_debug_decl(CodeGen *g, VariableTableEntry *var) {
     BlockContext *block_context = var->block_context;
-    AstNode *source_node = block_context->node;
+    AstNode *source_node = var->decl_node;
     LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(source_node->line + 1, source_node->column + 1,
             block_context->di_scope);
     LLVMZigInsertDeclareAtEnd(g->dbuilder, var->value_ref, var->di_loc_var, debug_loc,
@@ -2482,7 +2484,7 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
     LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForContinue");
 
     LLVMValueRef array_val = gen_array_base_ptr(g, node->data.for_expr.array_expr);
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     LLVMBuildStore(g->builder, LLVMConstNull(index_var->type->type_ref), index_ptr);
 
     gen_var_debug_decl(g, index_var);
@@ -2529,12 +2531,12 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
     g->break_block_stack.pop();
     g->continue_block_stack.pop();
     if (get_expr_type(node->data.for_expr.body)->id != TypeTableEntryIdUnreachable) {
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMBuildBr(g->builder, continue_block);
     }
 
     LLVMPositionBuilderAtEnd(g->builder, continue_block);
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     LLVMValueRef new_index_val = LLVMBuildAdd(g->builder, index_val, one_const, "");
     LLVMBuildStore(g->builder, new_index_val, index_ptr);
     LLVMBuildBr(g->builder, cond_block);
@@ -2547,7 +2549,7 @@ static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
     assert(node->type == NodeTypeBreak);
     LLVMBasicBlockRef dest_block = g->break_block_stack.last();
 
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     return LLVMBuildBr(g->builder, dest_block);
 }
 
@@ -2555,7 +2557,7 @@ static LLVMValueRef gen_continue(CodeGen *g, AstNode *node) {
     assert(node->type == NodeTypeContinue);
     LLVMBasicBlockRef dest_block = g->continue_block_stack.last();
 
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     return LLVMBuildBr(g->builder, dest_block);
 }
 
@@ -2565,7 +2567,6 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
     VariableTableEntry *variable = var_decl->variable;
 
     assert(variable);
-    assert(variable->is_ptr);
 
     if (var_decl->expr) {
         *init_value = gen_expr(g, var_decl->expr);
@@ -2614,7 +2615,7 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
 
                         LLVMValueRef size_val = gen_expr(g, size_node);
 
-                        add_debug_source_node(g, source_node);
+                        set_debug_source_node(g, source_node);
                         LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref,
                                 size_val, "");
 
@@ -2645,7 +2646,7 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
             uint64_t align_bytes = get_memcpy_align(g, variable->type);
 
             // memset uninitialized memory to 0xa
-            add_debug_source_node(g, source_node);
+            set_debug_source_node(g, source_node);
             LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
             LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
             LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, "");
@@ -2708,11 +2709,11 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
     LLVMValueRef target_value;
     if (handle_is_ptr(target_type)) {
         if (target_type->id == TypeTableEntryIdEnum) {
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, target_value_handle, 0, "");
             target_value = LLVMBuildLoad(g->builder, tag_field_ptr, "");
         } else if (target_type->id == TypeTableEntryIdErrorUnion) {
-            add_debug_source_node(g, node);
+            set_debug_source_node(g, node);
             LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, target_value_handle, 0, "");
             target_value = LLVMBuildLoad(g->builder, tag_field_ptr, "");
         } else {
@@ -2732,7 +2733,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
     LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SwitchElse");
     int prong_count = node->data.switch_expr.prongs.length;
 
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, target_value, else_block, prong_count);
 
     ZigList<LLVMValueRef> incoming_values = {0};
@@ -2789,7 +2790,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
                         }
 
                         AstNode *var_node = prong_node->data.switch_prong.var_symbol;
-                        add_debug_source_node(g, var_node);
+                        set_debug_source_node(g, var_node);
                         if (prong_node->data.switch_prong.var_is_target_expr) {
                             gen_assign_raw(g, var_node, BinOpTypeAssign,
                                     prong_var->value_ref, target_value, prong_var->type, target_type);
@@ -2844,7 +2845,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
         LLVMValueRef prong_val = gen_expr(g, prong_expr);
 
         if (get_expr_type(prong_expr)->id != TypeTableEntryIdUnreachable) {
-            add_debug_source_node(g, prong_expr);
+            set_debug_source_node(g, prong_expr);
             LLVMBuildBr(g->builder, end_block);
             incoming_values.append(prong_val);
             incoming_blocks.append(prong_block);
@@ -2853,7 +2854,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
 
     if (!else_prong) {
         LLVMPositionBuilderAtEnd(g->builder, else_block);
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         if (want_debug_safety(g, node)) {
             LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
         }
@@ -2867,7 +2868,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
     LLVMPositionBuilderAtEnd(g->builder, end_block);
 
     if (result_has_bits) {
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(incoming_values.at(0)), "");
         LLVMAddIncoming(phi, incoming_values.items, incoming_blocks.items, incoming_values.length);
         return phi;
@@ -2885,7 +2886,7 @@ static LLVMValueRef gen_goto(CodeGen *g, AstNode *node) {
     BlockContext *target_context = label->decl_node->block_context;
     gen_defers_for_block(g, this_context, target_context, false, false);
 
-    add_debug_source_node(g, node);
+    set_debug_source_node(g, node);
     LLVMBuildBr(g->builder, node->data.goto_expr.label_entry->basic_block);
     return nullptr;
 }
@@ -2898,7 +2899,7 @@ static LLVMValueRef gen_label(CodeGen *g, AstNode *node) {
 
     LLVMBasicBlockRef basic_block = label->basic_block;
     if (label->entered_from_fallthrough) {
-        add_debug_source_node(g, node);
+        set_debug_source_node(g, node);
         LLVMBuildBr(g->builder, basic_block);
     }
     LLVMPositionBuilderAtEnd(g->builder, basic_block);
@@ -3519,6 +3520,23 @@ static void do_code_gen(CodeGen *g) {
 
         }
 
+        clear_debug_source_node(g);
+
+        // allocate structs which are the result of casts
+        for (int cea_i = 0; cea_i < fn_table_entry->cast_alloca_list.length; cea_i += 1) {
+            AstNode *fn_call_node = fn_table_entry->cast_alloca_list.at(cea_i);
+            Expr *expr = &fn_call_node->data.fn_call_expr.resolved_expr;
+            fn_call_node->data.fn_call_expr.tmp_ptr = LLVMBuildAlloca(g->builder,
+                    expr->type_entry->type_ref, "");
+        }
+
+        // allocate structs which are struct value expressions
+        for (int alloca_i = 0; alloca_i < fn_table_entry->struct_val_expr_alloca_list.length; alloca_i += 1) {
+            StructValExprCodeGen *struct_val_expr_node = fn_table_entry->struct_val_expr_alloca_list.at(alloca_i);
+            struct_val_expr_node->ptr = LLVMBuildAlloca(g->builder,
+                    struct_val_expr_node->type_entry->type_ref, "");
+        }
+
         // create debug variable declarations for variables and allocate all local variables
         for (int var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
             VariableTableEntry *var = fn_table_entry->variable_list.at(var_i);
@@ -3527,29 +3545,32 @@ static void do_code_gen(CodeGen *g) {
                 continue;
             }
 
-            TypeTableEntry *gen_type;
             if (var->block_context->node->type == NodeTypeFnDef) {
-                var->is_ptr = false;
                 assert(var->gen_arg_index >= 0);
-                var->value_ref = LLVMGetParam(fn, var->gen_arg_index);
-
-                gen_type = fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index].type;
+                if (handle_is_ptr(var->type)) {
+                    TypeTableEntry *gen_type = fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index].type;
+                    var->value_ref = LLVMGetParam(fn, var->gen_arg_index);
+                    var->di_loc_var = LLVMZigCreateParameterVariable(g->dbuilder, var->block_context->di_scope,
+                            buf_ptr(&var->name), import->di_file, var->decl_node->line + 1,
+                            gen_type->di_type, !g->strip_debug_symbols, 0, var->gen_arg_index + 1);
+                } else {
+                    var->value_ref = LLVMBuildAlloca(g->builder, var->type->type_ref, buf_ptr(&var->name));
+                    uint64_t align_bytes = LLVMABISizeOfType(g->target_data_ref, var->type->type_ref);
+                    LLVMSetAlignment(var->value_ref, align_bytes);
+                    var->di_loc_var = LLVMZigCreateAutoVariable(g->dbuilder, var->block_context->di_scope,
+                            buf_ptr(&var->name), import->di_file, var->decl_node->line + 1,
+                            var->type->di_type, !g->strip_debug_symbols, 0);
+                }
 
-                var->di_loc_var = LLVMZigCreateParameterVariable(g->dbuilder, var->block_context->di_scope,
-                        buf_ptr(&var->name), import->di_file, var->decl_node->line + 1,
-                        gen_type->di_type, !g->strip_debug_symbols, 0, var->gen_arg_index + 1);
             } else {
-
-                add_debug_source_node(g, var->decl_node);
                 var->value_ref = LLVMBuildAlloca(g->builder, var->type->type_ref, buf_ptr(&var->name));
+
                 uint64_t align_bytes = LLVMABISizeOfType(g->target_data_ref, var->type->type_ref);
                 LLVMSetAlignment(var->value_ref, align_bytes);
 
-                gen_type = var->type;
-
                 var->di_loc_var = LLVMZigCreateAutoVariable(g->dbuilder, var->block_context->di_scope,
                         buf_ptr(&var->name), import->di_file, var->decl_node->line + 1,
-                        gen_type->di_type, !g->strip_debug_symbols, 0);
+                        var->type->di_type, !g->strip_debug_symbols, 0);
             }
         }
 
@@ -3567,25 +3588,14 @@ static void do_code_gen(CodeGen *g) {
             VariableTableEntry *variable = param_decl->data.param_decl.variable;
             assert(variable);
 
-            gen_var_debug_decl(g, variable);
-        }
+            if (!handle_is_ptr(variable->type)) {
+                clear_debug_source_node(g);
+                LLVMBuildStore(g->builder, LLVMGetParam(fn, variable->gen_arg_index), variable->value_ref);
+            }
 
-        // allocate structs which are the result of casts
-        for (int cea_i = 0; cea_i < fn_table_entry->cast_alloca_list.length; cea_i += 1) {
-            AstNode *fn_call_node = fn_table_entry->cast_alloca_list.at(cea_i);
-            add_debug_source_node(g, fn_call_node);
-            Expr *expr = &fn_call_node->data.fn_call_expr.resolved_expr;
-            fn_call_node->data.fn_call_expr.tmp_ptr = LLVMBuildAlloca(g->builder,
-                    expr->type_entry->type_ref, "");
+            gen_var_debug_decl(g, variable);
         }
 
-        // allocate structs which are struct value expressions
-        for (int alloca_i = 0; alloca_i < fn_table_entry->struct_val_expr_alloca_list.length; alloca_i += 1) {
-            StructValExprCodeGen *struct_val_expr_node = fn_table_entry->struct_val_expr_alloca_list.at(alloca_i);
-            add_debug_source_node(g, struct_val_expr_node->source_node);
-            struct_val_expr_node->ptr = LLVMBuildAlloca(g->builder,
-                    struct_val_expr_node->type_entry->type_ref, "");
-        }
 
         TypeTableEntry *implicit_return_type = fn_def_node->data.fn_def.implicit_return_type;
         gen_block(g, fn_def_node->data.fn_def.body, implicit_return_type);
src/zig_llvm.cpp
@@ -369,11 +369,15 @@ LLVMZigDIBuilder *LLVMZigCreateDIBuilder(LLVMModuleRef module, bool allow_unreso
     return reinterpret_cast<LLVMZigDIBuilder *>(di_builder);
 }
 
-void LLVMZigSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, LLVMZigDIScope *scope) {
+void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, LLVMZigDIScope *scope) {
     unwrap(builder)->SetCurrentDebugLocation(DebugLoc::get(
                 line, column, reinterpret_cast<DIScope*>(scope)));
 }
 
+void ZigLLVMClearCurrentDebugLocation(LLVMBuilderRef builder) {
+    unwrap(builder)->SetCurrentDebugLocation(DebugLoc());
+}
+
 
 LLVMZigDILexicalBlock *LLVMZigCreateLexicalBlock(LLVMZigDIBuilder *dbuilder, LLVMZigDIScope *scope,
         LLVMZigDIFile *file, unsigned line, unsigned col)
@@ -530,6 +534,21 @@ void LLVMZigSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) {
     }
 }
 
+void ZigLLVMAddFunctionAttr(LLVMValueRef fn_ref, const char *attr_name, const char *attr_value) {
+    Function *func = unwrap<Function>(fn_ref);
+    const AttributeSet attr_set = func->getAttributes();
+    AttrBuilder attr_builder;
+    if (attr_value) {
+        attr_builder.addAttribute(attr_name, attr_value);
+    } else {
+        attr_builder.addAttribute(attr_name);
+    }
+    const AttributeSet new_attr_set = attr_set.addAttributes(func->getContext(),
+            AttributeSet::FunctionIndex, AttributeSet::get(func->getContext(),
+                AttributeSet::FunctionIndex, attr_builder));
+    func->setAttributes(new_attr_set);
+}
+
 
 static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, "");
 static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorType, "");
src/zig_llvm.hpp
@@ -102,7 +102,8 @@ unsigned LLVMZigTag_DW_structure_type(void);
 LLVMZigDIBuilder *LLVMZigCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved);
 void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module);
 
-void LLVMZigSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, LLVMZigDIScope *scope);
+void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, LLVMZigDIScope *scope);
+void ZigLLVMClearCurrentDebugLocation(LLVMBuilderRef builder);
 
 LLVMZigDIScope *LLVMZigLexicalBlockToScope(LLVMZigDILexicalBlock *lexical_block);
 LLVMZigDIScope *LLVMZigCompileUnitToScope(LLVMZigDICompileUnit *compile_unit);
@@ -149,6 +150,8 @@ LLVMZigDILocation *LLVMZigGetDebugLoc(unsigned line, unsigned col, LLVMZigDIScop
 
 void LLVMZigSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state);
 
+void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value);
+
 
 // copied from include/llvm/ADT/Triple.h
 
std/compiler_rt.zig
@@ -8,16 +8,17 @@ const udwords = [2]su_int;
 const low = if (@compile_var("is_big_endian")) 1 else 0;
 const high = 1 - low;
 
+#debug_safety(false)
 export fn __udivdi3(a: du_int, b: du_int) -> du_int {
     return __udivmoddi4(a, b, null);
 }
 
+#debug_safety(false)
 fn du_int_to_udwords(x: du_int) -> udwords {
-    // TODO ability to take address of params
-    const x2 = x;
-    return *(&udwords)(&x2);
+    return *(&udwords)(&x);
 }
 
+#debug_safety(false)
 export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
     const n_uword_bits = @sizeof(su_int) * CHAR_BIT;
     const n_udword_bits = @sizeof(du_int) * CHAR_BIT;
@@ -214,6 +215,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
     return *(&du_int)(&q[0]);
 }
 
+#debug_safety(false)
 export fn __umoddi3(a: du_int, b: du_int) -> du_int {
     var r: du_int = undefined;
     __udivmoddi4(a, b, &r);
std/math.zig
@@ -1,11 +1,9 @@
 pub fn f64_from_bits(bits: u64) -> f64 {
-    const bits2 = bits;
-    *(&f64)(&bits2)
+    *(&f64)(&bits)
 }
 
 pub fn f64_to_bits(f: f64) -> u64 {
-    const f2 = f;
-    *(&u64)(&f2)
+    *(&u64)(&f)
 }
 
 pub fn f64_get_pos_inf() -> f64 {
test/self_hosted.zig
@@ -1376,3 +1376,19 @@ fn bool_cmp() {
 }
 #static_eval_enable(false)
 fn test_bool_cmp(a: bool, b: bool) -> bool { a == b }
+
+
+#attribute("test")
+fn take_address_of_parameter() {
+    test_take_address_of_parameter(12.34);
+    test_take_address_of_parameter_noeval(12.34);
+}
+fn test_take_address_of_parameter(f: f32) {
+    const f_ptr = &f;
+    assert(*f_ptr == 12.34);
+}
+#static_eval_enable(false)
+fn test_take_address_of_parameter_noeval(f: f32) {
+    const f_ptr = &f;
+    assert(*f_ptr == 12.34);
+}