aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-02-16 19:35:42 -0500
committerAndrew Kelley <superjoe30@gmail.com>2017-02-16 19:35:42 -0500
commit0148f39df929cc00c1b2231acce41c22f74f9969 (patch)
tree6b7904248232572d9edc5b69b74a67c166bb8008 /src/analyze.cpp
parent244362fed7ed9280a0612c7c57ed67f6fa33b40d (diff)
downloadzig-0148f39df929cc00c1b2231acce41c22f74f9969.tar.gz
zig-0148f39df929cc00c1b2231acce41c22f74f9969.zip
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
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp34
1 files changed, 23 insertions, 11 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 8ac641ebfc..e4ccf699ba 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -287,23 +287,25 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
}
TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const,
- uint32_t bit_offset, bool is_volatile)
+ bool is_volatile, uint32_t bit_offset, uint32_t unaligned_bit_count)
{
assert(child_type->id != TypeTableEntryIdInvalid);
TypeId type_id = {};
TypeTableEntry **parent_pointer = nullptr;
- if (bit_offset != 0 || is_volatile) {
+ if (unaligned_bit_count != 0 || is_volatile) {
type_id.id = TypeTableEntryIdPointer;
type_id.data.pointer.child_type = child_type;
type_id.data.pointer.is_const = is_const;
type_id.data.pointer.is_volatile = is_volatile;
type_id.data.pointer.bit_offset = bit_offset;
+ type_id.data.pointer.unaligned_bit_count = unaligned_bit_count;
auto existing_entry = g->type_table.maybe_get(type_id);
if (existing_entry)
return existing_entry->value;
} else {
+ assert(bit_offset == 0);
parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
if (*parent_pointer)
return *parent_pointer;
@@ -316,11 +318,11 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
const char *const_str = is_const ? "const " : "";
const char *volatile_str = is_volatile ? "volatile " : "";
buf_resize(&entry->name, 0);
- if (bit_offset == 0) {
+ if (unaligned_bit_count == 0) {
buf_appendf(&entry->name, "&%s%s%s", const_str, volatile_str, buf_ptr(&child_type->name));
} else {
- buf_appendf(&entry->name, "&:%" PRIu8 " %s%s%s", bit_offset, const_str,
- volatile_str, buf_ptr(&child_type->name));
+ buf_appendf(&entry->name, "&:%" PRIu32 ":%" PRIu32 " %s%s%s", bit_offset,
+ bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));
}
TypeTableEntry *canon_child_type = get_underlying_type(child_type);
@@ -344,6 +346,7 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
entry->data.pointer.is_const = is_const;
entry->data.pointer.is_volatile = is_volatile;
entry->data.pointer.bit_offset = bit_offset;
+ entry->data.pointer.unaligned_bit_count = unaligned_bit_count;
if (parent_pointer) {
*parent_pointer = entry;
@@ -354,7 +357,7 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
}
TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
- return get_pointer_to_type_extra(g, child_type, is_const, 0, false);
+ return get_pointer_to_type_extra(g, child_type, is_const, false, 0, 0);
}
TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
@@ -1429,13 +1432,15 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
break;
}
- type_struct_field->packed_bits_size = type_size_bits(g, field_type);
+ size_t field_size_in_bits = type_size_bits(g, field_type);
+ size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits;
- size_t next_packed_bits_offset = packed_bits_offset + type_struct_field->packed_bits_size;
+ type_struct_field->packed_bits_size = field_size_in_bits;
if (first_packed_bits_offset_misalign != SIZE_MAX) {
// this field is not byte-aligned; it is part of the previous field with a bit offset
type_struct_field->packed_bits_offset = packed_bits_offset - first_packed_bits_offset_misalign;
+ type_struct_field->unaligned_bit_count = field_size_in_bits;
if (next_packed_bits_offset % 8 == 0) {
// next field recovers byte alignment
@@ -1448,9 +1453,12 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
} else if (next_packed_bits_offset % 8 != 0) {
first_packed_bits_offset_misalign = packed_bits_offset;
type_struct_field->packed_bits_offset = 0;
+ type_struct_field->unaligned_bit_count = field_size_in_bits;
} else {
+ // This is a byte-aligned field (both start and end) in a packed struct.
element_types[gen_field_index] = field_type->type_ref;
type_struct_field->packed_bits_offset = 0;
+ type_struct_field->unaligned_bit_count = 0;
gen_field_index += 1;
}
packed_bits_offset = next_packed_bits_offset;
@@ -2237,7 +2245,9 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *
if (expected_type->id == TypeTableEntryIdPointer &&
actual_type->id == TypeTableEntryIdPointer &&
(!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const) &&
- (!actual_type->data.pointer.is_volatile || expected_type->data.pointer.is_volatile))
+ (!actual_type->data.pointer.is_volatile || expected_type->data.pointer.is_volatile) &&
+ actual_type->data.pointer.bit_offset == expected_type->data.pointer.bit_offset &&
+ actual_type->data.pointer.unaligned_bit_count == expected_type->data.pointer.unaligned_bit_count)
{
return types_match_const_cast_only(expected_type->data.pointer.child_type,
actual_type->data.pointer.child_type);
@@ -3943,7 +3953,8 @@ uint32_t type_id_hash(TypeId x) {
return hash_ptr(x.data.pointer.child_type) +
(x.data.pointer.is_const ? 2749109194 : 4047371087) +
(x.data.pointer.is_volatile ? 536730450 : 1685612214) +
- (((uint32_t)x.data.pointer.bit_offset) * 2639019452);
+ (((uint32_t)x.data.pointer.bit_offset) * 2639019452) +
+ (((uint32_t)x.data.pointer.unaligned_bit_count) * 529908881);
case TypeTableEntryIdArray:
return hash_ptr(x.data.array.child_type) +
(x.data.array.size * 2122979968);
@@ -3987,7 +3998,8 @@ bool type_id_eql(TypeId a, TypeId b) {
return a.data.pointer.child_type == b.data.pointer.child_type &&
a.data.pointer.is_const == b.data.pointer.is_const &&
a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
- a.data.pointer.bit_offset == b.data.pointer.bit_offset;
+ a.data.pointer.bit_offset == b.data.pointer.bit_offset &&
+ a.data.pointer.unaligned_bit_count == b.data.pointer.unaligned_bit_count;
case TypeTableEntryIdArray:
return a.data.array.child_type == b.data.array.child_type &&
a.data.array.size == b.data.array.size;