| author | |
| committer | |
| log | 55e54d98c47a0f1fb951f2011c6fc221af68d537 |
| tree | 031f12e33101d46cfd00849f811d1097d3300d3b |
| parent | a26e9fa7238e972301f761db80434fa0205d1016 |
| signature |
6 files changed, 163 insertions(+), 38 deletions(-)
src/all_types.hpp+13-1| ... | @@ -1183,13 +1183,22 @@ struct FnTypeId { | ... | @@ -1183,13 +1183,22 @@ struct FnTypeId { |
| 1183 | uint32_t fn_type_id_hash(FnTypeId*); | 1183 | uint32_t fn_type_id_hash(FnTypeId*); |
| 1184 | bool fn_type_id_eql(FnTypeId *a, FnTypeId *b); | 1184 | bool fn_type_id_eql(FnTypeId *a, FnTypeId *b); |
| 1185 | 1185 | ||
| 1186 | static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX; | ||
| 1187 | static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1; | ||
| 1188 | |||
| 1186 | struct ZigTypePointer { | 1189 | struct ZigTypePointer { |
| 1187 | ZigType *child_type; | 1190 | ZigType *child_type; |
| 1188 | ZigType *slice_parent; | 1191 | ZigType *slice_parent; |
| 1192 | |||
| 1189 | PtrLen ptr_len; | 1193 | PtrLen ptr_len; |
| 1190 | uint32_t explicit_alignment; // 0 means use ABI alignment | 1194 | uint32_t explicit_alignment; // 0 means use ABI alignment |
| 1195 | |||
| 1191 | uint32_t bit_offset_in_host; | 1196 | uint32_t bit_offset_in_host; |
| 1192 | uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned | 1197 | // size of host integer. 0 means no host integer; this field is aligned |
| 1198 | // when vector_index != VECTOR_INDEX_NONE this is the len of the containing vector | ||
| 1199 | uint32_t host_int_bytes; | ||
| 1200 | |||
| 1201 | uint32_t vector_index; // see the VECTOR_INDEX_* constants | ||
| 1193 | bool is_const; | 1202 | bool is_const; |
| 1194 | bool is_volatile; | 1203 | bool is_volatile; |
| 1195 | bool allow_zero; | 1204 | bool allow_zero; |
| ... | @@ -1732,8 +1741,11 @@ struct TypeId { | ... | @@ -1732,8 +1741,11 @@ struct TypeId { |
| 1732 | ZigType *child_type; | 1741 | ZigType *child_type; |
| 1733 | PtrLen ptr_len; | 1742 | PtrLen ptr_len; |
| 1734 | uint32_t alignment; | 1743 | uint32_t alignment; |
| 1744 | |||
| 1735 | uint32_t bit_offset_in_host; | 1745 | uint32_t bit_offset_in_host; |
| 1736 | uint32_t host_int_bytes; | 1746 | uint32_t host_int_bytes; |
| 1747 | |||
| 1748 | uint32_t vector_index; | ||
| 1737 | bool is_const; | 1749 | bool is_const; |
| 1738 | bool is_volatile; | 1750 | bool is_volatile; |
| 1739 | bool allow_zero; | 1751 | bool allow_zero; |
src/analyze.cpp+57-14| ... | @@ -480,9 +480,10 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) { | ... | @@ -480,9 +480,10 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) { |
| 480 | return entry; | 480 | return entry; |
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, | 483 | ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const, |
| 484 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, | 484 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, |
| 485 | uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero) | 485 | uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero, |
| 486 | uint32_t vector_index) | ||
| 486 | { | 487 | { |
| 487 | assert(ptr_len != PtrLenC || allow_zero); | 488 | assert(ptr_len != PtrLenC || allow_zero); |
| 488 | assert(!type_is_invalid(child_type)); | 489 | assert(!type_is_invalid(child_type)); |
| ... | @@ -494,7 +495,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -494,7 +495,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 494 | byte_alignment = 0; | 495 | byte_alignment = 0; |
| 495 | } | 496 | } |
| 496 | 497 | ||
| 497 | if (host_int_bytes != 0) { | 498 | if (host_int_bytes != 0 && vector_index == VECTOR_INDEX_NONE) { |
| 498 | uint32_t child_type_bits = type_size_bits(g, child_type); | 499 | uint32_t child_type_bits = type_size_bits(g, child_type); |
| 499 | if (host_int_bytes * 8 == child_type_bits) { | 500 | if (host_int_bytes * 8 == child_type_bits) { |
| 500 | assert(bit_offset_in_host == 0); | 501 | assert(bit_offset_in_host == 0); |
| ... | @@ -504,7 +505,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -504,7 +505,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 504 | 505 | ||
| 505 | TypeId type_id = {}; | 506 | TypeId type_id = {}; |
| 506 | ZigType **parent_pointer = nullptr; | 507 | ZigType **parent_pointer = nullptr; |
| 507 | if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || allow_zero) { | 508 | if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || |
| 509 | allow_zero || vector_index != VECTOR_INDEX_NONE) | ||
| 510 | { | ||
| 508 | type_id.id = ZigTypeIdPointer; | 511 | type_id.id = ZigTypeIdPointer; |
| 509 | type_id.data.pointer.child_type = child_type; | 512 | type_id.data.pointer.child_type = child_type; |
| 510 | type_id.data.pointer.is_const = is_const; | 513 | type_id.data.pointer.is_const = is_const; |
| ... | @@ -514,6 +517,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -514,6 +517,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 514 | type_id.data.pointer.host_int_bytes = host_int_bytes; | 517 | type_id.data.pointer.host_int_bytes = host_int_bytes; |
| 515 | type_id.data.pointer.ptr_len = ptr_len; | 518 | type_id.data.pointer.ptr_len = ptr_len; |
| 516 | type_id.data.pointer.allow_zero = allow_zero; | 519 | type_id.data.pointer.allow_zero = allow_zero; |
| 520 | type_id.data.pointer.vector_index = vector_index; | ||
| 517 | 521 | ||
| 518 | auto existing_entry = g->type_table.maybe_get(type_id); | 522 | auto existing_entry = g->type_table.maybe_get(type_id); |
| 519 | if (existing_entry) | 523 | if (existing_entry) |
| ... | @@ -540,19 +544,36 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -540,19 +544,36 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 540 | allow_zero_str = allow_zero ? "allowzero " : ""; | 544 | allow_zero_str = allow_zero ? "allowzero " : ""; |
| 541 | } | 545 | } |
| 542 | buf_resize(&entry->name, 0); | 546 | buf_resize(&entry->name, 0); |
| 543 | if (host_int_bytes == 0 && byte_alignment == 0) { | 547 | if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) { |
| 544 | buf_appendf(&entry->name, "%s%s%s%s%s", | 548 | buf_appendf(&entry->name, "%s%s%s%s%s", |
| 545 | star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); | 549 | star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); |
| 546 | } else if (host_int_bytes == 0) { | 550 | } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) { |
| 547 | buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, | 551 | buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, |
| 548 | const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); | 552 | const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); |
| 549 | } else if (byte_alignment == 0) { | 553 | } else if (byte_alignment == 0) { |
| 550 | buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, | 554 | assert(vector_index == VECTOR_INDEX_NONE); |
| 551 | bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str, | 555 | buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", |
| 556 | star_str, | ||
| 557 | bit_offset_in_host, host_int_bytes, vector_index, | ||
| 558 | const_str, volatile_str, allow_zero_str, | ||
| 559 | buf_ptr(&child_type->name)); | ||
| 560 | } else if (vector_index == VECTOR_INDEX_NONE) { | ||
| 561 | buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", | ||
| 562 | star_str, byte_alignment, | ||
| 563 | bit_offset_in_host, host_int_bytes, | ||
| 564 | const_str, volatile_str, allow_zero_str, | ||
| 565 | buf_ptr(&child_type->name)); | ||
| 566 | } else if (vector_index == VECTOR_INDEX_RUNTIME) { | ||
| 567 | buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":?) %s%s%s%s", | ||
| 568 | star_str, byte_alignment, | ||
| 569 | bit_offset_in_host, host_int_bytes, | ||
| 570 | const_str, volatile_str, allow_zero_str, | ||
| 552 | buf_ptr(&child_type->name)); | 571 | buf_ptr(&child_type->name)); |
| 553 | } else { | 572 | } else { |
| 554 | buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, | 573 | buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", |
| 555 | bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str, | 574 | star_str, byte_alignment, |
| 575 | bit_offset_in_host, host_int_bytes, vector_index, | ||
| 576 | const_str, volatile_str, allow_zero_str, | ||
| 556 | buf_ptr(&child_type->name)); | 577 | buf_ptr(&child_type->name)); |
| 557 | } | 578 | } |
| 558 | 579 | ||
| ... | @@ -581,6 +602,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -581,6 +602,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 581 | entry->data.pointer.bit_offset_in_host = bit_offset_in_host; | 602 | entry->data.pointer.bit_offset_in_host = bit_offset_in_host; |
| 582 | entry->data.pointer.host_int_bytes = host_int_bytes; | 603 | entry->data.pointer.host_int_bytes = host_int_bytes; |
| 583 | entry->data.pointer.allow_zero = allow_zero; | 604 | entry->data.pointer.allow_zero = allow_zero; |
| 605 | entry->data.pointer.vector_index = vector_index; | ||
| 584 | 606 | ||
| 585 | if (parent_pointer) { | 607 | if (parent_pointer) { |
| 586 | *parent_pointer = entry; | 608 | *parent_pointer = entry; |
| ... | @@ -590,8 +612,17 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -590,8 +612,17 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 590 | return entry; | 612 | return entry; |
| 591 | } | 613 | } |
| 592 | 614 | ||
| 615 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, | ||
| 616 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, | ||
| 617 | uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero) | ||
| 618 | { | ||
| 619 | return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len, | ||
| 620 | byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE); | ||
| 621 | } | ||
| 622 | |||
| 593 | ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) { | 623 | ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) { |
| 594 | return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false); | 624 | return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false, |
| 625 | VECTOR_INDEX_NONE); | ||
| 595 | } | 626 | } |
| 596 | 627 | ||
| 597 | ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { | 628 | ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { |
| ... | @@ -6910,6 +6941,7 @@ uint32_t type_id_hash(TypeId x) { | ... | @@ -6910,6 +6941,7 @@ uint32_t type_id_hash(TypeId x) { |
| 6910 | (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) + | 6941 | (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) + |
| 6911 | (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) + | 6942 | (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) + |
| 6912 | (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) + | 6943 | (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) + |
| 6944 | (((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) + | ||
| 6913 | (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881); | 6945 | (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881); |
| 6914 | case ZigTypeIdArray: | 6946 | case ZigTypeIdArray: |
| 6915 | return hash_ptr(x.data.array.child_type) + | 6947 | return hash_ptr(x.data.array.child_type) + |
| ... | @@ -6962,6 +6994,7 @@ bool type_id_eql(TypeId a, TypeId b) { | ... | @@ -6962,6 +6994,7 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 6962 | a.data.pointer.allow_zero == b.data.pointer.allow_zero && | 6994 | a.data.pointer.allow_zero == b.data.pointer.allow_zero && |
| 6963 | a.data.pointer.alignment == b.data.pointer.alignment && | 6995 | a.data.pointer.alignment == b.data.pointer.alignment && |
| 6964 | a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host && | 6996 | a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host && |
| 6997 | a.data.pointer.vector_index == b.data.pointer.vector_index && | ||
| 6965 | a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes; | 6998 | a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes; |
| 6966 | case ZigTypeIdArray: | 6999 | case ZigTypeIdArray: |
| 6967 | return a.data.array.child_type == b.data.array.child_type && | 7000 | return a.data.array.child_type == b.data.array.child_type && |
| ... | @@ -8266,11 +8299,21 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus | ... | @@ -8266,11 +8299,21 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus |
| 8266 | 8299 | ||
| 8267 | if (type->data.pointer.is_const || type->data.pointer.is_volatile || | 8300 | if (type->data.pointer.is_const || type->data.pointer.is_volatile || |
| 8268 | type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle || | 8301 | type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle || |
| 8269 | type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero) | 8302 | type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero || |
| 8303 | type->data.pointer.vector_index != VECTOR_INDEX_NONE) | ||
| 8270 | { | 8304 | { |
| 8271 | assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl)); | 8305 | assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl)); |
| 8272 | ZigType *peer_type = get_pointer_to_type_extra(g, elem_type, false, false, | 8306 | ZigType *peer_type; |
| 8273 | PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false); | 8307 | if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) { |
| 8308 | peer_type = get_pointer_to_type_extra2(g, elem_type, false, false, | ||
| 8309 | PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false, | ||
| 8310 | VECTOR_INDEX_NONE); | ||
| 8311 | } else { | ||
| 8312 | uint32_t host_vec_len = type->data.pointer.host_int_bytes; | ||
| 8313 | ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type); | ||
| 8314 | peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false, | ||
| 8315 | PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE); | ||
| 8316 | } | ||
| 8274 | type->llvm_type = get_llvm_type(g, peer_type); | 8317 | type->llvm_type = get_llvm_type(g, peer_type); |
| 8275 | type->llvm_di_type = get_llvm_di_type(g, peer_type); | 8318 | type->llvm_di_type = get_llvm_di_type(g, peer_type); |
| 8276 | assertNoError(type_resolve(g, elem_type, wanted_resolve_status)); | 8319 | assertNoError(type_resolve(g, elem_type, wanted_resolve_status)); |
src/analyze.hpp+6-2| ... | @@ -17,10 +17,14 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, | ... | @@ -17,10 +17,14 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, |
| 17 | ZigType *new_type_table_entry(ZigTypeId id); | 17 | ZigType *new_type_table_entry(ZigTypeId id); |
| 18 | ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn); | 18 | ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn); |
| 19 | ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const); | 19 | ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const); |
| 20 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, | 20 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, |
| 21 | bool is_volatile, PtrLen ptr_len, | 21 | bool is_const, bool is_volatile, PtrLen ptr_len, |
| 22 | uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count, | 22 | uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count, |
| 23 | bool allow_zero); | 23 | bool allow_zero); |
| 24 | ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, | ||
| 25 | bool is_const, bool is_volatile, PtrLen ptr_len, | ||
| 26 | uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count, | ||
| 27 | bool allow_zero, uint32_t vector_index); | ||
| 24 | uint64_t type_size(CodeGen *g, ZigType *type_entry); | 28 | uint64_t type_size(CodeGen *g, ZigType *type_entry); |
| 25 | uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); | 29 | uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); |
| 26 | ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); | 30 | ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); |
src/codegen.cpp+30-13| ... | @@ -838,6 +838,11 @@ static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type | ... | @@ -838,6 +838,11 @@ static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type |
| 838 | } | 838 | } |
| 839 | } | 839 | } |
| 840 | 840 | ||
| 841 | static void ir_assert(bool ok, IrInstruction *source_instruction) { | ||
| 842 | if (ok) return; | ||
| 843 | src_assert(ok, source_instruction->source_node); | ||
| 844 | } | ||
| 845 | |||
| 841 | static bool ir_want_fast_math(CodeGen *g, IrInstruction *instruction) { | 846 | static bool ir_want_fast_math(CodeGen *g, IrInstruction *instruction) { |
| 842 | // TODO memoize | 847 | // TODO memoize |
| 843 | Scope *scope = instruction->scope; | 848 | Scope *scope = instruction->scope; |
| ... | @@ -1695,11 +1700,11 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { | ... | @@ -1695,11 +1700,11 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { |
| 1695 | } | 1700 | } |
| 1696 | if (instruction->spill != nullptr) { | 1701 | if (instruction->spill != nullptr) { |
| 1697 | ZigType *ptr_type = instruction->spill->value.type; | 1702 | ZigType *ptr_type = instruction->spill->value.type; |
| 1698 | src_assert(ptr_type->id == ZigTypeIdPointer, instruction->source_node); | 1703 | ir_assert(ptr_type->id == ZigTypeIdPointer, instruction); |
| 1699 | return get_handle_value(g, ir_llvm_value(g, instruction->spill), | 1704 | return get_handle_value(g, ir_llvm_value(g, instruction->spill), |
| 1700 | ptr_type->data.pointer.child_type, instruction->spill->value.type); | 1705 | ptr_type->data.pointer.child_type, instruction->spill->value.type); |
| 1701 | } | 1706 | } |
| 1702 | src_assert(instruction->value.special != ConstValSpecialRuntime, instruction->source_node); | 1707 | ir_assert(instruction->value.special != ConstValSpecialRuntime, instruction); |
| 1703 | assert(instruction->value.type); | 1708 | assert(instruction->value.type); |
| 1704 | render_const_val(g, &instruction->value, ""); | 1709 | render_const_val(g, &instruction->value, ""); |
| 1705 | // we might have to do some pointer casting here due to the way union | 1710 | // we might have to do some pointer casting here due to the way union |
| ... | @@ -2428,8 +2433,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns | ... | @@ -2428,8 +2433,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns |
| 2428 | return nullptr; | 2433 | return nullptr; |
| 2429 | } | 2434 | } |
| 2430 | assert(g->cur_ret_ptr); | 2435 | assert(g->cur_ret_ptr); |
| 2431 | src_assert(instruction->operand->value.special != ConstValSpecialRuntime, | 2436 | ir_assert(instruction->operand->value.special != ConstValSpecialRuntime, &instruction->base); |
| 2432 | instruction->base.source_node); | ||
| 2433 | LLVMValueRef value = ir_llvm_value(g, instruction->operand); | 2437 | LLVMValueRef value = ir_llvm_value(g, instruction->operand); |
| 2434 | ZigType *return_type = instruction->operand->value.type; | 2438 | ZigType *return_type = instruction->operand->value.type; |
| 2435 | gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value); | 2439 | gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value); |
| ... | @@ -3399,7 +3403,9 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3399,7 +3403,9 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrI |
| 3399 | return nullptr; | 3403 | return nullptr; |
| 3400 | } | 3404 | } |
| 3401 | 3405 | ||
| 3402 | static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtrGen *instruction) { | 3406 | static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, |
| 3407 | IrInstructionLoadPtrGen *instruction) | ||
| 3408 | { | ||
| 3403 | ZigType *child_type = instruction->base.value.type; | 3409 | ZigType *child_type = instruction->base.value.type; |
| 3404 | if (!type_has_bits(child_type)) | 3410 | if (!type_has_bits(child_type)) |
| 3405 | return nullptr; | 3411 | return nullptr; |
| ... | @@ -3409,6 +3415,15 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3409,6 +3415,15 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3409 | assert(ptr_type->id == ZigTypeIdPointer); | 3415 | assert(ptr_type->id == ZigTypeIdPointer); |
| 3410 | 3416 | ||
| 3411 | uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes; | 3417 | uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes; |
| 3418 | |||
| 3419 | ir_assert(ptr_type->data.pointer.vector_index != VECTOR_INDEX_RUNTIME, &instruction->base); | ||
| 3420 | if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) { | ||
| 3421 | LLVMValueRef index_val = LLVMConstInt(LLVMInt32Type(), | ||
| 3422 | ptr_type->data.pointer.vector_index, false); | ||
| 3423 | LLVMValueRef loaded_vector = LLVMBuildLoad(g->builder, ptr, ""); | ||
| 3424 | return LLVMBuildExtractElement(g->builder, loaded_vector, index_val, ""); | ||
| 3425 | } | ||
| 3426 | |||
| 3412 | if (host_int_bytes == 0) | 3427 | if (host_int_bytes == 0) |
| 3413 | return get_handle_value(g, ptr, child_type, ptr_type); | 3428 | return get_handle_value(g, ptr, child_type, ptr_type); |
| 3414 | 3429 | ||
| ... | @@ -3636,7 +3651,7 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable, | ... | @@ -3636,7 +3651,7 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable, |
| 3636 | { | 3651 | { |
| 3637 | if (!type_has_bits(instruction->base.value.type)) | 3652 | if (!type_has_bits(instruction->base.value.type)) |
| 3638 | return nullptr; | 3653 | return nullptr; |
| 3639 | src_assert(g->cur_ret_ptr != nullptr, instruction->base.source_node); | 3654 | ir_assert(g->cur_ret_ptr != nullptr, &instruction->base); |
| 3640 | return g->cur_ret_ptr; | 3655 | return g->cur_ret_ptr; |
| 3641 | } | 3656 | } |
| 3642 | 3657 | ||
| ... | @@ -3729,6 +3744,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3729,6 +3744,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3729 | LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)ptr_index, ""); | 3744 | LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)ptr_index, ""); |
| 3730 | LLVMValueRef ptr = gen_load_untyped(g, ptr_ptr, 0, false, ""); | 3745 | LLVMValueRef ptr = gen_load_untyped(g, ptr_ptr, 0, false, ""); |
| 3731 | return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, ""); | 3746 | return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, ""); |
| 3747 | } else if (array_type->id == ZigTypeIdVector) { | ||
| 3748 | return array_ptr_ptr; | ||
| 3732 | } else { | 3749 | } else { |
| 3733 | zig_unreachable(); | 3750 | zig_unreachable(); |
| 3734 | } | 3751 | } |
| ... | @@ -3917,9 +3934,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3917,9 +3934,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3917 | if (instruction->modifier == CallModifierAsync) { | 3934 | if (instruction->modifier == CallModifierAsync) { |
| 3918 | frame_result_loc = result_loc; | 3935 | frame_result_loc = result_loc; |
| 3919 | } else { | 3936 | } else { |
| 3920 | src_assert(instruction->frame_result_loc != nullptr, instruction->base.source_node); | 3937 | ir_assert(instruction->frame_result_loc != nullptr, &instruction->base); |
| 3921 | frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc); | 3938 | frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc); |
| 3922 | src_assert(instruction->fn_entry != nullptr, instruction->base.source_node); | 3939 | ir_assert(instruction->fn_entry != nullptr, &instruction->base); |
| 3923 | frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, | 3940 | frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, |
| 3924 | LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), ""); | 3941 | LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), ""); |
| 3925 | } | 3942 | } |
| ... | @@ -4271,10 +4288,10 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa | ... | @@ -4271,10 +4288,10 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa |
| 4271 | if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull))) | 4288 | if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull))) |
| 4272 | codegen_report_errors_and_exit(g); | 4289 | codegen_report_errors_and_exit(g); |
| 4273 | 4290 | ||
| 4274 | src_assert(field->gen_index != SIZE_MAX, instruction->base.source_node); | 4291 | ir_assert(field->gen_index != SIZE_MAX, &instruction->base); |
| 4275 | LLVMValueRef field_ptr_val = LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, ""); | 4292 | LLVMValueRef field_ptr_val = LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, ""); |
| 4276 | ZigType *res_type = instruction->base.value.type; | 4293 | ZigType *res_type = instruction->base.value.type; |
| 4277 | src_assert(res_type->id == ZigTypeIdPointer, instruction->base.source_node); | 4294 | ir_assert(res_type->id == ZigTypeIdPointer, &instruction->base); |
| 4278 | if (res_type->data.pointer.host_int_bytes != 0) { | 4295 | if (res_type->data.pointer.host_int_bytes != 0) { |
| 4279 | // We generate packed structs with get_llvm_type_of_n_bytes, which is | 4296 | // We generate packed structs with get_llvm_type_of_n_bytes, which is |
| 4280 | // u8 for 1 byte or [n]u8 for multiple bytes. But the pointer to the type | 4297 | // u8 for 1 byte or [n]u8 for multiple bytes. But the pointer to the type |
| ... | @@ -4684,7 +4701,7 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executabl | ... | @@ -4684,7 +4701,7 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executabl |
| 4684 | 4701 | ||
| 4685 | static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutable *executable, IrInstructionSplatGen *instruction) { | 4702 | static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutable *executable, IrInstructionSplatGen *instruction) { |
| 4686 | ZigType *result_type = instruction->base.value.type; | 4703 | ZigType *result_type = instruction->base.value.type; |
| 4687 | src_assert(result_type->id == ZigTypeIdVector, instruction->base.source_node); | 4704 | ir_assert(result_type->id == ZigTypeIdVector, &instruction->base); |
| 4688 | uint32_t len = result_type->data.vector.len; | 4705 | uint32_t len = result_type->data.vector.len; |
| 4689 | LLVMTypeRef op_llvm_type = LLVMVectorType(get_llvm_type(g, instruction->scalar->value.type), 1); | 4706 | LLVMTypeRef op_llvm_type = LLVMVectorType(get_llvm_type(g, instruction->scalar->value.type), 1); |
| 4690 | LLVMTypeRef mask_llvm_type = LLVMVectorType(LLVMInt32Type(), len); | 4707 | LLVMTypeRef mask_llvm_type = LLVMVectorType(LLVMInt32Type(), len); |
| ... | @@ -5039,8 +5056,8 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn | ... | @@ -5039,8 +5056,8 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn |
| 5039 | } | 5056 | } |
| 5040 | 5057 | ||
| 5041 | LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); | 5058 | LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); |
| 5042 | src_assert(result_loc != nullptr, instruction->base.source_node); | 5059 | ir_assert(result_loc != nullptr, &instruction->base); |
| 5043 | src_assert(type_has_bits(child_type), instruction->base.source_node); | 5060 | ir_assert(type_has_bits(child_type), &instruction->base); |
| 5044 | 5061 | ||
| 5045 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); | 5062 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); |
| 5046 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, ""); | 5063 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, ""); |
src/ir.cpp+40-8| ... | @@ -12908,18 +12908,18 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc | ... | @@ -12908,18 +12908,18 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 12908 | ResultLoc *result_loc) | 12908 | ResultLoc *result_loc) |
| 12909 | { | 12909 | { |
| 12910 | Error err; | 12910 | Error err; |
| 12911 | ZigType *type_entry = ptr->value.type; | 12911 | ZigType *ptr_type = ptr->value.type; |
| 12912 | if (type_is_invalid(type_entry)) | 12912 | if (type_is_invalid(ptr_type)) |
| 12913 | return ira->codegen->invalid_instruction; | 12913 | return ira->codegen->invalid_instruction; |
| 12914 | 12914 | ||
| 12915 | if (type_entry->id != ZigTypeIdPointer) { | 12915 | if (ptr_type->id != ZigTypeIdPointer) { |
| 12916 | ir_add_error_node(ira, source_instruction->source_node, | 12916 | ir_add_error_node(ira, source_instruction->source_node, |
| 12917 | buf_sprintf("attempt to dereference non-pointer type '%s'", | 12917 | buf_sprintf("attempt to dereference non-pointer type '%s'", |
| 12918 | buf_ptr(&type_entry->name))); | 12918 | buf_ptr(&ptr_type->name))); |
| 12919 | return ira->codegen->invalid_instruction; | 12919 | return ira->codegen->invalid_instruction; |
| 12920 | } | 12920 | } |
| 12921 | 12921 | ||
| 12922 | ZigType *child_type = type_entry->data.pointer.child_type; | 12922 | ZigType *child_type = ptr_type->data.pointer.child_type; |
| 12923 | // if the child type has one possible value, the deref is comptime | 12923 | // if the child type has one possible value, the deref is comptime |
| 12924 | switch (type_has_one_possible_value(ira->codegen, child_type)) { | 12924 | switch (type_has_one_possible_value(ira->codegen, child_type)) { |
| 12925 | case OnePossibleValueInvalid: | 12925 | case OnePossibleValueInvalid: |
| ... | @@ -12949,14 +12949,29 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc | ... | @@ -12949,14 +12949,29 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 12949 | } | 12949 | } |
| 12950 | } | 12950 | } |
| 12951 | } | 12951 | } |
| 12952 | |||
| 12952 | // if the instruction is a const ref instruction we can skip it | 12953 | // if the instruction is a const ref instruction we can skip it |
| 12953 | if (ptr->id == IrInstructionIdRef) { | 12954 | if (ptr->id == IrInstructionIdRef) { |
| 12954 | IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr); | 12955 | IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr); |
| 12955 | return ref_inst->value; | 12956 | return ref_inst->value; |
| 12956 | } | 12957 | } |
| 12957 | 12958 | ||
| 12959 | // If the instruction is a element pointer instruction to a vector, we emit | ||
| 12960 | // vector element extract instruction rather than load pointer. If the | ||
| 12961 | // pointer type has non-VECTOR_INDEX_RUNTIME value, it would have been | ||
| 12962 | // possible to implement this in the codegen for IrInstructionLoadPtrGen. | ||
| 12963 | // However if it has VECTOR_INDEX_RUNTIME then we must emit a compile error | ||
| 12964 | // if the vector index cannot be determined right here, right now, because | ||
| 12965 | // the type information does not contain enough information to actually | ||
| 12966 | // perform a dereference. | ||
| 12967 | if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) { | ||
| 12968 | ir_add_error(ira, ptr, | ||
| 12969 | buf_sprintf("unable to determine element index in order to dereference vector pointer")); | ||
| 12970 | return ira->codegen->invalid_instruction; | ||
| 12971 | } | ||
| 12972 | |||
| 12958 | IrInstruction *result_loc_inst; | 12973 | IrInstruction *result_loc_inst; |
| 12959 | if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) { | 12974 | if (ptr_type->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) { |
| 12960 | if (result_loc == nullptr) result_loc = no_result_loc(); | 12975 | if (result_loc == nullptr) result_loc = no_result_loc(); |
| 12961 | result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, | 12976 | result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, |
| 12962 | true, false, true); | 12977 | true, false, true); |
| ... | @@ -17488,6 +17503,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -17488,6 +17503,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 17488 | return ir_get_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val, | 17503 | return ir_get_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val, |
| 17489 | ira->codegen->builtin_types.entry_void, ConstPtrMutComptimeConst, is_const, is_volatile, 0); | 17504 | ira->codegen->builtin_types.entry_void, ConstPtrMutComptimeConst, is_const, is_volatile, 0); |
| 17490 | } | 17505 | } |
| 17506 | } else if (array_type->id == ZigTypeIdVector) { | ||
| 17507 | // This depends on whether the element index is comptime, so it is computed later. | ||
| 17508 | return_type = nullptr; | ||
| 17491 | } else { | 17509 | } else { |
| 17492 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, | 17510 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, |
| 17493 | buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name))); | 17511 | buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name))); |
| ... | @@ -17512,8 +17530,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -17512,8 +17530,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 17512 | } | 17530 | } |
| 17513 | safety_check_on = false; | 17531 | safety_check_on = false; |
| 17514 | } | 17532 | } |
| 17515 | 17533 | if (array_type->id == ZigTypeIdVector) { | |
| 17516 | if (return_type->data.pointer.explicit_alignment != 0) { | 17534 | ZigType *elem_type = array_type->data.vector.elem_type; |
| 17535 | uint32_t host_vec_len = array_type->data.vector.len; | ||
| 17536 | return_type = get_pointer_to_type_extra2(ira->codegen, elem_type, | ||
| 17537 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | ||
| 17538 | elem_ptr_instruction->ptr_len, | ||
| 17539 | get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index); | ||
| 17540 | } else if (return_type->data.pointer.explicit_alignment != 0) { | ||
| 17517 | // figure out the largest alignment possible | 17541 | // figure out the largest alignment possible |
| 17518 | 17542 | ||
| 17519 | if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown))) | 17543 | if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown))) |
| ... | @@ -17742,6 +17766,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -17742,6 +17766,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 17742 | } | 17766 | } |
| 17743 | } | 17767 | } |
| 17744 | } | 17768 | } |
| 17769 | } else if (array_type->id == ZigTypeIdVector) { | ||
| 17770 | // runtime known element index | ||
| 17771 | ZigType *elem_type = array_type->data.vector.elem_type; | ||
| 17772 | uint32_t host_vec_len = array_type->data.vector.len; | ||
| 17773 | return_type = get_pointer_to_type_extra2(ira->codegen, elem_type, | ||
| 17774 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | ||
| 17775 | elem_ptr_instruction->ptr_len, | ||
| 17776 | get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME); | ||
| 17745 | } else { | 17777 | } else { |
| 17746 | // runtime known element index | 17778 | // runtime known element index |
| 17747 | switch (type_requires_comptime(ira->codegen, return_type)) { | 17779 | switch (type_requires_comptime(ira->codegen, return_type)) { |
test/stage1/behavior/vector.zig+17| ... | @@ -159,3 +159,20 @@ test "vector @splat" { | ... | @@ -159,3 +159,20 @@ test "vector @splat" { |
| 159 | S.doTheTest(); | 159 | S.doTheTest(); |
| 160 | comptime S.doTheTest(); | 160 | comptime S.doTheTest(); |
| 161 | } | 161 | } |
| 162 | |||
| 163 | test "load vector elements via comptime index" { | ||
| 164 | const S = struct { | ||
| 165 | fn doTheTest() void { | ||
| 166 | var v: @Vector(4, i32) = [_]i32{ 1, 2, 3, undefined }; | ||
| 167 | expect(v[0] == 1); | ||
| 168 | expect(v[1] == 2); | ||
| 169 | expect(loadv(&v[2]) == 3); | ||
| 170 | } | ||
| 171 | fn loadv(ptr: var) i32 { | ||
| 172 | return ptr.*; | ||
| 173 | } | ||
| 174 | }; | ||
| 175 | |||
| 176 | S.doTheTest(); | ||
| 177 | //comptime S.doTheTest(); | ||
| 178 | } |