From 56a8f2b018a6ee1f1116a64d34803511a6fbad80 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 24 Nov 2018 14:36:16 -0500 Subject: fix @intCast not catching negative numbers to unsigned --- src/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index 40f71e38fe..096552037d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1645,7 +1645,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z zig_unreachable(); } - if (actual_bits >= wanted_bits && actual_type->id == ZigTypeIdInt && + if (actual_type->id == ZigTypeIdInt && !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed && want_runtime_safety) { -- cgit v1.2.3 From 3d2752cc3677535ddfbeeefba4036633bcab01dc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 24 Nov 2018 16:15:58 -0500 Subject: refactor type_requires_comptime to have possible error fixes a compiler crash when building https://github.com/AndreaOrru/zen --- src/analyze.cpp | 85 ++++++++++++++++++++++++------------------- src/analyze.hpp | 8 ++++- src/codegen.cpp | 10 ++++-- src/ir.cpp | 110 +++++++++++++++++++++++++++++++++----------------------- 4 files changed, 129 insertions(+), 84 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 349169f9d1..e5679a21d5 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1619,13 +1619,16 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdPromise: - if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) - return g->builtin_types.entry_invalid; - if (type_requires_comptime(type_entry)) { - add_node_error(g, param_node->data.param_decl.type, - buf_sprintf("parameter of type '%s' must be declared comptime", - buf_ptr(&type_entry->name))); - return g->builtin_types.entry_invalid; + switch (type_requires_comptime(g, type_entry)) { + case ReqCompTimeNo: + break; + case ReqCompTimeYes: + add_node_error(g, param_node->data.param_decl.type, + buf_sprintf("parameter of type '%s' must be declared comptime", + buf_ptr(&type_entry->name))); + return g->builtin_types.entry_invalid; + case ReqCompTimeInvalid: + return g->builtin_types.entry_invalid; } break; } @@ -1711,10 +1714,13 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdPromise: - if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusZeroBitsKnown))) - return g->builtin_types.entry_invalid; - if (type_requires_comptime(fn_type_id.return_type)) { - return get_generic_fn_type(g, &fn_type_id); + switch (type_requires_comptime(g, fn_type_id.return_type)) { + case ReqCompTimeInvalid: + return g->builtin_types.entry_invalid; + case ReqCompTimeYes: + return get_generic_fn_type(g, &fn_type_id); + case ReqCompTimeNo: + break; } break; } @@ -2560,8 +2566,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { assert(struct_type->id == ZigTypeIdStruct); - Error err; - if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) return ErrorSemanticAnalyzeFail; if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown) @@ -2619,13 +2623,15 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { buf_sprintf("enums, not structs, support field assignment")); } - if ((err = type_resolve(g, field_type, ResolveStatusZeroBitsKnown))) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - continue; - } - - if (type_requires_comptime(field_type)) { - struct_type->data.structure.requires_comptime = true; + switch (type_requires_comptime(g, field_type)) { + case ReqCompTimeYes: + struct_type->data.structure.requires_comptime = true; + break; + case ReqCompTimeInvalid: + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + continue; + case ReqCompTimeNo: + break; } if (!type_has_bits(field_type)) @@ -2890,11 +2896,17 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { } union_field->type_entry = field_type; - if (type_requires_comptime(field_type)) { - union_type->data.unionation.requires_comptime = true; + switch (type_requires_comptime(g, field_type)) { + case ReqCompTimeInvalid: + union_type->data.unionation.is_invalid = true; + continue; + case ReqCompTimeYes: + union_type->data.unionation.requires_comptime = true; + break; + case ReqCompTimeNo: + break; } - if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value, buf_sprintf("non-enum union field assignment")); @@ -5089,7 +5101,10 @@ bool type_has_bits(ZigType *type_entry) { return !type_entry->zero_bits; } -bool type_requires_comptime(ZigType *type_entry) { +ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { + Error err; + if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) + return ReqCompTimeInvalid; switch (type_entry->id) { case ZigTypeIdInvalid: case ZigTypeIdOpaque: @@ -5102,27 +5117,25 @@ bool type_requires_comptime(ZigType *type_entry) { case ZigTypeIdNamespace: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: - return true; + return ReqCompTimeYes; case ZigTypeIdArray: - return type_requires_comptime(type_entry->data.array.child_type); + return type_requires_comptime(g, type_entry->data.array.child_type); case ZigTypeIdStruct: - assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); - return type_entry->data.structure.requires_comptime; + return type_entry->data.structure.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo; case ZigTypeIdUnion: - assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); - return type_entry->data.unionation.requires_comptime; + return type_entry->data.unionation.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo; case ZigTypeIdOptional: - return type_requires_comptime(type_entry->data.maybe.child_type); + return type_requires_comptime(g, type_entry->data.maybe.child_type); case ZigTypeIdErrorUnion: - return type_requires_comptime(type_entry->data.error_union.payload_type); + return type_requires_comptime(g, type_entry->data.error_union.payload_type); case ZigTypeIdPointer: if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) { - return false; + return ReqCompTimeNo; } else { - return type_requires_comptime(type_entry->data.pointer.child_type); + return type_requires_comptime(g, type_entry->data.pointer.child_type); } case ZigTypeIdFn: - return type_entry->data.fn.is_generic; + return type_entry->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo; case ZigTypeIdEnum: case ZigTypeIdErrorSet: case ZigTypeIdBool: @@ -5131,7 +5144,7 @@ bool type_requires_comptime(ZigType *type_entry) { case ZigTypeIdVoid: case ZigTypeIdUnreachable: case ZigTypeIdPromise: - return false; + return ReqCompTimeNo; } zig_unreachable(); } diff --git a/src/analyze.hpp b/src/analyze.hpp index e727b050ea..b506b533ca 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -87,7 +87,6 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node); ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value); void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc); AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index); -bool type_requires_comptime(ZigType *type_entry); Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry); Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status); void complete_enum(CodeGen *g, ZigType *enum_type); @@ -216,4 +215,11 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field); +enum ReqCompTime { + ReqCompTimeInvalid, + ReqCompTimeNo, + ReqCompTimeYes, +}; +ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry); + #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index 096552037d..37e0424961 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6281,8 +6281,14 @@ static void do_code_gen(CodeGen *g) { } if (ir_get_var_is_comptime(var)) continue; - if (type_requires_comptime(var->value->type)) - continue; + switch (type_requires_comptime(g, var->value->type)) { + case ReqCompTimeInvalid: + zig_unreachable(); + case ReqCompTimeYes: + continue; + case ReqCompTimeNo: + break; + } if (var->src_arg_index == SIZE_MAX) { var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes); diff --git a/src/ir.cpp b/src/ir.cpp index a62da827bc..1edb122670 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -11276,7 +11276,6 @@ static bool optional_value_is_null(ConstExprValue *val) { } static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { - Error err; IrInstruction *op1 = bin_op_instruction->op1->child; if (type_is_invalid(op1->value.type)) return ira->codegen->invalid_instruction; @@ -11470,10 +11469,19 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * if (casted_op2 == ira->codegen->invalid_instruction) return ira->codegen->invalid_instruction; - if ((err = type_resolve(ira->codegen, resolved_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + bool requires_comptime; + switch (type_requires_comptime(ira->codegen, resolved_type)) { + case ReqCompTimeYes: + requires_comptime = true; + break; + case ReqCompTimeNo: + requires_comptime = false; + break; + case ReqCompTimeInvalid: + return ira->codegen->invalid_instruction; + } - bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type); + bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type); if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); if (op1_val == nullptr) @@ -12406,42 +12414,41 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct ZigType *result_type = casted_init_value->value.type; if (type_is_invalid(result_type)) { result_type = ira->codegen->builtin_types.entry_invalid; - } else { - if ((err = type_resolve(ira->codegen, result_type, ResolveStatusZeroBitsKnown))) { - result_type = ira->codegen->builtin_types.entry_invalid; - } + } else if (result_type->id == ZigTypeIdUnreachable || result_type->id == ZigTypeIdOpaque) { + ir_add_error_node(ira, source_node, + buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name))); + result_type = ira->codegen->builtin_types.entry_invalid; } - if (!type_is_invalid(result_type)) { - if (result_type->id == ZigTypeIdUnreachable || - result_type->id == ZigTypeIdOpaque) - { + switch (type_requires_comptime(ira->codegen, result_type)) { + case ReqCompTimeInvalid: + result_type = ira->codegen->builtin_types.entry_invalid; + break; + case ReqCompTimeYes: { + var_class_requires_const = true; + if (!var->gen_is_const && !is_comptime_var) { ir_add_error_node(ira, source_node, - buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name))); + buf_sprintf("variable of type '%s' must be const or comptime", + buf_ptr(&result_type->name))); result_type = ira->codegen->builtin_types.entry_invalid; - } else if (type_requires_comptime(result_type)) { + } + break; + } + case ReqCompTimeNo: + if (casted_init_value->value.special == ConstValSpecialStatic && + casted_init_value->value.type->id == ZigTypeIdFn && + casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) + { var_class_requires_const = true; - if (!var->gen_is_const && !is_comptime_var) { - ir_add_error_node(ira, source_node, - buf_sprintf("variable of type '%s' must be const or comptime", - buf_ptr(&result_type->name))); + if (!var->src_is_const && !is_comptime_var) { + ErrorMsg *msg = ir_add_error_node(ira, source_node, + buf_sprintf("functions marked inline must be stored in const or comptime var")); + AstNode *proto_node = casted_init_value->value.data.x_ptr.data.fn.fn_entry->proto_node; + add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here")); result_type = ira->codegen->builtin_types.entry_invalid; } - } else { - if (casted_init_value->value.special == ConstValSpecialStatic && - casted_init_value->value.type->id == ZigTypeIdFn && - casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) - { - var_class_requires_const = true; - if (!var->src_is_const && !is_comptime_var) { - ErrorMsg *msg = ir_add_error_node(ira, source_node, - buf_sprintf("functions marked inline must be stored in const or comptime var")); - AstNode *proto_node = casted_init_value->value.data.x_ptr.data.fn.fn_entry->proto_node; - add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here")); - result_type = ira->codegen->builtin_types.entry_invalid; - } - } } + break; } if (var->value->type != nullptr && !is_comptime_var) { @@ -12912,10 +12919,15 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod } if (!comptime_arg) { - if (type_requires_comptime(casted_arg->value.type)) { + switch (type_requires_comptime(ira->codegen, casted_arg->value.type)) { + case ReqCompTimeYes: ir_add_error(ira, casted_arg, buf_sprintf("parameter of type '%s' requires comptime", buf_ptr(&casted_arg->value.type->name))); return false; + case ReqCompTimeInvalid: + return false; + case ReqCompTimeNo: + break; } casted_args[fn_type_id->param_count] = casted_arg; @@ -13388,12 +13400,15 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call inst_fn_type_id.return_type = specified_return_type; } - if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; - - if (type_requires_comptime(specified_return_type)) { + switch (type_requires_comptime(ira->codegen, specified_return_type)) { + case ReqCompTimeYes: // Throw out our work and call the function as if it were comptime. - return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr, true, FnInlineAuto); + return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr, + true, FnInlineAuto); + case ReqCompTimeInvalid: + return ira->codegen->invalid_instruction; + case ReqCompTimeNo: + break; } } IrInstruction *async_allocator_inst = nullptr; @@ -14334,11 +14349,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } else { // runtime known element index - if (type_requires_comptime(return_type)) { + switch (type_requires_comptime(ira->codegen, return_type)) { + case ReqCompTimeYes: ir_add_error(ira, elem_index, buf_sprintf("values of type '%s' must be comptime known, but index value is runtime known", buf_ptr(&return_type->data.pointer.child_type->name))); return ira->codegen->invalid_instruction; + case ReqCompTimeInvalid: + return ira->codegen->invalid_instruction; + case ReqCompTimeNo: + break; } if (ptr_align < abi_align) { if (elem_size >= ptr_align && elem_size % ptr_align == 0) { @@ -19390,7 +19410,6 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, } static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) { - Error err; AstNode *proto_node = instruction->base.source_node; assert(proto_node->type == NodeTypeFnProto); @@ -19429,11 +19448,8 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct if (type_is_invalid(param_type_value->value.type)) return ira->codegen->invalid_instruction; ZigType *param_type = ir_resolve_type(ira, param_type_value); - if (type_is_invalid(param_type)) - return ira->codegen->invalid_instruction; - if ((err = type_resolve(ira->codegen, param_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; - if (type_requires_comptime(param_type)) { + switch (type_requires_comptime(ira->codegen, param_type)) { + case ReqCompTimeYes: if (!calling_convention_allows_zig_types(fn_type_id.cc)) { ir_add_error(ira, param_type_value, buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", @@ -19443,6 +19459,10 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct param_info->type = param_type; fn_type_id.next_param_index += 1; return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); + case ReqCompTimeInvalid: + return ira->codegen->invalid_instruction; + case ReqCompTimeNo: + break; } if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) { ir_add_error(ira, param_type_value, -- cgit v1.2.3 From 67a39a4c99106714588676db0168fef52e0ecd9c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 26 Nov 2018 20:04:35 -0500 Subject: stage1: better file path handling * better message printed when cache hash fails * better handling of '/' as root source file * os_path_split parses '/' and '/a' correctly closes #1693 closes #1746 --- src/cache_hash.cpp | 6 ++++-- src/codegen.cpp | 11 ++++++++++- src/error.cpp | 1 + src/error.hpp | 1 + src/os.cpp | 10 ++++++++-- 5 files changed, 24 insertions(+), 5 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp index 7a3c08bc27..5e6c3b9a9d 100644 --- a/src/cache_hash.cpp +++ b/src/cache_hash.cpp @@ -352,8 +352,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { // if the mtime matches we can trust the digest OsFile this_file; if ((err = os_file_open_r(chf->path, &this_file))) { + fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err)); os_file_close(ch->manifest_file); - return err; + return ErrorCacheUnavailable; } OsTimeStamp actual_mtime; if ((err = os_file_mtime(this_file, &actual_mtime))) { @@ -392,8 +393,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { for (; file_i < input_file_count; file_i += 1) { CacheHashFile *chf = &ch->files.at(file_i); if ((err = populate_file_hash(ch, chf, nullptr))) { + fprintf(stderr, "Unable to hash %s: %s\n", buf_ptr(chf->path), err_str(err)); os_file_close(ch->manifest_file); - return err; + return ErrorCacheUnavailable; } } return ErrorNone; diff --git a/src/codegen.cpp b/src/codegen.cpp index 37e0424961..1033ed8120 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -129,6 +129,11 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out Buf *src_dir = buf_alloc(); os_path_split(root_src_path, src_dir, src_basename); + if (buf_len(src_basename) == 0) { + fprintf(stderr, "Invalid root source path: %s\n", buf_ptr(root_src_path)); + exit(1); + } + g->root_package = new_package(buf_ptr(src_dir), buf_ptr(src_basename)); g->std_package = new_package(buf_ptr(g->zig_std_dir), "index.zig"); g->root_package->package_table.put(buf_create_from_str("std"), g->std_package); @@ -8178,7 +8183,11 @@ void codegen_build_and_link(CodeGen *g) { os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir); if ((err = check_cache(g, manifest_dir, &digest))) { - fprintf(stderr, "Unable to check cache: %s\n", err_str(err)); + if (err == ErrorCacheUnavailable) { + // message already printed + } else { + fprintf(stderr, "Unable to check cache: %s\n", err_str(err)); + } exit(1); } diff --git a/src/error.cpp b/src/error.cpp index d0575a8494..10186fbde5 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -33,6 +33,7 @@ const char *err_str(Error err) { case ErrorSharingViolation: return "sharing violation"; case ErrorPipeBusy: return "pipe busy"; case ErrorPrimitiveTypeNotFound: return "primitive type not found"; + case ErrorCacheUnavailable: return "cache unavailable"; } return "(invalid error)"; } diff --git a/src/error.hpp b/src/error.hpp index 8b8fa5ce17..b60cb8517e 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -35,6 +35,7 @@ enum Error { ErrorSharingViolation, ErrorPipeBusy, ErrorPrimitiveTypeNotFound, + ErrorCacheUnavailable, }; const char *err_str(Error err); diff --git a/src/os.cpp b/src/os.cpp index 9d16d763ec..f739ee44e7 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -188,14 +188,20 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) { size_t len = buf_len(full_path); if (len != 0) { size_t last_index = len - 1; - if (os_is_sep(buf_ptr(full_path)[last_index])) { + char last_char = buf_ptr(full_path)[last_index]; + if (os_is_sep(last_char)) { + if (last_index == 0) { + if (out_dirname) buf_init_from_mem(out_dirname, &last_char, 1); + if (out_basename) buf_init_from_str(out_basename, ""); + return; + } last_index -= 1; } for (size_t i = last_index;;) { uint8_t c = buf_ptr(full_path)[i]; if (os_is_sep(c)) { if (out_dirname) { - buf_init_from_mem(out_dirname, buf_ptr(full_path), i); + buf_init_from_mem(out_dirname, buf_ptr(full_path), (i == 0) ? 1 : i); } if (out_basename) { buf_init_from_mem(out_basename, buf_ptr(full_path) + i + 1, buf_len(full_path) - (i + 1)); -- cgit v1.2.3