authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-16 19:35:42-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-16 19:35:42-05:00
log0148f39df929cc00c1b2231acce41c22f74f9969
tree6b7904248232572d9edc5b69b74a67c166bb8008
parent244362fed7ed9280a0612c7c57ed67f6fa33b40d

pointers with bit offset contain length

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 #261

6 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};
857858
858struct TypeTableEntryInt {859struct TypeTableEntryInt {
...@@ -877,6 +878,7 @@ struct TypeStructField {...@@ -877,6 +878,7 @@ struct TypeStructField {
877 // offset from the memory at gen_index878 // 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};
881struct TypeTableEntryStruct {883struct 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}
288288
289TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const,289TypeTableEntry *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);
293293
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;
302303
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 }
325327
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;
347350
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}
355358
356TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {359TypeTableEntry *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}
359362
360TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {363TypeTableEntry *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 }
14311434
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;
14331437
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;
14351439
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 offset1441 // 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;
14391444
1440 if (next_packed_bits_offset % 8 == 0) {1445 if (next_packed_bits_offset % 8 == 0) {
1441 // next field recovers byte alignment1446 // 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
16TypeTableEntry *new_type_table_entry(TypeTableEntryId id);16TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
17TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);17TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
18TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const,18TypeTableEntry *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);
20bool is_node_void_expr(AstNode *node);20bool is_node_void_expr(AstNode *node);
21uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);21uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);
22uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry);22uint64_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;
13761376
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 }
13941384
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;
13981388
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);
14181408
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 }
14321415
1433 LLVMValueRef containing_int = LLVMBuildLoad(g->builder, ptr, "");1416 LLVMValueRef containing_int = LLVMBuildLoad(g->builder, ptr, "");
14341417
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);
14391422
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 }
65496549
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);
1002010020
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
1132211322
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);
1132611326
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
1141011410
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);
1141511415
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'");
16291629
1630 add_compile_fail_case("casting bit offset pointer to regular pointer", R"SOURCE(
1631const u2 = @intType(false, 2);
1632const u3 = @intType(false, 3);
1633
1634const BitField = packed struct {
1635 a: u3,
1636 b: u3,
1637 c: u2,
1638};
1639
1640fn foo(bit_field: &const BitField) -> u3 {
1641 return bar(&bit_field.b);
1642}
1643
1644fn 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}
16311650
1632//////////////////////////////////////////////////////////////////////////////1651//////////////////////////////////////////////////////////////////////////////