forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMemberAccessStrategy.h
200 lines (172 loc) · 5.86 KB
/
MemberAccessStrategy.h
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
//===--- MemberAccessStrategy.h - Abstract member access --------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines an interface for summarizing how to access a
// particular physical member.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_IRGEN_MEMBERACCESSSTRATEGY_H
#define SWIFT_IRGEN_MEMBERACCESSSTRATEGY_H
#include <string>
#include "IRGen.h"
namespace swift {
namespace irgen {
/// A class which describes how to access a particular physical member.
class MemberAccessStrategy {
public:
enum class OffsetKind : uint8_t {
/// A word-size offset that represents a number of bytes.
Bytes_Word,
};
enum class Kind : uint8_t {
/// The member has complex or overlapping storage. It cannot be
/// accessed simply by projecting out to a particular offset.
Complex,
/// The member is at an offset which is statically known.
DirectFixed,
/// The member is at an offset which must be loaded from global memory.
DirectGlobal,
/// The member is at an offset which must be loaded from a
/// statically-known offset within the type's metadata.
IndirectFixed,
/// The member is at an offset which must be loaded from an offset
/// within the type's metadata, which itself must be loaded from
/// a global symbol.
IndirectGlobal,
};
private:
union StorageType {
std::string GlobalSymbol;
Size FixedOffset;
StorageType() {}
~StorageType() {}
} Storage;
Kind TheKind;
OffsetKind DirectOffsetKind;
OffsetKind IndirectOffsetKind;
explicit MemberAccessStrategy(Kind kind) : TheKind(kind) {}
public:
// These are implementable, but there's no need.
MemberAccessStrategy(const MemberAccessStrategy &other) = delete;
MemberAccessStrategy &operator=(const MemberAccessStrategy &other) = delete;
MemberAccessStrategy(MemberAccessStrategy &&other)
: TheKind(other.TheKind) {
switch (TheKind) {
case Kind::Complex:
return;
case Kind::DirectFixed:
Storage.FixedOffset = other.Storage.FixedOffset;
return;
case Kind::DirectGlobal:
DirectOffsetKind = other.DirectOffsetKind;
::new (&Storage.GlobalSymbol)
std::string(std::move(other.Storage.GlobalSymbol));
return;
case Kind::IndirectFixed:
DirectOffsetKind = other.DirectOffsetKind;
Storage.FixedOffset = other.Storage.FixedOffset;
return;
case Kind::IndirectGlobal:
DirectOffsetKind = other.DirectOffsetKind;
IndirectOffsetKind = other.IndirectOffsetKind;
::new (&Storage.GlobalSymbol)
std::string(std::move(other.Storage.GlobalSymbol));
return;
}
llvm_unreachable("bad member access strategy kind");
}
MemberAccessStrategy &operator=(MemberAccessStrategy &&other) {
this->~MemberAccessStrategy();
::new (this) MemberAccessStrategy(std::move(other));
return *this;
}
~MemberAccessStrategy() {
switch (TheKind) {
case Kind::Complex:
case Kind::DirectFixed:
case Kind::IndirectFixed:
return;
case Kind::DirectGlobal:
case Kind::IndirectGlobal:
Storage.GlobalSymbol.~basic_string();
return;
}
llvm_unreachable("bad member access strategy kind");
}
static MemberAccessStrategy
getComplex() {
return MemberAccessStrategy(Kind::Complex);
}
static MemberAccessStrategy
getDirectFixed(Size directOffset) {
MemberAccessStrategy result(Kind::DirectFixed);
result.Storage.FixedOffset = directOffset;
return result;
}
static MemberAccessStrategy
getDirectGlobal(std::string &&directOffsetSymbol,
OffsetKind directOffsetKind) {
MemberAccessStrategy result(Kind::DirectGlobal);
::new(&result.Storage.GlobalSymbol)
std::string(std::move(directOffsetSymbol));
result.DirectOffsetKind = directOffsetKind;
return result;
}
static MemberAccessStrategy
getIndirectFixed(Size indirectOffset, OffsetKind directOffsetKind) {
MemberAccessStrategy result(Kind::IndirectFixed);
result.Storage.FixedOffset = indirectOffset;
result.DirectOffsetKind = directOffsetKind;
return result;
}
static MemberAccessStrategy
getIndirectGlobal(std::string &&indirectOffsetSymbol,
OffsetKind indirectOffsetKind,
OffsetKind directOffsetKind) {
MemberAccessStrategy result(Kind::DirectGlobal);
::new(&result.Storage.GlobalSymbol)
std::string(std::move(indirectOffsetSymbol));
result.IndirectOffsetKind = indirectOffsetKind;
result.DirectOffsetKind = directOffsetKind;
return result;
}
Kind getKind() const { return TheKind; }
OffsetKind getDirectOffsetKind() const {
assert(TheKind == Kind::DirectGlobal ||
TheKind == Kind::IndirectFixed ||
TheKind == Kind::IndirectGlobal);
return DirectOffsetKind;
}
OffsetKind getIndirectOffsetKind() const {
assert(TheKind == Kind::IndirectGlobal);
return IndirectOffsetKind;
}
Size getDirectOffset() const {
assert(TheKind == Kind::DirectFixed);
return Storage.FixedOffset;
}
Size getIndirectOffset() const {
assert(TheKind == Kind::IndirectFixed);
return Storage.FixedOffset;
}
const std::string &getDirectGlobalSymbol() const {
assert(TheKind == Kind::DirectGlobal);
return Storage.GlobalSymbol;
}
const std::string &getIndirectGlobalSymbol() const {
assert(TheKind == Kind::IndirectGlobal);
return Storage.GlobalSymbol;
}
};
} // end namespace irgen
} // end namespace swift
#endif