aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp614
1 files changed, 255 insertions, 359 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index fdf41415ae..144b7bb14c 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -344,11 +344,10 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, TypeTableEntry *int_type, Bui
return *fn;
}
-static LLVMValueRef get_handle_value(CodeGen *g, AstNode *source_node, LLVMValueRef ptr, TypeTableEntry *type) {
+static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *type) {
if (handle_is_ptr(type)) {
return ptr;
} else {
- set_debug_source_node(g, source_node);
return LLVMBuildLoad(g->builder, ptr, "");
}
}
@@ -378,7 +377,7 @@ static void gen_debug_safety_crash(CodeGen *g) {
LLVMBuildUnreachable(g->builder);
}
-static void add_bounds_check(CodeGen *g, AstNode *source_node, LLVMValueRef target_val,
+static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,
LLVMIntPredicate lower_pred, LLVMValueRef lower_value,
LLVMIntPredicate upper_pred, LLVMValueRef upper_value)
{
@@ -391,8 +390,6 @@ static void add_bounds_check(CodeGen *g, AstNode *source_node, LLVMValueRef targ
upper_value = nullptr;
}
- 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");
LLVMBasicBlockRef lower_ok_block = upper_value ?
@@ -425,12 +422,11 @@ 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);
- set_debug_source_node(g, node);
if (want_debug_safety(g, node)) {
LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val));
LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false);
- add_bounds_check(g, node, err_val, LLVMIntNE, zero, LLVMIntULT, end_val);
+ add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val);
}
LLVMValueRef indices[] = {
@@ -514,15 +510,12 @@ static LLVMValueRef gen_truncate(CodeGen *g, AstNode *node) {
LLVMValueRef src_val = gen_expr(g, src_node);
- set_debug_source_node(g, node);
return LLVMBuildTrunc(g->builder, src_val, dest_type->type_ref, "");
}
static LLVMValueRef gen_unreachable(CodeGen *g, AstNode *node) {
assert(node->type == NodeTypeFnCallExpr);
- set_debug_source_node(g, node);
-
if (want_debug_safety(g, node) || g->is_test_build) {
gen_debug_safety_crash(g);
} else {
@@ -545,7 +538,6 @@ static LLVMValueRef gen_shl_with_overflow(CodeGen *g, AstNode *node) {
LLVMValueRef val2 = gen_expr(g, node->data.fn_call_expr.params.at(2));
LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3));
- set_debug_source_node(g, node);
LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, "");
LLVMValueRef orig_val;
if (int_type->data.integral.is_signed) {
@@ -590,7 +582,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
operand,
LLVMConstNull(LLVMInt1Type()),
};
- set_debug_source_node(g, node);
return LLVMBuildCall(g->builder, fn_val, params, 2, "");
}
case BuiltinFnIdAddWithOverflow:
@@ -622,7 +613,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
op2,
};
- 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, "");
@@ -646,7 +636,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
- 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, "");
@@ -677,7 +666,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
- 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);
@@ -707,13 +695,11 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
case BuiltinFnIdErrName:
return gen_err_name(g, node);
case BuiltinFnIdBreakpoint:
- set_debug_source_node(g, node);
return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
case BuiltinFnIdFrameAddress:
case BuiltinFnIdReturnAddress:
{
LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref);
- set_debug_source_node(g, node);
return LLVMBuildCall(g->builder, builtin_fn->fn_val, &zero, 1, "");
}
case BuiltinFnIdCmpExchange:
@@ -760,7 +746,6 @@ 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
- 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);
@@ -804,7 +789,6 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
!wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed &&
want_debug_safety(g, source_node))
{
- set_debug_source_node(g, source_node);
LLVMValueRef zero = LLVMConstNull(actual_type->type_ref);
LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntSGE, expr_val, zero, "");
@@ -822,14 +806,11 @@ 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) {
- 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) {
- set_debug_source_node(g, source_node);
return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, "");
} else {
- set_debug_source_node(g, source_node);
return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
}
} else {
@@ -837,10 +818,8 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
}
} else if (actual_bits > wanted_bits) {
if (actual_type->id == TypeTableEntryIdFloat) {
- set_debug_source_node(g, source_node);
return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");
} else if (actual_type->id == TypeTableEntryIdInt) {
- set_debug_source_node(g, source_node);
LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
if (!want_debug_safety(g, source_node)) {
return trunc_val;
@@ -869,256 +848,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
}
}
-static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
- assert(node->type == NodeTypeFnCallExpr);
-
- AstNode *expr_node = node->data.fn_call_expr.params.at(0);
-
- LLVMValueRef expr_val = gen_expr(g, expr_node);
-
- TypeTableEntry *actual_type = get_expr_type(expr_node);
- TypeTableEntry *wanted_type = get_expr_type(node);
-
- AstNodeFnCallExpr *cast_expr = &node->data.fn_call_expr;
-
- switch (cast_expr->cast_op) {
- case CastOpNoCast:
- zig_unreachable();
- case CastOpNoop:
- return expr_val;
- case CastOpErrToInt:
- assert(actual_type->id == TypeTableEntryIdErrorUnion);
- if (!type_has_bits(actual_type->data.error.child_type)) {
- return gen_widen_or_shorten(g, node, g->err_tag_type, wanted_type, expr_val);
- } else {
- zig_panic("TODO");
- }
- case CastOpMaybeWrap:
- {
- assert(cast_expr->tmp_ptr);
- assert(wanted_type->id == TypeTableEntryIdMaybe);
- assert(actual_type);
-
- TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
-
- if (child_type->id == TypeTableEntryIdPointer ||
- child_type->id == TypeTableEntryIdFn)
- {
- return expr_val;
- } else {
- 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);
-
- set_debug_source_node(g, node);
- LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 1, "");
- LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr);
- }
-
- return cast_expr->tmp_ptr;
- }
- case CastOpNullToMaybe:
- // handled by constant expression evaluator
- zig_unreachable();
- case CastOpErrorWrap:
- {
- assert(wanted_type->id == TypeTableEntryIdErrorUnion);
- TypeTableEntry *child_type = wanted_type->data.error.child_type;
- LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref);
-
- if (!type_has_bits(child_type)) {
- return ok_err_val;
- } else {
- assert(cast_expr->tmp_ptr);
- assert(wanted_type->id == TypeTableEntryIdErrorUnion);
- assert(actual_type);
-
- 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);
-
- LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 1, "");
- gen_assign_raw(g, node, BinOpTypeAssign,
- payload_ptr, expr_val, child_type, actual_type);
-
- return cast_expr->tmp_ptr;
- }
- }
- case CastOpPureErrorWrap:
- assert(wanted_type->id == TypeTableEntryIdErrorUnion);
-
- if (!type_has_bits(wanted_type->data.error.child_type)) {
- return expr_val;
- } else {
- zig_panic("TODO");
- }
- case CastOpPtrToInt:
- set_debug_source_node(g, node);
- return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
- case CastOpIntToPtr:
- set_debug_source_node(g, node);
- return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, "");
- case CastOpPointerReinterpret:
- 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);
- case CastOpToUnknownSizeArray:
- {
- assert(cast_expr->tmp_ptr);
- assert(wanted_type->id == TypeTableEntryIdStruct);
- assert(wanted_type->data.structure.is_slice);
-
- TypeTableEntry *pointer_type = wanted_type->data.structure.fields[0].type_entry;
-
- set_debug_source_node(g, node);
-
- size_t ptr_index = wanted_type->data.structure.fields[0].gen_index;
- if (ptr_index != SIZE_MAX) {
- LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, ptr_index, "");
- LLVMValueRef expr_bitcast = LLVMBuildBitCast(g->builder, expr_val, pointer_type->type_ref, "");
- LLVMBuildStore(g->builder, expr_bitcast, ptr_ptr);
- }
-
- size_t len_index = wanted_type->data.structure.fields[1].gen_index;
- LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, len_index, "");
- LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
- actual_type->data.array.len, false);
- LLVMBuildStore(g->builder, len_val, len_ptr);
-
- return cast_expr->tmp_ptr;
- }
- case CastOpResizeSlice:
- {
- assert(cast_expr->tmp_ptr);
- assert(wanted_type->id == TypeTableEntryIdStruct);
- assert(wanted_type->data.structure.is_slice);
- assert(actual_type->id == TypeTableEntryIdStruct);
- assert(actual_type->data.structure.is_slice);
-
- TypeTableEntry *actual_pointer_type = actual_type->data.structure.fields[0].type_entry;
- TypeTableEntry *actual_child_type = actual_pointer_type->data.pointer.child_type;
- TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
- TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
-
- set_debug_source_node(g, node);
-
- size_t actual_ptr_index = actual_type->data.structure.fields[0].gen_index;
- size_t actual_len_index = actual_type->data.structure.fields[1].gen_index;
- size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
- size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index;
-
- LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_ptr_index, "");
- LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, "");
- LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr,
- wanted_type->data.structure.fields[0].type_entry->type_ref, "");
- LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr,
- wanted_ptr_index, "");
- LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr);
-
- LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_len_index, "");
- LLVMValueRef src_len = LLVMBuildLoad(g->builder, src_len_ptr, "");
- uint64_t src_size = type_size(g, actual_child_type);
- uint64_t dest_size = type_size(g, wanted_child_type);
-
- LLVMValueRef new_len;
- if (dest_size == 1) {
- LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false);
- new_len = LLVMBuildMul(g->builder, src_len, src_size_val, "");
- } else if (src_size == 1) {
- LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false);
- if (want_debug_safety(g, node)) {
- LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, "");
- LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref);
- LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, "");
- LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenOk");
- LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenFail");
- LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
-
- LLVMPositionBuilderAtEnd(g->builder, fail_block);
- gen_debug_safety_crash(g);
-
- LLVMPositionBuilderAtEnd(g->builder, ok_block);
- }
- new_len = ZigLLVMBuildExactUDiv(g->builder, src_len, dest_size_val, "");
- } else {
- zig_unreachable();
- }
-
- LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr,
- wanted_len_index, "");
- LLVMBuildStore(g->builder, new_len, dest_len_ptr);
-
-
- return cast_expr->tmp_ptr;
- }
- case CastOpBytesToSlice:
- {
- assert(cast_expr->tmp_ptr);
- assert(wanted_type->id == TypeTableEntryIdStruct);
- assert(wanted_type->data.structure.is_slice);
- assert(actual_type->id == TypeTableEntryIdArray);
-
- TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
- TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
-
- set_debug_source_node(g, node);
-
- size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
- LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, wanted_ptr_index, "");
- LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, "");
- LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr);
-
- size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index;
- LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, wanted_len_index, "");
- LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
- actual_type->data.array.len / type_size(g, wanted_child_type), false);
- LLVMBuildStore(g->builder, len_val, len_ptr);
-
- return cast_expr->tmp_ptr;
- }
- case CastOpIntToFloat:
- assert(actual_type->id == TypeTableEntryIdInt);
- if (actual_type->data.integral.is_signed) {
- set_debug_source_node(g, node);
- return LLVMBuildSIToFP(g->builder, expr_val, wanted_type->type_ref, "");
- } else {
- 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) {
- set_debug_source_node(g, node);
- return LLVMBuildFPToSI(g->builder, expr_val, wanted_type->type_ref, "");
- } else {
- 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);
- set_debug_source_node(g, node);
- return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
-
- case CastOpIntToEnum:
- return gen_widen_or_shorten(g, node, actual_type, wanted_type->data.enumeration.tag_type, expr_val);
- case CastOpEnumToInt:
- return gen_widen_or_shorten(g, node, actual_type->data.enumeration.tag_type, wanted_type, expr_val);
- }
- zig_unreachable();
-}
-
-
static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
assert(node->type == NodeTypeFnCallExpr);
if (node->data.fn_call_expr.is_builtin) {
return gen_builtin_fn_call_expr(g, node);
- } else if (node->data.fn_call_expr.cast_op != CastOpNoCast) {
- return gen_cast_expr(g, node);
}
FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
@@ -1186,7 +920,6 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
}
}
- set_debug_source_node(g, node);
LLVMValueRef result = ZigLLVMBuildCall(g->builder, fn_val,
gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, "");
@@ -1209,7 +942,6 @@ 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
- set_debug_source_node(g, node);
array_ptr = LLVMBuildLoad(g->builder, array_ptr, "");
}
} else {
@@ -1234,20 +966,18 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal
if (want_debug_safety(g, source_node)) {
LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
array_type->data.array.len, false);
- add_bounds_check(g, source_node, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
+ add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
}
LLVMValueRef indices[] = {
LLVMConstNull(g->builtin_types.entry_usize->type_ref),
subscript_value
};
- 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
};
- 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);
@@ -1255,15 +985,13 @@ 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)) {
- set_debug_source_node(g, source_node);
size_t len_index = array_type->data.structure.fields[1].gen_index;
assert(len_index != SIZE_MAX);
LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, "");
LLVMValueRef len = LLVMBuildLoad(g->builder, len_ptr, "");
- add_bounds_check(g, source_node, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len);
+ add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len);
}
- set_debug_source_node(g, source_node);
size_t ptr_index = array_type->data.structure.fields[0].gen_index;
assert(ptr_index != SIZE_MAX);
LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");
@@ -1302,7 +1030,6 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
assert(var);
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;
@@ -1312,7 +1039,6 @@ 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
- set_debug_source_node(g, node);
struct_ptr = LLVMBuildLoad(g->builder, struct_ptr, "");
}
} else {
@@ -1325,7 +1051,6 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
size_t gen_field_index = node->data.field_access_expr.type_struct_field->gen_index;
assert(gen_field_index != SIZE_MAX);
- set_debug_source_node(g, node);
return LLVMBuildStructGEP(g->builder, struct_ptr, gen_field_index, "");
}
@@ -1348,15 +1073,14 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
}
if (want_debug_safety(g, node)) {
- add_bounds_check(g, node, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
+ add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
if (node->data.slice_expr.end) {
LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
array_type->data.array.len, false);
- add_bounds_check(g, node, end_val, LLVMIntEQ, nullptr, LLVMIntULE, array_end);
+ add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, array_end);
}
}
- set_debug_source_node(g, node);
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
LLVMValueRef indices[] = {
LLVMConstNull(g->builtin_types.entry_usize->type_ref),
@@ -1375,10 +1099,9 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
LLVMValueRef end_val = gen_expr(g, node->data.slice_expr.end);
if (want_debug_safety(g, node)) {
- add_bounds_check(g, node, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
+ add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
}
- 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);
@@ -1400,7 +1123,6 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
LLVMValueRef prev_end = nullptr;
if (!node->data.slice_expr.end || want_debug_safety(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, "");
}
@@ -1415,13 +1137,12 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
if (want_debug_safety(g, node)) {
assert(prev_end);
- add_bounds_check(g, node, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
+ add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
if (node->data.slice_expr.end) {
- add_bounds_check(g, node, end_val, LLVMIntEQ, nullptr, LLVMIntULE, prev_end);
+ add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, prev_end);
}
}
- 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, "");
@@ -1461,7 +1182,6 @@ 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 {
- set_debug_source_node(g, node);
return LLVMBuildLoad(g->builder, ptr, "");
}
}
@@ -1471,7 +1191,7 @@ static LLVMValueRef gen_variable(CodeGen *g, AstNode *source_node, VariableTable
return nullptr;
} else {
assert(variable->value_ref);
- return get_handle_value(g, source_node, variable->value_ref, variable->type);
+ return get_handle_value(g, variable->value_ref, variable->type);
}
}
@@ -1494,7 +1214,6 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva
if (is_lvalue || handle_is_ptr(type_entry)) {
return ptr;
} else {
- set_debug_source_node(g, node);
return LLVMBuildLoad(g->builder, ptr, "");
}
} else if (struct_type->id == TypeTableEntryIdMetaType) {
@@ -1631,7 +1350,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
case PrefixOpNegationWrap:
{
LLVMValueRef expr = gen_expr(g, expr_node);
- set_debug_source_node(g, node);
if (expr_type->id == TypeTableEntryIdFloat) {
return LLVMBuildFNeg(g->builder, expr, "");
} else if (expr_type->id == TypeTableEntryIdInt) {
@@ -1653,13 +1371,11 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
{
LLVMValueRef expr = gen_expr(g, expr_node);
LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
- set_debug_source_node(g, node);
return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, "");
}
case PrefixOpBinNot:
{
LLVMValueRef expr = gen_expr(g, expr_node);
- set_debug_source_node(g, node);
return LLVMBuildNot(g->builder, expr, "");
}
case PrefixOpAddressOf:
@@ -1677,7 +1393,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
return nullptr;
} else {
TypeTableEntry *child_type = expr_type->data.pointer.child_type;
- return get_handle_value(g, node, expr, child_type);
+ return get_handle_value(g, expr, child_type);
}
}
case PrefixOpMaybe:
@@ -1698,13 +1414,11 @@ 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)) {
- 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;
}
- 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");
@@ -1719,7 +1433,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
if (type_has_bits(child_type)) {
LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
- return get_handle_value(g, expr_node, child_val_ptr, child_type);
+ return get_handle_value(g, child_val_ptr, child_type);
} else {
return nullptr;
}
@@ -1733,7 +1447,6 @@ 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)) {
- set_debug_source_node(g, node);
LLVMValueRef cond_val;
if (child_type->id == TypeTableEntryIdPointer ||
child_type->id == TypeTableEntryIdFn)
@@ -1761,9 +1474,8 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
{
return expr_val;
} else {
- 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);
+ return get_handle_value(g, maybe_field_ptr, child_type);
}
}
}
@@ -1773,7 +1485,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,
TypeTableEntry *type_entry, bool exact)
{
- set_debug_source_node(g, source_node);
if (want_debug_safety(g, source_node)) {
LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);
@@ -1846,22 +1557,18 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
switch (bin_op) {
case BinOpTypeBinOr:
case BinOpTypeAssignBitOr:
- set_debug_source_node(g, source_node);
return LLVMBuildOr(g->builder, val1, val2, "");
case BinOpTypeBinXor:
case BinOpTypeAssignBitXor:
- set_debug_source_node(g, source_node);
return LLVMBuildXor(g->builder, val1, val2, "");
case BinOpTypeBinAnd:
case BinOpTypeAssignBitAnd:
- set_debug_source_node(g, source_node);
return LLVMBuildAnd(g->builder, val1, val2, "");
case BinOpTypeBitShiftLeft:
case BinOpTypeBitShiftLeftWrap:
case BinOpTypeAssignBitShiftLeft:
case BinOpTypeAssignBitShiftLeftWrap:
{
- set_debug_source_node(g, source_node);
assert(op1_type->id == TypeTableEntryIdInt);
bool is_wrapping = (bin_op == BinOpTypeBitShiftLeftWrap) ||
(bin_op == BinOpTypeAssignBitShiftLeftWrap);
@@ -1880,7 +1587,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
assert(op1_type->id == TypeTableEntryIdInt);
assert(op2_type->id == TypeTableEntryIdInt);
- set_debug_source_node(g, source_node);
if (op1_type->data.integral.is_signed) {
return LLVMBuildAShr(g->builder, val1, val2, "");
} else {
@@ -1890,7 +1596,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
case BinOpTypeAddWrap:
case BinOpTypeAssignPlus:
case BinOpTypeAssignPlusWrap:
- set_debug_source_node(g, source_node);
if (op1_type->id == TypeTableEntryIdFloat) {
return LLVMBuildFAdd(g->builder, val1, val2, "");
} else if (op1_type->id == TypeTableEntryIdInt) {
@@ -1911,7 +1616,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
case BinOpTypeSubWrap:
case BinOpTypeAssignMinus:
case BinOpTypeAssignMinusWrap:
- set_debug_source_node(g, source_node);
if (op1_type->id == TypeTableEntryIdFloat) {
return LLVMBuildFSub(g->builder, val1, val2, "");
} else if (op1_type->id == TypeTableEntryIdInt) {
@@ -1932,7 +1636,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
case BinOpTypeMultWrap:
case BinOpTypeAssignTimes:
case BinOpTypeAssignTimesWrap:
- set_debug_source_node(g, source_node);
if (op1_type->id == TypeTableEntryIdFloat) {
return LLVMBuildFMul(g->builder, val1, val2, "");
} else if (op1_type->id == TypeTableEntryIdInt) {
@@ -1954,7 +1657,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
return gen_div(g, source_node, val1, val2, op1_type, false);
case BinOpTypeMod:
case BinOpTypeAssignMod:
- set_debug_source_node(g, source_node);
if (op1_type->id == TypeTableEntryIdFloat) {
return LLVMBuildFRem(g->builder, val1, val2, "");
} else {
@@ -2044,7 +1746,6 @@ 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);
- 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, "");
@@ -2081,18 +1782,15 @@ 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");
- 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);
- set_debug_source_node(g, node);
LLVMBuildBr(g->builder, false_block);
LLVMPositionBuilderAtEnd(g->builder, false_block);
- 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};
@@ -2112,7 +1810,6 @@ 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");
- set_debug_source_node(g, expr_node);
LLVMBuildCondBr(g->builder, val1, true_block, false_block);
LLVMPositionBuilderAtEnd(g->builder, false_block);
@@ -2120,11 +1817,9 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
- set_debug_source_node(g, expr_node);
LLVMBuildBr(g->builder, true_block);
LLVMPositionBuilderAtEnd(g->builder, true_block);
- 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};
@@ -2133,14 +1828,13 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
return phi;
}
-static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest,
+static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef dest,
TypeTableEntry *type_entry)
{
assert(handle_is_ptr(type_entry));
LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
- 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, "");
@@ -2172,18 +1866,16 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
assert(op1_type == op2_type);
assert(bin_op == BinOpTypeAssign);
- return gen_struct_memcpy(g, source_node, value, target_ref, op1_type);
+ return gen_struct_memcpy(g, value, target_ref, op1_type);
}
if (bin_op != BinOpTypeAssign) {
assert(source_node->type == NodeTypeBinOpExpr);
- 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);
}
- set_debug_source_node(g, source_node);
LLVMBuildStore(g->builder, value, target_ref);
return nullptr;
}
@@ -2214,9 +1906,8 @@ static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef may
{
return maybe_struct_ref;
} else {
- 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);
+ return get_handle_value(g, maybe_field_ptr, child_type);
}
}
@@ -2240,7 +1931,6 @@ 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 {
- 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, "");
}
@@ -2255,21 +1945,18 @@ 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);
- 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) {
- 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) {
- 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};
@@ -2351,7 +2038,6 @@ 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;
- 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, "");
@@ -2377,7 +2063,6 @@ 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);
- set_debug_source_node(g, node);
if (have_end_block) {
LLVMBuildBr(g->builder, end_block);
} else if (err_reachable) {
@@ -2389,7 +2074,7 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
return nullptr;
}
LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
- LLVMValueRef child_val = get_handle_value(g, node, child_val_ptr, child_type);
+ LLVMValueRef child_val = get_handle_value(g, child_val_ptr, child_type);
if (!have_end_block) {
return child_val;
@@ -2452,17 +2137,14 @@ static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef va
bool is_extern = g->cur_fn->type_entry->data.fn.fn_type_id.is_extern;
if (handle_is_ptr(return_type)) {
if (is_extern) {
- set_debug_source_node(g, source_node);
LLVMValueRef by_val_value = LLVMBuildLoad(g->builder, value, "");
LLVMBuildRet(g->builder, by_val_value);
} else {
assert(g->cur_ret_ptr);
gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type);
- set_debug_source_node(g, source_node);
LLVMBuildRetVoid(g->builder);
}
} else {
- set_debug_source_node(g, source_node);
LLVMBuildRet(g->builder, value);
}
return nullptr;
@@ -2504,7 +2186,6 @@ 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");
- set_debug_source_node(g, node);
LLVMValueRef err_val;
if (type_has_bits(child_type)) {
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
@@ -2524,7 +2205,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
if (type_has_bits(return_type->data.error.child_type)) {
assert(g->cur_ret_ptr);
- 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);
@@ -2537,9 +2217,8 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
LLVMPositionBuilderAtEnd(g->builder, continue_block);
if (type_has_bits(child_type)) {
- set_debug_source_node(g, node);
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
- return get_handle_value(g, node, val_ptr, child_type);
+ return get_handle_value(g, val_ptr, child_type);
} else {
return nullptr;
}
@@ -2552,7 +2231,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetReturn");
LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetContinue");
- set_debug_source_node(g, node);
LLVMValueRef maybe_val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
LLVMValueRef is_non_null = LLVMBuildLoad(g->builder, maybe_val_ptr, "");
@@ -2566,7 +2244,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
if (handle_is_ptr(return_type)) {
assert(g->cur_ret_ptr);
- set_debug_source_node(g, node);
LLVMValueRef maybe_bit_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 1, "");
LLVMBuildStore(g->builder, zero, maybe_bit_ptr);
LLVMBuildRetVoid(g->builder);
@@ -2577,9 +2254,8 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
LLVMPositionBuilderAtEnd(g->builder, continue_block);
if (type_has_bits(child_type)) {
- set_debug_source_node(g, node);
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
- return get_handle_value(g, node, val_ptr, child_type);
+ return get_handle_value(g, val_ptr, child_type);
} else {
return nullptr;
}
@@ -2610,7 +2286,6 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");
}
- set_debug_source_node(g, source_node);
LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);
LLVMPositionBuilderAtEnd(g->builder, then_block);
@@ -2632,7 +2307,6 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
if (then_endif_reachable || else_endif_reachable) {
LLVMPositionBuilderAtEnd(g->builder, endif_block);
if (use_then_value && use_else_value) {
- set_debug_source_node(g, source_node);
LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");
LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};
LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block};
@@ -2697,7 +2371,7 @@ static LLVMValueRef gen_if_var_then_block(CodeGen *g, AstNode *node, VariableTab
payload_val = init_val;
} else {
LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, init_val, 0, "");
- payload_val = get_handle_value(g, node, payload_ptr, child_type);
+ payload_val = get_handle_value(g, payload_ptr, child_type);
}
gen_assign_raw(g, node, BinOpTypeAssign, variable->value_ref, payload_val,
variable->type, child_type);
@@ -2736,10 +2410,8 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
LLVMValueRef cond_value;
if (maybe_is_ptr) {
- set_debug_source_node(g, node);
cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), "");
} else {
- set_debug_source_node(g, node);
LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, init_val, 1, "");
cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");
}
@@ -2760,7 +2432,6 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeEndIf");
}
- set_debug_source_node(g, node);
LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);
LLVMPositionBuilderAtEnd(g->builder, then_block);
@@ -2810,7 +2481,7 @@ static LLVMValueRef ir_render_load_var(CodeGen *g, IrExecutable *executable,
return nullptr;
assert(var->value_ref);
- return get_handle_value(g, load_var_instruction->base.source_node, var->value_ref, var->type);
+ return get_handle_value(g, var->value_ref, var->type);
}
static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable,
@@ -2894,6 +2565,233 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
zig_unreachable();
}
+static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
+ IrInstructionCast *cast_instruction)
+{
+ TypeTableEntry *actual_type = cast_instruction->value->type_entry;
+ TypeTableEntry *wanted_type = cast_instruction->base.type_entry;
+ LLVMValueRef expr_val = cast_instruction->value->llvm_value;
+ assert(expr_val);
+
+ switch (cast_instruction->cast_op) {
+ case CastOpNoCast:
+ zig_unreachable();
+ case CastOpNoop:
+ return expr_val;
+ case CastOpErrToInt:
+ assert(actual_type->id == TypeTableEntryIdErrorUnion);
+ if (!type_has_bits(actual_type->data.error.child_type)) {
+ return gen_widen_or_shorten(g, cast_instruction->base.source_node,
+ g->err_tag_type, wanted_type, expr_val);
+ } else {
+ zig_panic("TODO");
+ }
+ case CastOpMaybeWrap:
+ {
+ assert(cast_instruction->tmp_ptr);
+ assert(wanted_type->id == TypeTableEntryIdMaybe);
+ assert(actual_type);
+
+ TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
+
+ if (child_type->id == TypeTableEntryIdPointer ||
+ child_type->id == TypeTableEntryIdFn)
+ {
+ return expr_val;
+ } else {
+ LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 0, "");
+ gen_assign_raw(g, cast_instruction->base.source_node, BinOpTypeAssign,
+ val_ptr, expr_val, child_type, actual_type);
+
+ LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 1, "");
+ LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr);
+ }
+
+ return cast_instruction->tmp_ptr;
+ }
+ case CastOpNullToMaybe:
+ // handled by constant expression evaluator
+ zig_unreachable();
+ case CastOpErrorWrap:
+ {
+ assert(wanted_type->id == TypeTableEntryIdErrorUnion);
+ TypeTableEntry *child_type = wanted_type->data.error.child_type;
+ LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref);
+
+ if (!type_has_bits(child_type)) {
+ return ok_err_val;
+ } else {
+ assert(cast_instruction->tmp_ptr);
+ assert(wanted_type->id == TypeTableEntryIdErrorUnion);
+ assert(actual_type);
+
+ LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 0, "");
+ LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr);
+
+ LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 1, "");
+ gen_assign_raw(g, cast_instruction->base.source_node, BinOpTypeAssign,
+ payload_ptr, expr_val, child_type, actual_type);
+
+ return cast_instruction->tmp_ptr;
+ }
+ }
+ case CastOpPureErrorWrap:
+ assert(wanted_type->id == TypeTableEntryIdErrorUnion);
+
+ if (!type_has_bits(wanted_type->data.error.child_type)) {
+ return expr_val;
+ } else {
+ zig_panic("TODO");
+ }
+ case CastOpPtrToInt:
+ return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
+ case CastOpIntToPtr:
+ return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, "");
+ case CastOpPointerReinterpret:
+ return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
+ case CastOpWidenOrShorten:
+ return gen_widen_or_shorten(g, cast_instruction->base.source_node, actual_type, wanted_type, expr_val);
+ case CastOpToUnknownSizeArray:
+ {
+ assert(cast_instruction->tmp_ptr);
+ assert(wanted_type->id == TypeTableEntryIdStruct);
+ assert(wanted_type->data.structure.is_slice);
+
+ TypeTableEntry *pointer_type = wanted_type->data.structure.fields[0].type_entry;
+
+
+ size_t ptr_index = wanted_type->data.structure.fields[0].gen_index;
+ if (ptr_index != SIZE_MAX) {
+ LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, ptr_index, "");
+ LLVMValueRef expr_bitcast = LLVMBuildBitCast(g->builder, expr_val, pointer_type->type_ref, "");
+ LLVMBuildStore(g->builder, expr_bitcast, ptr_ptr);
+ }
+
+ size_t len_index = wanted_type->data.structure.fields[1].gen_index;
+ LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, len_index, "");
+ LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
+ actual_type->data.array.len, false);
+ LLVMBuildStore(g->builder, len_val, len_ptr);
+
+ return cast_instruction->tmp_ptr;
+ }
+ case CastOpResizeSlice:
+ {
+ assert(cast_instruction->tmp_ptr);
+ assert(wanted_type->id == TypeTableEntryIdStruct);
+ assert(wanted_type->data.structure.is_slice);
+ assert(actual_type->id == TypeTableEntryIdStruct);
+ assert(actual_type->data.structure.is_slice);
+
+ TypeTableEntry *actual_pointer_type = actual_type->data.structure.fields[0].type_entry;
+ TypeTableEntry *actual_child_type = actual_pointer_type->data.pointer.child_type;
+ TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
+ TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
+
+
+ size_t actual_ptr_index = actual_type->data.structure.fields[0].gen_index;
+ size_t actual_len_index = actual_type->data.structure.fields[1].gen_index;
+ size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
+ size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index;
+
+ LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_ptr_index, "");
+ LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, "");
+ LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr,
+ wanted_type->data.structure.fields[0].type_entry->type_ref, "");
+ LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
+ wanted_ptr_index, "");
+ LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr);
+
+ LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_len_index, "");
+ LLVMValueRef src_len = LLVMBuildLoad(g->builder, src_len_ptr, "");
+ uint64_t src_size = type_size(g, actual_child_type);
+ uint64_t dest_size = type_size(g, wanted_child_type);
+
+ LLVMValueRef new_len;
+ if (dest_size == 1) {
+ LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false);
+ new_len = LLVMBuildMul(g->builder, src_len, src_size_val, "");
+ } else if (src_size == 1) {
+ LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false);
+ if (ir_want_debug_safety(g, &cast_instruction->base)) {
+ LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, "");
+ LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref);
+ LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, "");
+ LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenOk");
+ LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenFail");
+ LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
+
+ LLVMPositionBuilderAtEnd(g->builder, fail_block);
+ gen_debug_safety_crash(g);
+
+ LLVMPositionBuilderAtEnd(g->builder, ok_block);
+ }
+ new_len = ZigLLVMBuildExactUDiv(g->builder, src_len, dest_size_val, "");
+ } else {
+ zig_unreachable();
+ }
+
+ LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
+ wanted_len_index, "");
+ LLVMBuildStore(g->builder, new_len, dest_len_ptr);
+
+
+ return cast_instruction->tmp_ptr;
+ }
+ case CastOpBytesToSlice:
+ {
+ assert(cast_instruction->tmp_ptr);
+ assert(wanted_type->id == TypeTableEntryIdStruct);
+ assert(wanted_type->data.structure.is_slice);
+ assert(actual_type->id == TypeTableEntryIdArray);
+
+ TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
+ TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
+
+
+ size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
+ LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, wanted_ptr_index, "");
+ LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, "");
+ LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr);
+
+ size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index;
+ LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, wanted_len_index, "");
+ LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
+ actual_type->data.array.len / type_size(g, wanted_child_type), false);
+ LLVMBuildStore(g->builder, len_val, len_ptr);
+
+ return cast_instruction->tmp_ptr;
+ }
+ case CastOpIntToFloat:
+ assert(actual_type->id == TypeTableEntryIdInt);
+ if (actual_type->data.integral.is_signed) {
+ return LLVMBuildSIToFP(g->builder, expr_val, wanted_type->type_ref, "");
+ } else {
+ return LLVMBuildUIToFP(g->builder, expr_val, wanted_type->type_ref, "");
+ }
+ case CastOpFloatToInt:
+ assert(wanted_type->id == TypeTableEntryIdInt);
+ if (wanted_type->data.integral.is_signed) {
+ return LLVMBuildFPToSI(g->builder, expr_val, wanted_type->type_ref, "");
+ } else {
+ return LLVMBuildFPToUI(g->builder, expr_val, wanted_type->type_ref, "");
+ }
+
+ case CastOpBoolToInt:
+ assert(wanted_type->id == TypeTableEntryIdInt);
+ assert(actual_type->id == TypeTableEntryIdBool);
+ return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
+
+ case CastOpIntToEnum:
+ return gen_widen_or_shorten(g, cast_instruction->base.source_node,
+ actual_type, wanted_type->data.enumeration.tag_type, expr_val);
+ case CastOpEnumToInt:
+ return gen_widen_or_shorten(g, cast_instruction->base.source_node,
+ actual_type->data.enumeration.tag_type, wanted_type, expr_val);
+ }
+ zig_unreachable();
+}
+
static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
set_debug_source_node(g, instruction->source_node);
switch (instruction->id) {
@@ -2907,13 +2805,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_load_var(g, executable, (IrInstructionLoadVar *)instruction);
case IrInstructionIdBinOp:
return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
+ case IrInstructionIdCast:
+ return ir_render_cast(g, executable, (IrInstructionCast *)instruction);
case IrInstructionIdCondBr:
case IrInstructionIdSwitchBr:
case IrInstructionIdPhi:
case IrInstructionIdStoreVar:
case IrInstructionIdCall:
case IrInstructionIdBuiltinCall:
- case IrInstructionIdCast:
zig_panic("TODO render more IR instructions to LLVM");
}
zig_unreachable();
@@ -3592,7 +3491,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
1, "");
LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
LLVMPointerType(enum_field->type_entry->type_ref, 0), "");
- LLVMValueRef handle_val = get_handle_value(g, var_node, bitcasted_union_field_ptr,
+ LLVMValueRef handle_val = get_handle_value(g, bitcasted_union_field_ptr,
enum_field->type_entry);
gen_assign_raw(g, var_node, BinOpTypeAssign,
@@ -3602,8 +3501,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
// variable is the payload
LLVMValueRef err_payload_ptr = LLVMBuildStructGEP(g->builder,
target_value_handle, 1, "");
- LLVMValueRef handle_val = get_handle_value(g, var_node,
- err_payload_ptr, prong_var->type);
+ LLVMValueRef handle_val = get_handle_value(g, err_payload_ptr, prong_var->type);
gen_assign_raw(g, var_node, BinOpTypeAssign,
prong_var->value_ref, handle_val, prong_var->type, prong_var->type);
} else {
@@ -4375,10 +4273,8 @@ static void do_code_gen(CodeGen *g) {
// allocate structs which are the result of casts
for (size_t 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, "");
+ IrInstructionCast *cast_instruction = fn_table_entry->cast_alloca_list.at(cea_i);
+ cast_instruction->tmp_ptr = LLVMBuildAlloca(g->builder, cast_instruction->base.type_entry->type_ref, "");
}
// allocate structs which are struct value expressions