-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstorage.cpp
More file actions
95 lines (77 loc) · 2.32 KB
/
storage.cpp
File metadata and controls
95 lines (77 loc) · 2.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <cassert>
#include "storage.h"
namespace {
unsigned pad(unsigned offset, unsigned align) {
// alignments must be powers of 2
assert((align & (align - 1U)) == 0U);
// Determine by how many bytes (if any) the offset is misaligned
unsigned misalignment = offset & (align - 1U);
// Determine how many bytes of padding should be added to the offset
// to restore correct alignment
assert(misalignment < align);
return misalignment == 0U ? 0U : (align - misalignment);
}
}
StorageCalculator::StorageCalculator(Mode mode, unsigned start_offset)
: m_mode(mode)
, m_size(0U)
, m_align(start_offset)
, m_finished(false) {
assert(mode == STRUCT || mode == UNION);
}
StorageCalculator::~StorageCalculator() {
}
unsigned StorageCalculator::add_field(const std::shared_ptr<Type> &type) {
unsigned size = type->get_storage_size();
unsigned align = type->get_alignment();
// Keep track of largest alignment requirement, because
// that will become the overall struct or union's
// required alignment
if (align > m_align) {
m_align = align;
}
unsigned field_offset;
if (m_mode == STRUCT) {
// Determine amount of padding needed
unsigned padding = pad(m_size, align);
m_size += padding;
// Now we know the offset of this field
field_offset = m_size;
// Next offset will, at a minimum, need to place the next
// field beyond the storage for this one
m_size += size;
} else {
// For a union, all field offsets are 0, and the union's
// overall size is just the size of the largest member
field_offset = 0U;
if (size > m_size) {
m_size = size;
}
}
return field_offset;
}
void StorageCalculator::finish() {
if (m_align == 0U) {
// special case: if the struct or union has no fields,
// its size is 0 and its alignment is 1
assert(m_size == 0U);
m_align = 1U;
} else {
if (m_mode == STRUCT) {
// pad so that the overall size of the struct is a multiple
// of the maximum field alignment
m_size += pad(m_size, m_align);
}
}
assert((m_align & (m_align - 1U)) == 0U);
assert((m_size & (m_align - 1U)) == 0U);
m_finished = true;
}
unsigned StorageCalculator::get_size() const {
assert(m_finished);
return m_size;
}
unsigned StorageCalculator::get_align() const {
assert(m_finished);
return m_align;
}