better parameter codegen

* ability to take address of a parameter (closes #97)
 * debug symbols work for parameters
master
Andrew Kelley 2016-04-27 17:34:53 -07:00
parent 09042f1b0c
commit 4815c03caa
8 changed files with 209 additions and 158 deletions

View File

@ -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 {

View File

@ -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;

View File

@ -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);
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);
}
gen_type = fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index].type;
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);
if (!handle_is_ptr(variable->type)) {
clear_debug_source_node(g);
LLVMBuildStore(g->builder, LLVMGetParam(fn, variable->gen_arg_index), variable->value_ref);
}
gen_var_debug_decl(g, variable);
}
// 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, "");
}
// 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);

View File

@ -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, "");

View File

@ -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

View File

@ -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);

View File

@ -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 {

View File

@ -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);
}