| author | |
| committer | |
| log | 0148f39df929cc00c1b2231acce41c22f74f9969 |
| tree | 6b7904248232572d9edc5b69b74a67c166bb8008 |
| parent | 244362fed7ed9280a0612c7c57ed67f6fa33b40d |
adds compile error when passing pointer that is byte-aligned
at the beginning but not the end to a function expecting
a fully byte aligned pointer
closes #2616 files changed, 74 insertions(+), 57 deletions(-)
src/all_types.hpp+3| ... | @@ -853,6 +853,7 @@ struct TypeTableEntryPointer { | ... | @@ -853,6 +853,7 @@ struct TypeTableEntryPointer { |
| 853 | bool is_const; | 853 | bool is_const; |
| 854 | bool is_volatile; | 854 | bool is_volatile; |
| 855 | uint32_t bit_offset; | 855 | uint32_t bit_offset; |
| 856 | uint32_t unaligned_bit_count; | ||
| 856 | }; | 857 | }; |
| 857 | 858 | ||
| 858 | struct TypeTableEntryInt { | 859 | struct TypeTableEntryInt { |
| ... | @@ -877,6 +878,7 @@ struct TypeStructField { | ... | @@ -877,6 +878,7 @@ struct TypeStructField { |
| 877 | // offset from the memory at gen_index | 878 | // offset from the memory at gen_index |
| 878 | size_t packed_bits_offset; | 879 | size_t packed_bits_offset; |
| 879 | size_t packed_bits_size; | 880 | size_t packed_bits_size; |
| 881 | size_t unaligned_bit_count; | ||
| 880 | }; | 882 | }; |
| 881 | struct TypeTableEntryStruct { | 883 | struct TypeTableEntryStruct { |
| 882 | AstNode *decl_node; | 884 | AstNode *decl_node; |
| ... | @@ -1204,6 +1206,7 @@ struct TypeId { | ... | @@ -1204,6 +1206,7 @@ struct TypeId { |
| 1204 | bool is_const; | 1206 | bool is_const; |
| 1205 | bool is_volatile; | 1207 | bool is_volatile; |
| 1206 | uint32_t bit_offset; | 1208 | uint32_t bit_offset; |
| 1209 | uint32_t unaligned_bit_count; | ||
| 1207 | } pointer; | 1210 | } pointer; |
| 1208 | struct { | 1211 | struct { |
| 1209 | TypeTableEntry *child_type; | 1212 | TypeTableEntry *child_type; |
src/analyze.cpp+23-11| ... | @@ -287,23 +287,25 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) { | ... | @@ -287,23 +287,25 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) { |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const, | 289 | TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const, |
| 290 | uint32_t bit_offset, bool is_volatile) | 290 | bool is_volatile, uint32_t bit_offset, uint32_t unaligned_bit_count) |
| 291 | { | 291 | { |
| 292 | assert(child_type->id != TypeTableEntryIdInvalid); | 292 | assert(child_type->id != TypeTableEntryIdInvalid); |
| 293 | 293 | ||
| 294 | TypeId type_id = {}; | 294 | TypeId type_id = {}; |
| 295 | TypeTableEntry **parent_pointer = nullptr; | 295 | TypeTableEntry **parent_pointer = nullptr; |
| 296 | if (bit_offset != 0 || is_volatile) { | 296 | if (unaligned_bit_count != 0 || is_volatile) { |
| 297 | type_id.id = TypeTableEntryIdPointer; | 297 | type_id.id = TypeTableEntryIdPointer; |
| 298 | type_id.data.pointer.child_type = child_type; | 298 | type_id.data.pointer.child_type = child_type; |
| 299 | type_id.data.pointer.is_const = is_const; | 299 | type_id.data.pointer.is_const = is_const; |
| 300 | type_id.data.pointer.is_volatile = is_volatile; | 300 | type_id.data.pointer.is_volatile = is_volatile; |
| 301 | type_id.data.pointer.bit_offset = bit_offset; | 301 | type_id.data.pointer.bit_offset = bit_offset; |
| 302 | type_id.data.pointer.unaligned_bit_count = unaligned_bit_count; | ||
| 302 | 303 | ||
| 303 | auto existing_entry = g->type_table.maybe_get(type_id); | 304 | auto existing_entry = g->type_table.maybe_get(type_id); |
| 304 | if (existing_entry) | 305 | if (existing_entry) |
| 305 | return existing_entry->value; | 306 | return existing_entry->value; |
| 306 | } else { | 307 | } else { |
| 308 | assert(bit_offset == 0); | ||
| 307 | parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)]; | 309 | parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)]; |
| 308 | if (*parent_pointer) | 310 | if (*parent_pointer) |
| 309 | return *parent_pointer; | 311 | return *parent_pointer; |
| ... | @@ -316,11 +318,11 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type | ... | @@ -316,11 +318,11 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type |
| 316 | const char *const_str = is_const ? "const " : ""; | 318 | const char *const_str = is_const ? "const " : ""; |
| 317 | const char *volatile_str = is_volatile ? "volatile " : ""; | 319 | const char *volatile_str = is_volatile ? "volatile " : ""; |
| 318 | buf_resize(&entry->name, 0); | 320 | buf_resize(&entry->name, 0); |
| 319 | if (bit_offset == 0) { | 321 | if (unaligned_bit_count == 0) { |
| 320 | buf_appendf(&entry->name, "&%s%s%s", const_str, volatile_str, buf_ptr(&child_type->name)); | 322 | buf_appendf(&entry->name, "&%s%s%s", const_str, volatile_str, buf_ptr(&child_type->name)); |
| 321 | } else { | 323 | } else { |
| 322 | buf_appendf(&entry->name, "&:%" PRIu8 " %s%s%s", bit_offset, const_str, | 324 | buf_appendf(&entry->name, "&:%" PRIu32 ":%" PRIu32 " %s%s%s", bit_offset, |
| 323 | volatile_str, buf_ptr(&child_type->name)); | 325 | bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name)); |
| 324 | } | 326 | } |
| 325 | 327 | ||
| 326 | TypeTableEntry *canon_child_type = get_underlying_type(child_type); | 328 | TypeTableEntry *canon_child_type = get_underlying_type(child_type); |
| ... | @@ -344,6 +346,7 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type | ... | @@ -344,6 +346,7 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type |
| 344 | entry->data.pointer.is_const = is_const; | 346 | entry->data.pointer.is_const = is_const; |
| 345 | entry->data.pointer.is_volatile = is_volatile; | 347 | entry->data.pointer.is_volatile = is_volatile; |
| 346 | entry->data.pointer.bit_offset = bit_offset; | 348 | entry->data.pointer.bit_offset = bit_offset; |
| 349 | entry->data.pointer.unaligned_bit_count = unaligned_bit_count; | ||
| 347 | 350 | ||
| 348 | if (parent_pointer) { | 351 | if (parent_pointer) { |
| 349 | *parent_pointer = entry; | 352 | *parent_pointer = entry; |
| ... | @@ -354,7 +357,7 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type | ... | @@ -354,7 +357,7 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type |
| 354 | } | 357 | } |
| 355 | 358 | ||
| 356 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { | 359 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { |
| 357 | return get_pointer_to_type_extra(g, child_type, is_const, 0, false); | 360 | return get_pointer_to_type_extra(g, child_type, is_const, false, 0, 0); |
| 358 | } | 361 | } |
| 359 | 362 | ||
| 360 | TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { | 363 | TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { |
| ... | @@ -1429,13 +1432,15 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { | ... | @@ -1429,13 +1432,15 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 1429 | break; | 1432 | break; |
| 1430 | } | 1433 | } |
| 1431 | 1434 | ||
| 1432 | type_struct_field->packed_bits_size = type_size_bits(g, field_type); | 1435 | size_t field_size_in_bits = type_size_bits(g, field_type); |
| 1436 | size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits; | ||
| 1433 | 1437 | ||
| 1434 | size_t next_packed_bits_offset = packed_bits_offset + type_struct_field->packed_bits_size; | 1438 | type_struct_field->packed_bits_size = field_size_in_bits; |
| 1435 | 1439 | ||
| 1436 | if (first_packed_bits_offset_misalign != SIZE_MAX) { | 1440 | if (first_packed_bits_offset_misalign != SIZE_MAX) { |
| 1437 | // this field is not byte-aligned; it is part of the previous field with a bit offset | 1441 | // this field is not byte-aligned; it is part of the previous field with a bit offset |
| 1438 | type_struct_field->packed_bits_offset = packed_bits_offset - first_packed_bits_offset_misalign; | 1442 | type_struct_field->packed_bits_offset = packed_bits_offset - first_packed_bits_offset_misalign; |
| 1443 | type_struct_field->unaligned_bit_count = field_size_in_bits; | ||
| 1439 | 1444 | ||
| 1440 | if (next_packed_bits_offset % 8 == 0) { | 1445 | if (next_packed_bits_offset % 8 == 0) { |
| 1441 | // next field recovers byte alignment | 1446 | // next field recovers byte alignment |
| ... | @@ -1448,9 +1453,12 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { | ... | @@ -1448,9 +1453,12 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 1448 | } else if (next_packed_bits_offset % 8 != 0) { | 1453 | } else if (next_packed_bits_offset % 8 != 0) { |
| 1449 | first_packed_bits_offset_misalign = packed_bits_offset; | 1454 | first_packed_bits_offset_misalign = packed_bits_offset; |
| 1450 | type_struct_field->packed_bits_offset = 0; | 1455 | type_struct_field->packed_bits_offset = 0; |
| 1456 | type_struct_field->unaligned_bit_count = field_size_in_bits; | ||
| 1451 | } else { | 1457 | } else { |
| 1458 | // This is a byte-aligned field (both start and end) in a packed struct. | ||
| 1452 | element_types[gen_field_index] = field_type->type_ref; | 1459 | element_types[gen_field_index] = field_type->type_ref; |
| 1453 | type_struct_field->packed_bits_offset = 0; | 1460 | type_struct_field->packed_bits_offset = 0; |
| 1461 | type_struct_field->unaligned_bit_count = 0; | ||
| 1454 | gen_field_index += 1; | 1462 | gen_field_index += 1; |
| 1455 | } | 1463 | } |
| 1456 | packed_bits_offset = next_packed_bits_offset; | 1464 | packed_bits_offset = next_packed_bits_offset; |
| ... | @@ -2237,7 +2245,9 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry * | ... | @@ -2237,7 +2245,9 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry * |
| 2237 | if (expected_type->id == TypeTableEntryIdPointer && | 2245 | if (expected_type->id == TypeTableEntryIdPointer && |
| 2238 | actual_type->id == TypeTableEntryIdPointer && | 2246 | actual_type->id == TypeTableEntryIdPointer && |
| 2239 | (!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const) && | 2247 | (!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const) && |
| 2240 | (!actual_type->data.pointer.is_volatile || expected_type->data.pointer.is_volatile)) | 2248 | (!actual_type->data.pointer.is_volatile || expected_type->data.pointer.is_volatile) && |
| 2249 | actual_type->data.pointer.bit_offset == expected_type->data.pointer.bit_offset && | ||
| 2250 | actual_type->data.pointer.unaligned_bit_count == expected_type->data.pointer.unaligned_bit_count) | ||
| 2241 | { | 2251 | { |
| 2242 | return types_match_const_cast_only(expected_type->data.pointer.child_type, | 2252 | return types_match_const_cast_only(expected_type->data.pointer.child_type, |
| 2243 | actual_type->data.pointer.child_type); | 2253 | actual_type->data.pointer.child_type); |
| ... | @@ -3943,7 +3953,8 @@ uint32_t type_id_hash(TypeId x) { | ... | @@ -3943,7 +3953,8 @@ uint32_t type_id_hash(TypeId x) { |
| 3943 | return hash_ptr(x.data.pointer.child_type) + | 3953 | return hash_ptr(x.data.pointer.child_type) + |
| 3944 | (x.data.pointer.is_const ? 2749109194 : 4047371087) + | 3954 | (x.data.pointer.is_const ? 2749109194 : 4047371087) + |
| 3945 | (x.data.pointer.is_volatile ? 536730450 : 1685612214) + | 3955 | (x.data.pointer.is_volatile ? 536730450 : 1685612214) + |
| 3946 | (((uint32_t)x.data.pointer.bit_offset) * 2639019452); | 3956 | (((uint32_t)x.data.pointer.bit_offset) * 2639019452) + |
| 3957 | (((uint32_t)x.data.pointer.unaligned_bit_count) * 529908881); | ||
| 3947 | case TypeTableEntryIdArray: | 3958 | case TypeTableEntryIdArray: |
| 3948 | return hash_ptr(x.data.array.child_type) + | 3959 | return hash_ptr(x.data.array.child_type) + |
| 3949 | (x.data.array.size * 2122979968); | 3960 | (x.data.array.size * 2122979968); |
| ... | @@ -3987,7 +3998,8 @@ bool type_id_eql(TypeId a, TypeId b) { | ... | @@ -3987,7 +3998,8 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 3987 | return a.data.pointer.child_type == b.data.pointer.child_type && | 3998 | return a.data.pointer.child_type == b.data.pointer.child_type && |
| 3988 | a.data.pointer.is_const == b.data.pointer.is_const && | 3999 | a.data.pointer.is_const == b.data.pointer.is_const && |
| 3989 | a.data.pointer.is_volatile == b.data.pointer.is_volatile && | 4000 | a.data.pointer.is_volatile == b.data.pointer.is_volatile && |
| 3990 | a.data.pointer.bit_offset == b.data.pointer.bit_offset; | 4001 | a.data.pointer.bit_offset == b.data.pointer.bit_offset && |
| 4002 | a.data.pointer.unaligned_bit_count == b.data.pointer.unaligned_bit_count; | ||
| 3991 | case TypeTableEntryIdArray: | 4003 | case TypeTableEntryIdArray: |
| 3992 | return a.data.array.child_type == b.data.array.child_type && | 4004 | return a.data.array.child_type == b.data.array.child_type && |
| 3993 | a.data.array.size == b.data.array.size; | 4005 | a.data.array.size == b.data.array.size; |
src/analyze.hpp+1-1| ... | @@ -16,7 +16,7 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m | ... | @@ -16,7 +16,7 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m |
| 16 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); | 16 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); |
| 17 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); | 17 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); |
| 18 | TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const, | 18 | TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const, |
| 19 | uint32_t bit_offset, bool is_volatile); | 19 | bool is_volatile, uint32_t bit_offset, uint32_t unaligned_bit_count); |
| 20 | bool is_node_void_expr(AstNode *node); | 20 | bool is_node_void_expr(AstNode *node); |
| 21 | uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry); | 21 | uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry); |
| 22 | uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry); | 22 | uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry); |
src/codegen.cpp+16-33| ... | @@ -1374,27 +1374,17 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -1374,27 +1374,17 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 1374 | assert(ptr_type->id == TypeTableEntryIdPointer); | 1374 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 1375 | bool is_volatile = ptr_type->data.pointer.is_volatile; | 1375 | bool is_volatile = ptr_type->data.pointer.is_volatile; |
| 1376 | 1376 | ||
| 1377 | uint32_t bit_offset = ptr_type->data.pointer.bit_offset; | 1377 | uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; |
| 1378 | LLVMValueRef containing_int; | 1378 | if (unaligned_bit_count == 0) |
| 1379 | if (bit_offset == 0) { | 1379 | return get_handle_value(g, ptr, child_type, is_volatile); |
| 1380 | LLVMValueRef result_val = get_handle_value(g, ptr, child_type, is_volatile); | 1380 | |
| 1381 | if (LLVMGetTypeKind(LLVMTypeOf(result_val)) == LLVMIntegerTypeKind && | 1381 | assert(!handle_is_ptr(child_type)); |
| 1382 | LLVMGetTypeKind(child_type->type_ref) == LLVMIntegerTypeKind && | 1382 | LLVMValueRef containing_int = LLVMBuildLoad(g->builder, ptr, ""); |
| 1383 | LLVMGetIntTypeWidth(child_type->type_ref) < LLVMGetIntTypeWidth(LLVMTypeOf(result_val))) | 1383 | LLVMSetVolatile(containing_int, is_volatile); |
| 1384 | { | ||
| 1385 | containing_int = result_val; | ||
| 1386 | } else { | ||
| 1387 | return result_val; | ||
| 1388 | } | ||
| 1389 | } else { | ||
| 1390 | assert(!handle_is_ptr(child_type)); | ||
| 1391 | containing_int = LLVMBuildLoad(g->builder, ptr, ""); | ||
| 1392 | LLVMSetVolatile(containing_int, is_volatile); | ||
| 1393 | } | ||
| 1394 | 1384 | ||
| 1395 | uint32_t child_bit_count = type_size_bits(g, child_type); | 1385 | uint32_t bit_offset = ptr_type->data.pointer.bit_offset; |
| 1396 | uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); | 1386 | uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); |
| 1397 | uint32_t shift_amt = host_bit_count - bit_offset - child_bit_count; | 1387 | uint32_t shift_amt = host_bit_count - bit_offset - unaligned_bit_count; |
| 1398 | 1388 | ||
| 1399 | LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); | 1389 | LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); |
| 1400 | LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, ""); | 1390 | LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, ""); |
| ... | @@ -1416,25 +1406,18 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir | ... | @@ -1416,25 +1406,18 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir |
| 1416 | if (handle_is_ptr(child_type)) | 1406 | if (handle_is_ptr(child_type)) |
| 1417 | return gen_struct_memcpy(g, value, ptr, child_type); | 1407 | return gen_struct_memcpy(g, value, ptr, child_type); |
| 1418 | 1408 | ||
| 1419 | uint32_t bit_offset = ptr_type->data.pointer.bit_offset; | 1409 | uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; |
| 1420 | if (bit_offset == 0) { | 1410 | if (unaligned_bit_count == 0) { |
| 1421 | LLVMTypeRef ptr_child_ref = LLVMGetElementType(LLVMTypeOf(ptr)); | 1411 | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, value, ptr); |
| 1422 | bool need_to_do_some_bit_stuff = | 1412 | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); |
| 1423 | LLVMGetTypeKind(ptr_child_ref) == LLVMIntegerTypeKind && | 1413 | return nullptr; |
| 1424 | LLVMGetTypeKind(child_type->type_ref) == LLVMIntegerTypeKind && | ||
| 1425 | LLVMGetIntTypeWidth(child_type->type_ref) < LLVMGetIntTypeWidth(ptr_child_ref); | ||
| 1426 | if (!need_to_do_some_bit_stuff) { | ||
| 1427 | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, value, ptr); | ||
| 1428 | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); | ||
| 1429 | return nullptr; | ||
| 1430 | } | ||
| 1431 | } | 1414 | } |
| 1432 | 1415 | ||
| 1433 | LLVMValueRef containing_int = LLVMBuildLoad(g->builder, ptr, ""); | 1416 | LLVMValueRef containing_int = LLVMBuildLoad(g->builder, ptr, ""); |
| 1434 | 1417 | ||
| 1435 | uint32_t child_bit_count = type_size_bits(g, child_type); | 1418 | uint32_t bit_offset = ptr_type->data.pointer.bit_offset; |
| 1436 | uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); | 1419 | uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); |
| 1437 | uint32_t shift_amt = host_bit_count - bit_offset - child_bit_count; | 1420 | uint32_t shift_amt = host_bit_count - bit_offset - unaligned_bit_count; |
| 1438 | LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); | 1421 | LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); |
| 1439 | 1422 | ||
| 1440 | LLVMValueRef mask_val = LLVMConstAllOnes(child_type->type_ref); | 1423 | LLVMValueRef mask_val = LLVMConstAllOnes(child_type->type_ref); |
src/ir.cpp+12-12| ... | @@ -6227,11 +6227,11 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio | ... | @@ -6227,11 +6227,11 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio |
| 6227 | const_val->type = pointee_type; | 6227 | const_val->type = pointee_type; |
| 6228 | type_ensure_zero_bits_known(ira->codegen, type_entry); | 6228 | type_ensure_zero_bits_known(ira->codegen, type_entry); |
| 6229 | const_val->data.x_type = get_pointer_to_type_extra(ira->codegen, type_entry, | 6229 | const_val->data.x_type = get_pointer_to_type_extra(ira->codegen, type_entry, |
| 6230 | ptr_is_const, 0, ptr_is_volatile); | 6230 | ptr_is_const, ptr_is_volatile, 0, 0); |
| 6231 | return const_instr; | 6231 | return const_instr; |
| 6232 | } else { | 6232 | } else { |
| 6233 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, pointee_type, | 6233 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, pointee_type, |
| 6234 | ptr_is_const, 0, ptr_is_volatile); | 6234 | ptr_is_const, ptr_is_volatile, 0, 0); |
| 6235 | IrInstruction *const_instr = ir_get_const(ira, instruction); | 6235 | IrInstruction *const_instr = ir_get_const(ira, instruction); |
| 6236 | ConstExprValue *const_val = &const_instr->value; | 6236 | ConstExprValue *const_val = &const_instr->value; |
| 6237 | const_val->type = ptr_type; | 6237 | const_val->type = ptr_type; |
| ... | @@ -6547,7 +6547,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi | ... | @@ -6547,7 +6547,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi |
| 6547 | ConstPtrMutComptimeConst, is_const, is_volatile); | 6547 | ConstPtrMutComptimeConst, is_const, is_volatile); |
| 6548 | } | 6548 | } |
| 6549 | 6549 | ||
| 6550 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type, is_const, 0, is_volatile); | 6550 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type, is_const, is_volatile, 0, 0); |
| 6551 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); | 6551 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 6552 | assert(fn_entry); | 6552 | assert(fn_entry); |
| 6553 | IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope, | 6553 | IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope, |
| ... | @@ -8839,7 +8839,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -8839,7 +8839,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 8839 | } | 8839 | } |
| 8840 | TypeTableEntry *child_type = array_type->data.array.child_type; | 8840 | TypeTableEntry *child_type = array_type->data.array.child_type; |
| 8841 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, | 8841 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 8842 | ptr_type->data.pointer.is_const, 0, ptr_type->data.pointer.is_volatile); | 8842 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, 0, 0); |
| 8843 | } else if (array_type->id == TypeTableEntryIdPointer) { | 8843 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 8844 | return_type = array_type; | 8844 | return_type = array_type; |
| 8845 | } else if (is_slice(array_type)) { | 8845 | } else if (is_slice(array_type)) { |
| ... | @@ -9057,7 +9057,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field | ... | @@ -9057,7 +9057,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 9057 | ConstExprValue *struct_val = const_ptr_pointee(ptr_val); | 9057 | ConstExprValue *struct_val = const_ptr_pointee(ptr_val); |
| 9058 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index]; | 9058 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index]; |
| 9059 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type, | 9059 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type, |
| 9060 | is_const, 0, is_volatile); | 9060 | is_const, is_volatile, 0, 0); |
| 9061 | ConstExprValue *const_val = ir_build_const_from(ira, &field_ptr_instruction->base); | 9061 | ConstExprValue *const_val = ir_build_const_from(ira, &field_ptr_instruction->base); |
| 9062 | const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct; | 9062 | const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct; |
| 9063 | const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut; | 9063 | const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut; |
| ... | @@ -9068,7 +9068,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field | ... | @@ -9068,7 +9068,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 9068 | } | 9068 | } |
| 9069 | ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); | 9069 | ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); |
| 9070 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, | 9070 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, |
| 9071 | field->packed_bits_offset, is_volatile); | 9071 | is_volatile, field->packed_bits_offset, field->unaligned_bit_count); |
| 9072 | } else { | 9072 | } else { |
| 9073 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, | 9073 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 9074 | field_ptr_instruction, container_ptr, container_type); | 9074 | field_ptr_instruction, container_ptr, container_type); |
| ... | @@ -9080,7 +9080,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field | ... | @@ -9080,7 +9080,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 9080 | TypeEnumField *field = find_enum_type_field(bare_type, field_name); | 9080 | TypeEnumField *field = find_enum_type_field(bare_type, field_name); |
| 9081 | if (field) { | 9081 | if (field) { |
| 9082 | ir_build_enum_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); | 9082 | ir_build_enum_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); |
| 9083 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, 0, is_volatile); | 9083 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, 0, 0); |
| 9084 | } else { | 9084 | } else { |
| 9085 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, | 9085 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 9086 | field_ptr_instruction, container_ptr, container_type); | 9086 | field_ptr_instruction, container_ptr, container_type); |
| ... | @@ -10016,7 +10016,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, | ... | @@ -10016,7 +10016,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| 10016 | } | 10016 | } |
| 10017 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; | 10017 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; |
| 10018 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, child_type, | 10018 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 10019 | ptr_type->data.pointer.is_const, 0, ptr_type->data.pointer.is_volatile); | 10019 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, 0, 0); |
| 10020 | 10020 | ||
| 10021 | if (instr_is_comptime(value)) { | 10021 | if (instr_is_comptime(value)) { |
| 10022 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); | 10022 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| ... | @@ -11322,7 +11322,7 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi | ... | @@ -11322,7 +11322,7 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi |
| 11322 | 11322 | ||
| 11323 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; | 11323 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; |
| 11324 | TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8; | 11324 | TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8; |
| 11325 | TypeTableEntry *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, 0, dest_is_volatile); | 11325 | TypeTableEntry *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, 0, 0); |
| 11326 | 11326 | ||
| 11327 | IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr); | 11327 | IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr); |
| 11328 | if (casted_dest_ptr->value.type->id == TypeTableEntryIdInvalid) | 11328 | if (casted_dest_ptr->value.type->id == TypeTableEntryIdInvalid) |
| ... | @@ -11410,8 +11410,8 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi | ... | @@ -11410,8 +11410,8 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi |
| 11410 | 11410 | ||
| 11411 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; | 11411 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; |
| 11412 | TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8; | 11412 | TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8; |
| 11413 | TypeTableEntry *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, 0, dest_is_volatile); | 11413 | TypeTableEntry *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, 0, 0); |
| 11414 | TypeTableEntry *u8_ptr_const = get_pointer_to_type_extra(ira->codegen, u8, true, 0, src_is_volatile); | 11414 | TypeTableEntry *u8_ptr_const = get_pointer_to_type_extra(ira->codegen, u8, true, src_is_volatile, 0, 0); |
| 11415 | 11415 | ||
| 11416 | IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr_mut); | 11416 | IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr_mut); |
| 11417 | if (casted_dest_ptr->value.type->id == TypeTableEntryIdInvalid) | 11417 | if (casted_dest_ptr->value.type->id == TypeTableEntryIdInvalid) |
| ... | @@ -11929,7 +11929,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, | ... | @@ -11929,7 +11929,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, |
| 11929 | } else if (canon_type->id == TypeTableEntryIdErrorUnion) { | 11929 | } else if (canon_type->id == TypeTableEntryIdErrorUnion) { |
| 11930 | TypeTableEntry *child_type = canon_type->data.error.child_type; | 11930 | TypeTableEntry *child_type = canon_type->data.error.child_type; |
| 11931 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, child_type, | 11931 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 11932 | ptr_type->data.pointer.is_const, 0, ptr_type->data.pointer.is_volatile); | 11932 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, 0, 0); |
| 11933 | if (instr_is_comptime(value)) { | 11933 | if (instr_is_comptime(value)) { |
| 11934 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); | 11934 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); |
| 11935 | if (!ptr_val) | 11935 | if (!ptr_val) |
test/run_tests.cpp+19| ... | @@ -1627,6 +1627,25 @@ pub fn main(args: [][]u8) -> ??void { | ... | @@ -1627,6 +1627,25 @@ pub fn main(args: [][]u8) -> ??void { |
| 1627 | } | 1627 | } |
| 1628 | )SOURCE", 1, ".tmp_source.zig:2:30: error: expected return type of main to be '%void', instead is '??void'"); | 1628 | )SOURCE", 1, ".tmp_source.zig:2:30: error: expected return type of main to be '%void', instead is '??void'"); |
| 1629 | 1629 | ||
| 1630 | add_compile_fail_case("casting bit offset pointer to regular pointer", R"SOURCE( | ||
| 1631 | const u2 = @intType(false, 2); | ||
| 1632 | const u3 = @intType(false, 3); | ||
| 1633 | |||
| 1634 | const BitField = packed struct { | ||
| 1635 | a: u3, | ||
| 1636 | b: u3, | ||
| 1637 | c: u2, | ||
| 1638 | }; | ||
| 1639 | |||
| 1640 | fn foo(bit_field: &const BitField) -> u3 { | ||
| 1641 | return bar(&bit_field.b); | ||
| 1642 | } | ||
| 1643 | |||
| 1644 | fn bar(x: &const u3) -> u3 { | ||
| 1645 | return *x; | ||
| 1646 | } | ||
| 1647 | )SOURCE", 1, ".tmp_source.zig:12:26: error: expected type '&const u3', found '&:3:6 const u3'"); | ||
| 1648 | |||
| 1630 | } | 1649 | } |
| 1631 | 1650 | ||
| 1632 | ////////////////////////////////////////////////////////////////////////////// | 1651 | ////////////////////////////////////////////////////////////////////////////// |