From 5f28a9d23851d94edc2b24e549b7c5abbbf23f68 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 25 Oct 2017 23:10:41 -0400 Subject: cleaner verbose flags and zig build prints failed command --- src/analyze.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 292943a6e6..45efa205e3 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2982,7 +2982,7 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ return; } - if (g->verbose) { + if (g->verbose_ir) { fprintf(stderr, "{ // (analyzed)\n"); ir_print(g, stderr, &fn_table_entry->analyzed_executable, 4); fprintf(stderr, "}\n"); @@ -3015,7 +3015,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { fn_table_entry->anal_state = FnAnalStateInvalid; return; } - if (g->verbose) { + if (g->verbose_ir) { fprintf(stderr, "\n"); ast_render(g, stderr, fn_table_entry->body_node, 4); fprintf(stderr, "\n{ // (IR)\n"); @@ -3115,7 +3115,7 @@ void preview_use_decl(CodeGen *g, AstNode *node) { } ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code) { - if (g->verbose) { + if (g->verbose_tokenize) { fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(abs_full_path)); fprintf(stderr, "----------------\n"); fprintf(stderr, "%s\n", buf_ptr(source_code)); @@ -3135,7 +3135,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a exit(1); } - if (g->verbose) { + if (g->verbose_tokenize) { print_tokens(source_code, tokenization.tokens); fprintf(stderr, "\nAST:\n"); @@ -3150,7 +3150,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color); assert(import_entry->root); - if (g->verbose) { + if (g->verbose_ast) { ast_print(stderr, import_entry->root, 0); } -- cgit v1.2.3 From 300c83d8930d15d4bc4e34fe11e3b6bf3130ecc4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 25 Oct 2017 23:18:18 -0400 Subject: fix crash on field access of opaque type --- src/analyze.cpp | 2 +- test/compile_errors.zig | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 45efa205e3..b6bd9c8124 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2804,7 +2804,6 @@ static bool is_container(TypeTableEntry *type_entry) { switch (type_entry->id) { case TypeTableEntryIdInvalid: case TypeTableEntryIdVar: - case TypeTableEntryIdOpaque: zig_unreachable(); case TypeTableEntryIdStruct: case TypeTableEntryIdEnum: @@ -2831,6 +2830,7 @@ static bool is_container(TypeTableEntry *type_entry) { case TypeTableEntryIdBoundFn: case TypeTableEntryIdEnumTag: case TypeTableEntryIdArgTuple: + case TypeTableEntryIdOpaque: return false; } zig_unreachable(); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index efab136d7e..f3201aea9a 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2238,4 +2238,18 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\} , ".tmp_source.zig:37:16: error: cannot store runtime value in compile time variable"); + + cases.add("field access of opaque type", + \\const MyType = @OpaqueType(); + \\ + \\export fn entry() -> bool { + \\ var x: i32 = 1; + \\ return bar(@ptrCast(&MyType, &x)); + \\} + \\ + \\fn bar(x: &MyType) -> bool { + \\ return x.blah; + \\} + , + ".tmp_source.zig:9:13: error: type '&MyType' does not support field access"); } -- cgit v1.2.3 From c7053bea204f87fe1c8b28ec97b27003a24dcafc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 26 Oct 2017 00:32:30 -0400 Subject: better output when @cImport generates invalid zig --- src/analyze.cpp | 31 +++++++++++++++++++++++++------ src/errmsg.cpp | 1 + 2 files changed, 26 insertions(+), 6 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index b6bd9c8124..e6ccf82dfe 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -27,9 +27,17 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type); static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type); ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { - // if this assert fails, then parsec generated code that - // failed semantic analysis, which isn't supposed to happen - assert(!node->owner->c_import_node); + if (node->owner->c_import_node != nullptr) { + // if this happens, then parsec generated code that + // failed semantic analysis, which isn't supposed to happen + ErrorMsg *err = add_node_error(g, node->owner->c_import_node, + buf_sprintf("compiler bug: @cImport generated invalid zig code")); + + add_error_note(g, err, node, msg); + + g->errors.append(err); + return err; + } ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column, node->owner->source_code, node->owner->line_offsets, msg); @@ -39,9 +47,20 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { } ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) { - // if this assert fails, then parsec generated code that - // failed semantic analysis, which isn't supposed to happen - assert(!node->owner->c_import_node); + if (node->owner->c_import_node != nullptr) { + // if this happens, then parsec generated code that + // failed semantic analysis, which isn't supposed to happen + + Buf *note_path = buf_create_from_str("?.c"); + Buf *note_source = buf_create_from_str("TODO: remember C source location to display here "); + ZigList note_line_offsets = {0}; + note_line_offsets.append(0); + ErrorMsg *note = err_msg_create_with_line(note_path, 0, 0, + note_source, ¬e_line_offsets, msg); + + err_msg_add_note(parent_msg, note); + return note; + } ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column, node->owner->source_code, node->owner->line_offsets, msg); diff --git a/src/errmsg.cpp b/src/errmsg.cpp index bef4d7548d..01c3ee8429 100644 --- a/src/errmsg.cpp +++ b/src/errmsg.cpp @@ -123,6 +123,7 @@ ErrorMsg *err_msg_create_with_line(Buf *path, size_t line, size_t column, size_t end_line = line + 1; size_t line_end_offset = (end_line >= line_offsets->length) ? buf_len(source) : line_offsets->at(line + 1); size_t len = (line_end_offset + 1 > line_start_offset) ? (line_end_offset - line_start_offset - 1) : 0; + if (len == SIZE_MAX) len = 0; buf_init_from_mem(&err_msg->line_buf, buf_ptr(source) + line_start_offset, len); -- cgit v1.2.3 From f1072d0d9fba397b3920015fd854414868e6ea17 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 24 Oct 2017 02:14:55 -0400 Subject: use llvm named structs for const values when possible normally we want to use llvm types for constants. but union constants (which are found inside enums) when they are initialized with the non-most-aligned-member must be unnamed structs. these bubble up to all aggregate types. if a constant of an aggregate type contains, recursively, a union constant with a non-most-aligned-member initialized, the aggregate typed constant must be unnamed too. this fixes some of the asserts that were coming in from llvm master branch. --- src/all_types.hpp | 3 ++ src/analyze.cpp | 7 ++--- src/codegen.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 75 insertions(+), 20 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/all_types.hpp b/src/all_types.hpp index b8966e764a..9f59ae2aac 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1008,6 +1008,9 @@ struct TypeTableEntryEnum { size_t gen_union_index; size_t gen_tag_index; + + uint32_t union_size_bytes; + TypeTableEntry *most_aligned_union_member; }; struct TypeTableEntryEnumTag { diff --git a/src/analyze.cpp b/src/analyze.cpp index e6ccf82dfe..89ce5df6b4 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1363,6 +1363,8 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { // unset temporary flag enum_type->data.enumeration.embedded_in_current = false; enum_type->data.enumeration.complete = true; + enum_type->data.enumeration.union_size_bytes = biggest_size_in_bits / 8; + enum_type->data.enumeration.most_aligned_union_member = most_aligned_union_member; if (!enum_type->data.enumeration.is_invalid) { TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count); @@ -1384,10 +1386,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { }; union_type_ref = LLVMStructType(union_element_types, 2, false); } else { - LLVMTypeRef union_element_types[] = { - most_aligned_union_member->type_ref, - }; - union_type_ref = LLVMStructType(union_element_types, 1, false); + union_type_ref = most_aligned_union_member->type_ref; } enum_type->data.enumeration.union_type_ref = union_type_ref; diff --git a/src/codegen.cpp b/src/codegen.cpp index 68fd4159bd..0a78ef0740 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3665,6 +3665,12 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con zig_unreachable(); } +// We have this because union constants can't be represented by the official union type, +// and this property bubbles up in whatever aggregate type contains a union constant +static bool is_llvm_value_unnamed_type(TypeTableEntry *type_entry, LLVMValueRef val) { + return LLVMTypeOf(val) != type_entry->type_ref; +} + static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { TypeTableEntry *type_entry = const_val->type; assert(!type_entry->zero_bits); @@ -3726,24 +3732,34 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { } else { LLVMValueRef child_val; LLVMValueRef maybe_val; + bool make_unnamed_struct; if (const_val->data.x_maybe) { child_val = gen_const_val(g, const_val->data.x_maybe); maybe_val = LLVMConstAllOnes(LLVMInt1Type()); + + make_unnamed_struct = is_llvm_value_unnamed_type(const_val->type, child_val); } else { - child_val = LLVMConstNull(child_type->type_ref); + child_val = LLVMGetUndef(child_type->type_ref); maybe_val = LLVMConstNull(LLVMInt1Type()); + + make_unnamed_struct = false; } LLVMValueRef fields[] = { child_val, maybe_val, }; - return LLVMConstStruct(fields, 2, false); + if (make_unnamed_struct) { + return LLVMConstStruct(fields, 2, false); + } else { + return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); + } } } case TypeTableEntryIdStruct: { LLVMValueRef *fields = allocate(type_entry->data.structure.gen_field_count); size_t src_field_count = type_entry->data.structure.src_field_count; + bool make_unnamed_struct = false; if (type_entry->data.structure.layout == ContainerLayoutPacked) { size_t src_field_index = 0; while (src_field_index < src_field_count) { @@ -3761,8 +3777,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { } if (src_field_index + 1 == src_field_index_end) { - fields[type_struct_field->gen_index] = - gen_const_val(g, &const_val->data.x_struct.fields[src_field_index]); + ConstExprValue *field_val = &const_val->data.x_struct.fields[src_field_index]; + LLVMValueRef val = gen_const_val(g, field_val); + fields[type_struct_field->gen_index] = val; + make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(field_val->type, val); } else { LLVMTypeRef big_int_type_ref = LLVMStructGetTypeAtIndex(type_entry->type_ref, (unsigned)type_struct_field->gen_index); @@ -3790,11 +3808,18 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { if (type_struct_field->gen_index == SIZE_MAX) { continue; } - fields[type_struct_field->gen_index] = gen_const_val(g, &const_val->data.x_struct.fields[i]); + ConstExprValue *field_val = &const_val->data.x_struct.fields[i]; + LLVMValueRef val = gen_const_val(g, field_val); + fields[type_struct_field->gen_index] = val; + make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(field_val->type, val); } } - return LLVMConstStruct(fields, type_entry->data.structure.gen_field_count, - type_entry->data.structure.layout == ContainerLayoutPacked); + if (make_unnamed_struct) { + return LLVMConstStruct(fields, type_entry->data.structure.gen_field_count, + type_entry->data.structure.layout == ContainerLayoutPacked); + } else { + return LLVMConstNamedStruct(type_entry->type_ref, fields, type_entry->data.structure.gen_field_count); + } } case TypeTableEntryIdUnion: { @@ -3808,11 +3833,19 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { } LLVMValueRef *values = allocate(len); + LLVMTypeRef element_type_ref = type_entry->data.array.child_type->type_ref; + bool make_unnamed_struct = false; for (uint64_t i = 0; i < len; i += 1) { ConstExprValue *elem_value = &const_val->data.x_array.s_none.elements[i]; - values[i] = gen_const_val(g, elem_value); + LLVMValueRef val = gen_const_val(g, elem_value); + values[i] = val; + make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(elem_value->type, val); + } + if (make_unnamed_struct) { + return LLVMConstStruct(values, len, true); + } else { + return LLVMConstArray(element_type_ref, values, (unsigned)len); } - return LLVMConstArray(LLVMTypeOf(values[0]), values, (unsigned)len); } case TypeTableEntryIdEnum: { @@ -3825,14 +3858,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag]; assert(enum_field->value == const_val->data.x_enum.tag); LLVMValueRef union_value; + + bool make_unnamed_struct; + if (type_has_bits(enum_field->type_entry)) { - uint64_t union_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, - union_type_ref); uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, enum_field->type_entry->type_ref); - uint64_t pad_bytes = union_type_bytes - field_type_bytes; + uint64_t pad_bytes = type_entry->data.enumeration.union_size_bytes - field_type_bytes; + + ConstExprValue *payload_value = const_val->data.x_enum.payload; + LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value); + + make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) || + payload_value->type != type_entry->data.enumeration.most_aligned_union_member; - LLVMValueRef correctly_typed_value = gen_const_val(g, const_val->data.x_enum.payload); if (pad_bytes == 0) { union_value = correctly_typed_value; } else { @@ -3843,12 +3882,18 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { union_value = LLVMConstStruct(fields, 2, false); } } else { + make_unnamed_struct = false; union_value = LLVMGetUndef(union_type_ref); } LLVMValueRef fields[2]; fields[type_entry->data.enumeration.gen_tag_index] = tag_value; fields[type_entry->data.enumeration.gen_union_index] = union_value; - return LLVMConstStruct(fields, 2, false); + + if (make_unnamed_struct) { + return LLVMConstStruct(fields, 2, false); + } else { + return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); + } } } case TypeTableEntryIdFn: @@ -3932,18 +3977,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { } else { LLVMValueRef err_tag_value; LLVMValueRef err_payload_value; + 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); + make_unnamed_struct = false; } else { err_tag_value = LLVMConstNull(g->err_tag_type->type_ref); - err_payload_value = gen_const_val(g, const_val->data.x_err_union.payload); + ConstExprValue *payload_val = const_val->data.x_err_union.payload; + err_payload_value = gen_const_val(g, payload_val); + make_unnamed_struct = is_llvm_value_unnamed_type(payload_val->type, err_payload_value); } LLVMValueRef fields[] = { err_tag_value, err_payload_value, }; - return LLVMConstStruct(fields, 2, false); + if (make_unnamed_struct) { + return LLVMConstStruct(fields, 2, false); + } else { + return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); + } } } case TypeTableEntryIdVoid: -- cgit v1.2.3