diff options
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 127 |
1 files changed, 76 insertions, 51 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index b1412b2b59..ea82b3fcd6 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -92,9 +92,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib); buf_resize(&g->global_asm, 0); - // reserve index 0 to indicate no error - g->error_decls.append(nullptr); - if (root_src_path) { Buf *src_basename = buf_alloc(); Buf *src_dir = buf_alloc(); @@ -410,7 +407,7 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e } TypeTableEntry *fn_type = fn_table_entry->type_entry; TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; - if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdPureError) { + if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdErrorSet) { return UINT32_MAX; } bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type); @@ -1442,7 +1439,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns is_err_return = return_instruction->value->value.data.rh_error_union == RuntimeHintErrorUnionError; // TODO: emit a branch to check if the return value is an error } - } else if (return_type->id == TypeTableEntryIdPureError) { + } else if (return_type->id == TypeTableEntryIdErrorSet) { is_err_return = true; } if (is_err_return) { @@ -1823,7 +1820,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, } else if (type_entry->id == TypeTableEntryIdEnum) { LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); - } else if (type_entry->id == TypeTableEntryIdPureError || + } else if (type_entry->id == TypeTableEntryIdErrorSet || type_entry->id == TypeTableEntryIdPointer || type_entry->id == TypeTableEntryIdBool) { @@ -2139,7 +2136,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, IrInstructionIntToErr *instruction) { TypeTableEntry *wanted_type = instruction->base.value.type; - assert(wanted_type->id == TypeTableEntryIdPureError); + assert(wanted_type->id == TypeTableEntryIdErrorSet); TypeTableEntry *actual_type = instruction->target->value.type; assert(actual_type->id == TypeTableEntryIdInt); @@ -2156,11 +2153,11 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, I eval_min_max_value_int(g, actual_type, &biggest_possible_err_val, true); if (bigint_fits_in_bits(&biggest_possible_err_val, 64, false) && - bigint_as_unsigned(&biggest_possible_err_val) < g->error_decls.length) + bigint_as_unsigned(&biggest_possible_err_val) < g->errors_by_index.length) { ok_bit = neq_zero_bit; } else { - LLVMValueRef error_value_count = LLVMConstInt(actual_type->type_ref, g->error_decls.length, false); + LLVMValueRef error_value_count = LLVMConstInt(actual_type->type_ref, g->errors_by_index.length, false); LLVMValueRef in_bounds_bit = LLVMBuildICmp(g->builder, LLVMIntULT, target_val, error_value_count, ""); ok_bit = LLVMBuildAnd(g->builder, neq_zero_bit, in_bounds_bit, ""); } @@ -2187,15 +2184,15 @@ static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutable *executable, I TypeTableEntry *actual_type = instruction->target->value.type; LLVMValueRef target_val = ir_llvm_value(g, instruction->target); - if (actual_type->id == TypeTableEntryIdPureError) { + if (actual_type->id == TypeTableEntryIdErrorSet) { return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), g->err_tag_type, wanted_type, target_val); } else if (actual_type->id == TypeTableEntryIdErrorUnion) { - if (!type_has_bits(actual_type->data.error.child_type)) { + if (!type_has_bits(actual_type->data.error_union.payload_type)) { return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), g->err_tag_type, wanted_type, target_val); } else { - zig_panic("TODO"); + zig_panic("TODO err to int when error union payload type not void"); } } else { zig_unreachable(); @@ -2235,7 +2232,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst switch (op_id) { case IrUnOpInvalid: - case IrUnOpError: case IrUnOpMaybe: case IrUnOpDereference: zig_unreachable(); @@ -2489,7 +2485,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr TypeTableEntry *src_return_type = fn_type_id->return_type; bool ret_has_bits = type_has_bits(src_return_type); bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type); - bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError); + bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdErrorSet); size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0); bool is_var_args = fn_type_id->is_var_args; LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); @@ -2907,7 +2903,7 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstru static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrInstructionErrName *instruction) { assert(g->generate_error_name_table); - if (g->error_decls.length == 1) { + if (g->errors_by_index.length == 1) { LLVMBuildUnreachable(g->builder); return nullptr; } @@ -2915,7 +2911,7 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI LLVMValueRef err_val = ir_llvm_value(g, instruction->value); if (ir_want_runtime_safety(g, &instruction->base)) { LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val)); - LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false); + LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->errors_by_index.length, false); add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val); } @@ -3393,11 +3389,11 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable, static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErr *instruction) { TypeTableEntry *err_union_type = instruction->value->value.type; - TypeTableEntry *child_type = err_union_type->data.error.child_type; + TypeTableEntry *payload_type = err_union_type->data.error_union.payload_type; LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->value); LLVMValueRef err_val; - if (type_has_bits(child_type)) { + if (type_has_bits(payload_type)) { LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); } else { @@ -3412,11 +3408,11 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab TypeTableEntry *ptr_type = instruction->value->value.type; assert(ptr_type->id == TypeTableEntryIdPointer); TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type; - TypeTableEntry *child_type = err_union_type->data.error.child_type; + TypeTableEntry *payload_type = err_union_type->data.error_union.payload_type; LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); - if (type_has_bits(child_type)) { + if (type_has_bits(payload_type)) { LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); return gen_load_untyped(g, err_val_ptr, 0, false, ""); } else { @@ -3428,13 +3424,13 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu TypeTableEntry *ptr_type = instruction->value->value.type; assert(ptr_type->id == TypeTableEntryIdPointer); TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type; - TypeTableEntry *child_type = err_union_type->data.error.child_type; + TypeTableEntry *payload_type = err_union_type->data.error_union.payload_type; LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); - if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->error_decls.length > 1) { + if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) { LLVMValueRef err_val; - if (type_has_bits(child_type)) { + if (type_has_bits(payload_type)) { LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); } else { @@ -3452,7 +3448,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu LLVMPositionBuilderAtEnd(g->builder, ok_block); } - if (type_has_bits(child_type)) { + if (type_has_bits(payload_type)) { return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, ""); } else { return nullptr; @@ -3493,10 +3489,10 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable assert(wanted_type->id == TypeTableEntryIdErrorUnion); - TypeTableEntry *child_type = wanted_type->data.error.child_type; + TypeTableEntry *payload_type = wanted_type->data.error_union.payload_type; LLVMValueRef err_val = ir_llvm_value(g, instruction->value); - if (!type_has_bits(child_type)) + if (!type_has_bits(payload_type)) return err_val; assert(instruction->tmp_ptr); @@ -3512,11 +3508,11 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa assert(wanted_type->id == TypeTableEntryIdErrorUnion); - TypeTableEntry *child_type = wanted_type->data.error.child_type; + TypeTableEntry *payload_type = wanted_type->data.error_union.payload_type; LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref); - if (!type_has_bits(child_type)) + if (!type_has_bits(payload_type)) return ok_err_val; assert(instruction->tmp_ptr); @@ -3527,7 +3523,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false); LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, ""); - gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, child_type, false), payload_val); + gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, payload_type, false), payload_val); return instruction->tmp_ptr; } @@ -3700,6 +3696,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdArgType: case IrInstructionIdTagType: case IrInstructionIdExport: + case IrInstructionIdErrorUnion: zig_unreachable(); case IrInstructionIdReturn: return ir_render_return(g, executable, (IrInstructionReturn *)instruction); @@ -3933,7 +3930,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con case TypeTableEntryIdUndefLit: case TypeTableEntryIdNullLit: case TypeTableEntryIdErrorUnion: - case TypeTableEntryIdPureError: + case TypeTableEntryIdErrorSet: case TypeTableEntryIdNamespace: case TypeTableEntryIdBlock: case TypeTableEntryIdBoundFn: @@ -4026,10 +4023,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { switch (type_entry->id) { case TypeTableEntryIdInt: return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint); - case TypeTableEntryIdPureError: - assert(const_val->data.x_pure_err); - return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref, - const_val->data.x_pure_err->value, false); + case TypeTableEntryIdErrorSet: + assert(const_val->data.x_err_set != nullptr); + return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, + const_val->data.x_err_set->value, false); case TypeTableEntryIdFloat: switch (type_entry->data.floating.bit_count) { case 32: @@ -4330,8 +4327,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { } case TypeTableEntryIdErrorUnion: { - TypeTableEntry *child_type = type_entry->data.error.child_type; - if (!type_has_bits(child_type)) { + TypeTableEntry *payload_type = type_entry->data.error_union.payload_type; + if (!type_has_bits(payload_type)) { uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0; return LLVMConstInt(g->err_tag_type->type_ref, value, false); } else { @@ -4340,7 +4337,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { bool make_unnamed_struct; if (const_val->data.x_err_union.err) { err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false); - err_payload_value = LLVMConstNull(child_type->type_ref); + err_payload_value = LLVMConstNull(payload_type->type_ref); make_unnamed_struct = false; } else { err_tag_value = LLVMConstNull(g->err_tag_type->type_ref); @@ -4410,21 +4407,20 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const } static void generate_error_name_table(CodeGen *g) { - if (g->err_name_table != nullptr || !g->generate_error_name_table || g->error_decls.length == 1) { + if (g->err_name_table != nullptr || !g->generate_error_name_table || g->errors_by_index.length == 1) { return; } - assert(g->error_decls.length > 0); + assert(g->errors_by_index.length > 0); TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type); - LLVMValueRef *values = allocate<LLVMValueRef>(g->error_decls.length); + LLVMValueRef *values = allocate<LLVMValueRef>(g->errors_by_index.length); values[0] = LLVMGetUndef(str_type->type_ref); - for (size_t i = 1; i < g->error_decls.length; i += 1) { - AstNode *error_decl_node = g->error_decls.at(i); - assert(error_decl_node->type == NodeTypeErrorValueDecl); - Buf *name = error_decl_node->data.error_value_decl.name; + for (size_t i = 1; i < g->errors_by_index.length; i += 1) { + ErrorTableEntry *err_entry = g->errors_by_index.at(i); + Buf *name = &err_entry->name; g->largest_err_name_len = max(g->largest_err_name_len, buf_len(name)); @@ -4443,7 +4439,7 @@ static void generate_error_name_table(CodeGen *g) { values[i] = LLVMConstNamedStruct(str_type->type_ref, fields, 2); } - LLVMValueRef err_name_table_init = LLVMConstArray(str_type->type_ref, values, (unsigned)g->error_decls.length); + LLVMValueRef err_name_table_init = LLVMConstArray(str_type->type_ref, values, (unsigned)g->errors_by_index.length); g->err_name_table = LLVMAddGlobal(g->module, LLVMTypeOf(err_name_table_init), buf_ptr(get_mangled_name(g, buf_create_from_str("__zig_err_name_table"), false))); @@ -4573,6 +4569,28 @@ static void validate_inline_fns(CodeGen *g) { static void do_code_gen(CodeGen *g) { assert(!g->errors.length); + { + // create debug type for error sets + assert(g->err_enumerators.length == g->errors_by_index.length); + uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, g->err_tag_type->type_ref); + uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, g->err_tag_type->type_ref); + ZigLLVMDIFile *err_set_di_file = nullptr; + ZigLLVMDIType *err_set_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, + ZigLLVMCompileUnitToScope(g->compile_unit), buf_ptr(&g->builtin_types.entry_global_error_set->name), + err_set_di_file, 0, + tag_debug_size_in_bits, + tag_debug_align_in_bits, + g->err_enumerators.items, g->err_enumerators.length, + g->err_tag_type->di_type, ""); + ZigLLVMReplaceTemporary(g->dbuilder, g->builtin_types.entry_global_error_set->di_type, err_set_di_type); + g->builtin_types.entry_global_error_set->di_type = err_set_di_type; + + for (size_t i = 0; i < g->error_di_types.length; i += 1) { + ZigLLVMDIType **di_type_ptr = g->error_di_types.at(i); + *di_type_ptr = err_set_di_type; + } + } + codegen_add_time_event(g, "Code Generation"); generate_error_name_table(g); @@ -5176,16 +5194,23 @@ static void define_builtin_types(CodeGen *g) { } { - TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPureError); + TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdErrorSet); buf_init_from_str(&entry->name, "error"); // TODO allow overriding this type and keep track of max value and emit an // error if there are too many errors declared g->err_tag_type = g->builtin_types.entry_u16; - g->builtin_types.entry_pure_error = entry; + g->builtin_types.entry_global_error_set = entry; entry->type_ref = g->err_tag_type->type_ref; - entry->di_type = g->err_tag_type->di_type; + + entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, + ZigLLVMTag_DW_enumeration_type(), "error", + ZigLLVMCompileUnitToScope(g->compile_unit), nullptr, 0); + + // reserve index 0 to indicate no error + g->err_enumerators.append(ZigLLVMCreateDebugEnumerator(g->dbuilder, "(none)", 0)); + g->errors_by_index.append(nullptr); g->primitive_type_table.put(&entry->name, entry); } @@ -5815,7 +5840,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry case TypeTableEntryIdBoundFn: case TypeTableEntryIdArgTuple: case TypeTableEntryIdErrorUnion: - case TypeTableEntryIdPureError: + case TypeTableEntryIdErrorSet: zig_unreachable(); case TypeTableEntryIdVoid: case TypeTableEntryIdUnreachable: @@ -5988,7 +6013,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf return; } case TypeTableEntryIdErrorUnion: - case TypeTableEntryIdPureError: + case TypeTableEntryIdErrorSet: case TypeTableEntryIdFn: zig_panic("TODO implement get_c_type for more types"); case TypeTableEntryIdInvalid: @@ -6155,7 +6180,7 @@ static void gen_h_file(CodeGen *g) { case TypeTableEntryIdUndefLit: case TypeTableEntryIdNullLit: case TypeTableEntryIdErrorUnion: - case TypeTableEntryIdPureError: + case TypeTableEntryIdErrorSet: case TypeTableEntryIdNamespace: case TypeTableEntryIdBlock: case TypeTableEntryIdBoundFn: |
