| author | |
| committer | |
| log | d794549985fc9a3fd6d6b1620be15d290f6a759f |
| tree | 82e39db15fd95ecb7041ec7fea74857689d07982 |
| parent | cf5108f222107ed242d2dc2c37d76758157da542 |
6 files changed, 146 insertions(+), 57 deletions(-)
src/analyze.cpp+30-36| ... | @@ -163,6 +163,7 @@ static TypeTableEntry *new_container_type_entry(TypeTableEntryId id, AstNode *so | ... | @@ -163,6 +163,7 @@ static TypeTableEntry *new_container_type_entry(TypeTableEntryId id, AstNode *so |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | 165 | ||
| 166 | // TODO no reason to limit to 8/16/32/64 | ||
| 166 | static size_t bits_needed_for_unsigned(uint64_t x) { | 167 | static size_t bits_needed_for_unsigned(uint64_t x) { |
| 167 | if (x <= UINT8_MAX) { | 168 | if (x <= UINT8_MAX) { |
| 168 | return 8; | 169 | return 8; |
| ... | @@ -262,6 +263,14 @@ uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry) { | ... | @@ -262,6 +263,14 @@ uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry) { |
| 262 | if (canon_type->id == TypeTableEntryIdStruct && canon_type->data.structure.layout == ContainerLayoutPacked) { | 263 | if (canon_type->id == TypeTableEntryIdStruct && canon_type->data.structure.layout == ContainerLayoutPacked) { |
| 263 | uint64_t size_in_bits = type_size_bits(g, type_entry); | 264 | uint64_t size_in_bits = type_size_bits(g, type_entry); |
| 264 | return (size_in_bits + 7) / 8; | 265 | return (size_in_bits + 7) / 8; |
| 266 | } else if (canon_type->id == TypeTableEntryIdArray) { | ||
| 267 | TypeTableEntry *canon_child_type = get_underlying_type(canon_type->data.array.child_type); | ||
| 268 | if (canon_child_type->id == TypeTableEntryIdStruct && | ||
| 269 | canon_child_type->data.structure.layout == ContainerLayoutPacked) | ||
| 270 | { | ||
| 271 | uint64_t size_in_bits = type_size_bits(g, type_entry); | ||
| 272 | return (size_in_bits + 7) / 8; | ||
| 273 | } | ||
| 265 | } | 274 | } |
| 266 | 275 | ||
| 267 | return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref); | 276 | return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref); |
| ... | @@ -280,6 +289,13 @@ uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry) { | ... | @@ -280,6 +289,13 @@ uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry) { |
| 280 | result += type_size_bits(g, canon_type->data.structure.fields[i].type_entry); | 289 | result += type_size_bits(g, canon_type->data.structure.fields[i].type_entry); |
| 281 | } | 290 | } |
| 282 | return result; | 291 | return result; |
| 292 | } else if (canon_type->id == TypeTableEntryIdArray) { | ||
| 293 | TypeTableEntry *canon_child_type = get_underlying_type(canon_type->data.array.child_type); | ||
| 294 | if (canon_child_type->id == TypeTableEntryIdStruct && | ||
| 295 | canon_child_type->data.structure.layout == ContainerLayoutPacked) | ||
| 296 | { | ||
| 297 | return canon_type->data.array.len * type_size_bits(g, canon_child_type); | ||
| 298 | } | ||
| 283 | } | 299 | } |
| 284 | 300 | ||
| 285 | return LLVMSizeOfTypeInBits(g->target_data_ref, canon_type->type_ref); | 301 | return LLVMSizeOfTypeInBits(g->target_data_ref, canon_type->type_ref); |
| ... | @@ -537,14 +553,6 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t | ... | @@ -537,14 +553,6 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t |
| 537 | 553 | ||
| 538 | ensure_complete_type(g, child_type); | 554 | ensure_complete_type(g, child_type); |
| 539 | 555 | ||
| 540 | TypeTableEntry *canon_child_type = get_underlying_type(child_type); | ||
| 541 | if (canon_child_type->id == TypeTableEntryIdStruct && | ||
| 542 | canon_child_type->data.structure.layout == ContainerLayoutPacked && | ||
| 543 | type_size_bits(g, canon_child_type) != 8 * type_size(g, canon_child_type)) | ||
| 544 | { | ||
| 545 | zig_panic("TODO array of packed struct with unaligned size"); | ||
| 546 | } | ||
| 547 | |||
| 548 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray); | 556 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray); |
| 549 | entry->zero_bits = (array_size == 0) || child_type->zero_bits; | 557 | entry->zero_bits = (array_size == 0) || child_type->zero_bits; |
| 550 | 558 | ||
| ... | @@ -1459,15 +1467,16 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { | ... | @@ -1459,15 +1467,16 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 1459 | type_struct_field->packed_bits_offset = packed_bits_offset - first_packed_bits_offset_misalign; | 1467 | type_struct_field->packed_bits_offset = packed_bits_offset - first_packed_bits_offset_misalign; |
| 1460 | type_struct_field->unaligned_bit_count = field_size_in_bits; | 1468 | type_struct_field->unaligned_bit_count = field_size_in_bits; |
| 1461 | 1469 | ||
| 1462 | if (next_packed_bits_offset % 8 == 0) { | 1470 | size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign; |
| 1463 | // next field recovers byte alignment | 1471 | LLVMTypeRef int_type_ref = LLVMIntType(full_bit_count); |
| 1464 | size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign; | 1472 | if (8 * LLVMStoreSizeOfType(g->target_data_ref, int_type_ref) == full_bit_count) { |
| 1465 | element_types[gen_field_index] = LLVMIntType(full_bit_count); | 1473 | // next field recovers store alignment |
| 1474 | element_types[gen_field_index] = int_type_ref; | ||
| 1466 | gen_field_index += 1; | 1475 | gen_field_index += 1; |
| 1467 | 1476 | ||
| 1468 | first_packed_bits_offset_misalign = SIZE_MAX; | 1477 | first_packed_bits_offset_misalign = SIZE_MAX; |
| 1469 | } | 1478 | } |
| 1470 | } else if (next_packed_bits_offset % 8 != 0) { | 1479 | } else if (8 * LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref) != field_size_in_bits) { |
| 1471 | first_packed_bits_offset_misalign = packed_bits_offset; | 1480 | first_packed_bits_offset_misalign = packed_bits_offset; |
| 1472 | type_struct_field->packed_bits_offset = 0; | 1481 | type_struct_field->packed_bits_offset = 0; |
| 1473 | type_struct_field->unaligned_bit_count = field_size_in_bits; | 1482 | type_struct_field->unaligned_bit_count = field_size_in_bits; |
| ... | @@ -1489,7 +1498,9 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { | ... | @@ -1489,7 +1498,9 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 1489 | } | 1498 | } |
| 1490 | if (first_packed_bits_offset_misalign != SIZE_MAX) { | 1499 | if (first_packed_bits_offset_misalign != SIZE_MAX) { |
| 1491 | size_t full_bit_count = packed_bits_offset - first_packed_bits_offset_misalign; | 1500 | size_t full_bit_count = packed_bits_offset - first_packed_bits_offset_misalign; |
| 1492 | element_types[gen_field_index] = LLVMIntType(full_bit_count); | 1501 | LLVMTypeRef int_type_ref = LLVMIntType(full_bit_count); |
| 1502 | size_t store_bit_count = 8 * LLVMStoreSizeOfType(g->target_data_ref, int_type_ref); | ||
| 1503 | element_types[gen_field_index] = LLVMIntType(store_bit_count); | ||
| 1493 | gen_field_index += 1; | 1504 | gen_field_index += 1; |
| 1494 | } | 1505 | } |
| 1495 | 1506 | ||
| ... | @@ -3620,33 +3631,22 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -3620,33 +3631,22 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 3620 | zig_unreachable(); | 3631 | zig_unreachable(); |
| 3621 | } | 3632 | } |
| 3622 | 3633 | ||
| 3623 | static uint64_t max_unsigned_val(TypeTableEntry *type_entry) { | 3634 | uint64_t max_unsigned_val(TypeTableEntry *type_entry) { |
| 3624 | assert(type_entry->id == TypeTableEntryIdInt); | 3635 | assert(type_entry->id == TypeTableEntryIdInt); |
| 3625 | if (type_entry->data.integral.bit_count == 64) { | 3636 | if (type_entry->data.integral.bit_count == 64) { |
| 3626 | return UINT64_MAX; | 3637 | return UINT64_MAX; |
| 3627 | } else if (type_entry->data.integral.bit_count == 32) { | ||
| 3628 | return UINT32_MAX; | ||
| 3629 | } else if (type_entry->data.integral.bit_count == 16) { | ||
| 3630 | return UINT16_MAX; | ||
| 3631 | } else if (type_entry->data.integral.bit_count == 8) { | ||
| 3632 | return UINT8_MAX; | ||
| 3633 | } else { | 3638 | } else { |
| 3634 | zig_unreachable(); | 3639 | return (((uint64_t)1) << type_entry->data.integral.bit_count) - 1; |
| 3635 | } | 3640 | } |
| 3636 | } | 3641 | } |
| 3637 | 3642 | ||
| 3638 | static int64_t max_signed_val(TypeTableEntry *type_entry) { | 3643 | static int64_t max_signed_val(TypeTableEntry *type_entry) { |
| 3639 | assert(type_entry->id == TypeTableEntryIdInt); | 3644 | assert(type_entry->id == TypeTableEntryIdInt); |
| 3645 | |||
| 3640 | if (type_entry->data.integral.bit_count == 64) { | 3646 | if (type_entry->data.integral.bit_count == 64) { |
| 3641 | return INT64_MAX; | 3647 | return INT64_MAX; |
| 3642 | } else if (type_entry->data.integral.bit_count == 32) { | ||
| 3643 | return INT32_MAX; | ||
| 3644 | } else if (type_entry->data.integral.bit_count == 16) { | ||
| 3645 | return INT16_MAX; | ||
| 3646 | } else if (type_entry->data.integral.bit_count == 8) { | ||
| 3647 | return INT8_MAX; | ||
| 3648 | } else { | 3648 | } else { |
| 3649 | zig_unreachable(); | 3649 | return (((uint64_t)1) << (type_entry->data.integral.bit_count - 1)) - 1; |
| 3650 | } | 3650 | } |
| 3651 | } | 3651 | } |
| 3652 | 3652 | ||
| ... | @@ -3654,14 +3654,8 @@ int64_t min_signed_val(TypeTableEntry *type_entry) { | ... | @@ -3654,14 +3654,8 @@ int64_t min_signed_val(TypeTableEntry *type_entry) { |
| 3654 | assert(type_entry->id == TypeTableEntryIdInt); | 3654 | assert(type_entry->id == TypeTableEntryIdInt); |
| 3655 | if (type_entry->data.integral.bit_count == 64) { | 3655 | if (type_entry->data.integral.bit_count == 64) { |
| 3656 | return INT64_MIN; | 3656 | return INT64_MIN; |
| 3657 | } else if (type_entry->data.integral.bit_count == 32) { | ||
| 3658 | return INT32_MIN; | ||
| 3659 | } else if (type_entry->data.integral.bit_count == 16) { | ||
| 3660 | return INT16_MIN; | ||
| 3661 | } else if (type_entry->data.integral.bit_count == 8) { | ||
| 3662 | return INT8_MIN; | ||
| 3663 | } else { | 3657 | } else { |
| 3664 | zig_unreachable(); | 3658 | return -((int64_t)(((uint64_t)1) << (type_entry->data.integral.bit_count - 1))); |
| 3665 | } | 3659 | } |
| 3666 | } | 3660 | } |
| 3667 | 3661 |
src/analyze.hpp+1| ... | @@ -84,6 +84,7 @@ bool ir_get_var_is_comptime(VariableTableEntry *var); | ... | @@ -84,6 +84,7 @@ bool ir_get_var_is_comptime(VariableTableEntry *var); |
| 84 | bool const_values_equal(ConstExprValue *a, ConstExprValue *b); | 84 | bool const_values_equal(ConstExprValue *a, ConstExprValue *b); |
| 85 | void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max); | 85 | void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max); |
| 86 | int64_t min_signed_val(TypeTableEntry *type_entry); | 86 | int64_t min_signed_val(TypeTableEntry *type_entry); |
| 87 | uint64_t max_unsigned_val(TypeTableEntry *type_entry); | ||
| 87 | 88 | ||
| 88 | void render_const_value(Buf *buf, ConstExprValue *const_val); | 89 | void render_const_value(Buf *buf, ConstExprValue *const_val); |
| 89 | void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars); | 90 | void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars); |
src/codegen.cpp+29| ... | @@ -1466,6 +1466,27 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -1466,6 +1466,27 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 1466 | array_type->data.array.len, false); | 1466 | array_type->data.array.len, false); |
| 1467 | add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end); | 1467 | add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end); |
| 1468 | } | 1468 | } |
| 1469 | if (array_ptr_type->data.pointer.unaligned_bit_count != 0) { | ||
| 1470 | return array_ptr_ptr; | ||
| 1471 | } | ||
| 1472 | TypeTableEntry *canon_child_type = get_underlying_type(array_type->data.array.child_type); | ||
| 1473 | if (canon_child_type->id == TypeTableEntryIdStruct && | ||
| 1474 | canon_child_type->data.structure.layout == ContainerLayoutPacked) | ||
| 1475 | { | ||
| 1476 | LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0); | ||
| 1477 | LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, ""); | ||
| 1478 | size_t unaligned_bit_count = instruction->base.value.type->data.pointer.unaligned_bit_count; | ||
| 1479 | assert(unaligned_bit_count != 0); | ||
| 1480 | assert(unaligned_bit_count % 8 == 0); | ||
| 1481 | LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->type_ref, | ||
| 1482 | unaligned_bit_count / 8, false); | ||
| 1483 | LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, ""); | ||
| 1484 | LLVMValueRef indices[] = { | ||
| 1485 | byte_offset | ||
| 1486 | }; | ||
| 1487 | LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP(g->builder, u8_array_ptr, indices, 1, ""); | ||
| 1488 | return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(canon_child_type->type_ref, 0), ""); | ||
| 1489 | } | ||
| 1469 | LLVMValueRef indices[] = { | 1490 | LLVMValueRef indices[] = { |
| 1470 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), | 1491 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), |
| 1471 | subscript_value | 1492 | subscript_value |
| ... | @@ -1552,11 +1573,19 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa | ... | @@ -1552,11 +1573,19 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa |
| 1552 | IrInstructionStructFieldPtr *instruction) | 1573 | IrInstructionStructFieldPtr *instruction) |
| 1553 | { | 1574 | { |
| 1554 | LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr); | 1575 | LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr); |
| 1576 | // not necessarily a pointer. could be TypeTableEntryIdStruct | ||
| 1577 | TypeTableEntry *struct_ptr_type = instruction->struct_ptr->value.type; | ||
| 1555 | TypeStructField *field = instruction->field; | 1578 | TypeStructField *field = instruction->field; |
| 1556 | 1579 | ||
| 1557 | if (!type_has_bits(field->type_entry)) | 1580 | if (!type_has_bits(field->type_entry)) |
| 1558 | return nullptr; | 1581 | return nullptr; |
| 1559 | 1582 | ||
| 1583 | if (struct_ptr_type->id == TypeTableEntryIdPointer && | ||
| 1584 | struct_ptr_type->data.pointer.unaligned_bit_count != 0) | ||
| 1585 | { | ||
| 1586 | return struct_ptr; | ||
| 1587 | } | ||
| 1588 | |||
| 1560 | assert(field->gen_index != SIZE_MAX); | 1589 | assert(field->gen_index != SIZE_MAX); |
| 1561 | return LLVMBuildStructGEP(g->builder, struct_ptr, field->gen_index, ""); | 1590 | return LLVMBuildStructGEP(g->builder, struct_ptr, field->gen_index, ""); |
| 1562 | } | 1591 | } |
src/ir.cpp+21-19| ... | @@ -7412,21 +7412,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -7412,21 +7412,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 7412 | return ira->codegen->builtin_types.entry_bool; | 7412 | return ira->codegen->builtin_types.entry_bool; |
| 7413 | } | 7413 | } |
| 7414 | 7414 | ||
| 7415 | static uint64_t max_unsigned_val(TypeTableEntry *type_entry) { | ||
| 7416 | assert(type_entry->id == TypeTableEntryIdInt); | ||
| 7417 | if (type_entry->data.integral.bit_count == 64) { | ||
| 7418 | return UINT64_MAX; | ||
| 7419 | } else if (type_entry->data.integral.bit_count == 32) { | ||
| 7420 | return UINT32_MAX; | ||
| 7421 | } else if (type_entry->data.integral.bit_count == 16) { | ||
| 7422 | return UINT16_MAX; | ||
| 7423 | } else if (type_entry->data.integral.bit_count == 8) { | ||
| 7424 | return UINT8_MAX; | ||
| 7425 | } else { | ||
| 7426 | zig_unreachable(); | ||
| 7427 | } | ||
| 7428 | } | ||
| 7429 | |||
| 7430 | static int ir_eval_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val, | 7415 | static int ir_eval_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val, |
| 7431 | ConstExprValue *out_val, bool (*bignum_fn)(BigNum *, BigNum *, BigNum *), | 7416 | ConstExprValue *out_val, bool (*bignum_fn)(BigNum *, BigNum *, BigNum *), |
| 7432 | TypeTableEntry *type, bool wrapping_op) | 7417 | TypeTableEntry *type, bool wrapping_op) |
| ... | @@ -8844,8 +8829,21 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -8844,8 +8829,21 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 8844 | buf_sprintf("index 0 outside array of size 0")); | 8829 | buf_sprintf("index 0 outside array of size 0")); |
| 8845 | } | 8830 | } |
| 8846 | TypeTableEntry *child_type = array_type->data.array.child_type; | 8831 | TypeTableEntry *child_type = array_type->data.array.child_type; |
| 8847 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, | 8832 | if (ptr_type->data.pointer.unaligned_bit_count == 0) { |
| 8848 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, 0, 0); | 8833 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 8834 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, 0, 0); | ||
| 8835 | } else { | ||
| 8836 | ConstExprValue *elem_val = ir_resolve_const(ira, elem_index, UndefBad); | ||
| 8837 | if (!elem_val) | ||
| 8838 | return ira->codegen->builtin_types.entry_invalid; | ||
| 8839 | |||
| 8840 | size_t bit_width = type_size_bits(ira->codegen, child_type); | ||
| 8841 | size_t bit_offset = bit_width * elem_val->data.x_bignum.data.x_uint; | ||
| 8842 | |||
| 8843 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, | ||
| 8844 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | ||
| 8845 | bit_offset, bit_width); | ||
| 8846 | } | ||
| 8849 | } else if (array_type->id == TypeTableEntryIdPointer) { | 8847 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 8850 | return_type = array_type; | 8848 | return_type = array_type; |
| 8851 | } else if (is_slice(array_type)) { | 8849 | } else if (is_slice(array_type)) { |
| ... | @@ -9072,9 +9070,13 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field | ... | @@ -9072,9 +9070,13 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 9072 | return ptr_type; | 9070 | return ptr_type; |
| 9073 | } | 9071 | } |
| 9074 | } | 9072 | } |
| 9073 | size_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset; | ||
| 9074 | size_t ptr_unaligned_bit_count = container_ptr->value.type->data.pointer.unaligned_bit_count; | ||
| 9075 | size_t unaligned_bit_count_for_result_type = (ptr_unaligned_bit_count == 0) ? | ||
| 9076 | field->unaligned_bit_count : type_size_bits(ira->codegen, field->type_entry); | ||
| 9075 | ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); | 9077 | ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); |
| 9076 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, | 9078 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, |
| 9077 | is_volatile, field->packed_bits_offset, field->unaligned_bit_count); | 9079 | ptr_bit_offset + field->packed_bits_offset, unaligned_bit_count_for_result_type); |
| 9078 | } else { | 9080 | } else { |
| 9079 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, | 9081 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 9080 | field_ptr_instruction, container_ptr, container_type); | 9082 | field_ptr_instruction, container_ptr, container_type); |
test/cases/misc.zig+12| ... | @@ -50,27 +50,39 @@ fn intTypeBuiltin() { | ... | @@ -50,27 +50,39 @@ fn intTypeBuiltin() { |
| 50 | assert(!usize.is_signed); | 50 | assert(!usize.is_signed); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | const u1 = @intType(false, 1); | ||
| 54 | const u63 = @intType(false, 63); | ||
| 55 | const i1 = @intType(true, 1); | ||
| 56 | const i63 = @intType(true, 63); | ||
| 57 | |||
| 53 | fn minValueAndMaxValue() { | 58 | fn minValueAndMaxValue() { |
| 54 | @setFnTest(this); | 59 | @setFnTest(this); |
| 55 | 60 | ||
| 61 | assert(@maxValue(u1) == 1); | ||
| 56 | assert(@maxValue(u8) == 255); | 62 | assert(@maxValue(u8) == 255); |
| 57 | assert(@maxValue(u16) == 65535); | 63 | assert(@maxValue(u16) == 65535); |
| 58 | assert(@maxValue(u32) == 4294967295); | 64 | assert(@maxValue(u32) == 4294967295); |
| 59 | assert(@maxValue(u64) == 18446744073709551615); | 65 | assert(@maxValue(u64) == 18446744073709551615); |
| 60 | 66 | ||
| 67 | assert(@maxValue(i1) == 0); | ||
| 61 | assert(@maxValue(i8) == 127); | 68 | assert(@maxValue(i8) == 127); |
| 62 | assert(@maxValue(i16) == 32767); | 69 | assert(@maxValue(i16) == 32767); |
| 63 | assert(@maxValue(i32) == 2147483647); | 70 | assert(@maxValue(i32) == 2147483647); |
| 71 | assert(@maxValue(i63) == 4611686018427387903); | ||
| 64 | assert(@maxValue(i64) == 9223372036854775807); | 72 | assert(@maxValue(i64) == 9223372036854775807); |
| 65 | 73 | ||
| 74 | assert(@minValue(u1) == 0); | ||
| 66 | assert(@minValue(u8) == 0); | 75 | assert(@minValue(u8) == 0); |
| 67 | assert(@minValue(u16) == 0); | 76 | assert(@minValue(u16) == 0); |
| 68 | assert(@minValue(u32) == 0); | 77 | assert(@minValue(u32) == 0); |
| 78 | assert(@minValue(u63) == 0); | ||
| 69 | assert(@minValue(u64) == 0); | 79 | assert(@minValue(u64) == 0); |
| 70 | 80 | ||
| 81 | assert(@minValue(i1) == -1); | ||
| 71 | assert(@minValue(i8) == -128); | 82 | assert(@minValue(i8) == -128); |
| 72 | assert(@minValue(i16) == -32768); | 83 | assert(@minValue(i16) == -32768); |
| 73 | assert(@minValue(i32) == -2147483648); | 84 | assert(@minValue(i32) == -2147483648); |
| 85 | assert(@minValue(i63) == -4611686018427387904); | ||
| 74 | assert(@minValue(i64) == -9223372036854775808); | 86 | assert(@minValue(i64) == -9223372036854775808); |
| 75 | } | 87 | } |
| 76 | 88 |
test/cases/struct.zig+53-2| ... | @@ -285,8 +285,10 @@ const Foo96Bits = packed struct { | ... | @@ -285,8 +285,10 @@ const Foo96Bits = packed struct { |
| 285 | fn packedStruct24Bits() { | 285 | fn packedStruct24Bits() { |
| 286 | @setFnTest(this); | 286 | @setFnTest(this); |
| 287 | 287 | ||
| 288 | comptime assert(@sizeOf(Foo24Bits) == 3); | 288 | comptime { |
| 289 | comptime assert(@sizeOf(Foo96Bits) == 12); | 289 | assert(@sizeOf(Foo24Bits) == 3); |
| 290 | assert(@sizeOf(Foo96Bits) == 12); | ||
| 291 | } | ||
| 290 | 292 | ||
| 291 | var value = Foo96Bits { | 293 | var value = Foo96Bits { |
| 292 | .a = 0, | 294 | .a = 0, |
| ... | @@ -318,3 +320,52 @@ fn packedStruct24Bits() { | ... | @@ -318,3 +320,52 @@ fn packedStruct24Bits() { |
| 318 | assert(value.c == 1); | 320 | assert(value.c == 1); |
| 319 | assert(value.d == 1); | 321 | assert(value.d == 1); |
| 320 | } | 322 | } |
| 323 | |||
| 324 | const FooArray24Bits = packed struct { | ||
| 325 | a: u16, | ||
| 326 | b: [2]Foo24Bits, | ||
| 327 | c: u16, | ||
| 328 | }; | ||
| 329 | |||
| 330 | fn packedArray24Bits() { | ||
| 331 | @setFnTest(this); | ||
| 332 | |||
| 333 | comptime { | ||
| 334 | assert(@sizeOf([9]Foo24Bits) == 9 * 3); | ||
| 335 | assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2); | ||
| 336 | } | ||
| 337 | |||
| 338 | var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1); | ||
| 339 | bytes[bytes.len - 1] = 0xaa; | ||
| 340 | const ptr = &([]FooArray24Bits)(bytes[0...bytes.len - 1])[0]; | ||
| 341 | assert(ptr.a == 0); | ||
| 342 | assert(ptr.b[0].field == 0); | ||
| 343 | assert(ptr.b[1].field == 0); | ||
| 344 | assert(ptr.c == 0); | ||
| 345 | |||
| 346 | ptr.a = @maxValue(u16); | ||
| 347 | assert(ptr.a == @maxValue(u16)); | ||
| 348 | assert(ptr.b[0].field == 0); | ||
| 349 | assert(ptr.b[1].field == 0); | ||
| 350 | assert(ptr.c == 0); | ||
| 351 | |||
| 352 | ptr.b[0].field = @maxValue(u24); | ||
| 353 | assert(ptr.a == @maxValue(u16)); | ||
| 354 | assert(ptr.b[0].field == @maxValue(u24)); | ||
| 355 | assert(ptr.b[1].field == 0); | ||
| 356 | assert(ptr.c == 0); | ||
| 357 | |||
| 358 | ptr.b[1].field = @maxValue(u24); | ||
| 359 | assert(ptr.a == @maxValue(u16)); | ||
| 360 | assert(ptr.b[0].field == @maxValue(u24)); | ||
| 361 | assert(ptr.b[1].field == @maxValue(u24)); | ||
| 362 | assert(ptr.c == 0); | ||
| 363 | |||
| 364 | ptr.c = @maxValue(u16); | ||
| 365 | assert(ptr.a == @maxValue(u16)); | ||
| 366 | assert(ptr.b[0].field == @maxValue(u24)); | ||
| 367 | assert(ptr.b[1].field == @maxValue(u24)); | ||
| 368 | assert(ptr.c == @maxValue(u16)); | ||
| 369 | |||
| 370 | assert(bytes[bytes.len - 1] == 0xaa); | ||
| 371 | } |