Skip to content

Commit 733915f

Browse files
authored
Merge pull request swiftlang#9033 from rjmccall/rvalue-pointer-conversions
2 parents c719818 + 338825e commit 733915f

File tree

11 files changed

+1197
-229
lines changed

11 files changed

+1197
-229
lines changed

include/swift/Basic/ExternalUnion.h

Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
//===- ExternalUnion.h - A union with an external discriminator -*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines the ExternalUnion class, which allows clients to
14+
// conveniently define unions of possibly non-trivial types whose
15+
// discriminator will be provided externally.
16+
//
17+
// It's the client's responsibility to call the appropriate
18+
// "special members" within its own special members.
19+
//
20+
//===----------------------------------------------------------------------===//
21+
22+
#ifndef SWIFT_BASIC_EXTERNALUNION_H
23+
#define SWIFT_BASIC_EXTERNALUNION_H
24+
25+
#include "llvm/Support/Compiler.h"
26+
#include <type_traits>
27+
#include <utility>
28+
#include <assert.h>
29+
30+
namespace swift {
31+
32+
template <size_t... Values>
33+
struct static_max;
34+
35+
template <size_t Value>
36+
struct static_max<Value> {
37+
static const size_t value = Value;
38+
};
39+
40+
template <size_t Head, size_t... Tail>
41+
struct static_max<Head, Tail...> {
42+
static const size_t value =
43+
(Head > static_max<Tail...>::value ? Head : static_max<Tail...>::value);
44+
};
45+
46+
template <class T, class... Members>
47+
struct indexOf;
48+
49+
template <class T>
50+
struct indexOf<T> {
51+
constexpr static const int value = -1;
52+
};
53+
54+
template <class T, class U, class... Members>
55+
struct indexOf<T, U, Members...> {
56+
private:
57+
constexpr static const int indexInTail = indexOf<T, Members...>::value;
58+
public:
59+
constexpr static const int value =
60+
(std::is_same<T, U>::value ? 0 :
61+
indexInTail != -1 ? indexInTail + 1 : -1);
62+
};
63+
64+
template <class... Members>
65+
struct SpecialMembers;
66+
67+
/// An external union whose discriminator is just a position in
68+
/// the template arguments.
69+
///
70+
/// The external union itself is a trivial type, and it is the
71+
/// responsibility of the client to call the "special member functions"
72+
/// at the appropriate time.
73+
template <class... Members>
74+
class BasicExternalUnion {
75+
/// The value storage.
76+
LLVM_ALIGNAS(static_max<alignof(Members)...>::value)
77+
char Storage[static_max<sizeof(Members)...>::value];
78+
79+
public:
80+
/// Construct a union member in-place.
81+
template <class T, class... Args>
82+
T &emplaceWithoutIndex(int index, Args &&... args) {
83+
constexpr int typeIndex = indexOf<T, Members...>::value;
84+
static_assert(typeIndex != -1, "type not in union");
85+
86+
return *(::new ((void*) &Storage) T(std::forward<Args>(args)...));
87+
}
88+
89+
/// Construct a union member in-place.
90+
template <class T, class... Args>
91+
T &emplace(int index, Args &&... args) {
92+
constexpr int typeIndex = indexOf<T, Members...>::value;
93+
static_assert(typeIndex != -1, "type not in union");
94+
assert(index == typeIndex && "current kind is wrong for value");
95+
96+
return *(::new ((void*) &Storage) T(std::forward<Args>(args)...));
97+
}
98+
99+
/// Return a reference to a union member.
100+
template <class T>
101+
T &getWithoutIndex() {
102+
constexpr int typeIndex = indexOf<T, Members...>::value;
103+
static_assert(typeIndex != -1, "type not in union");
104+
105+
return reinterpret_cast<T &>(Storage);
106+
}
107+
108+
/// Return a reference to a union member.
109+
template <class T>
110+
const T &getWithoutIndex() const {
111+
constexpr int typeIndex = indexOf<T, Members...>::value;
112+
static_assert(typeIndex != -1, "type not in union");
113+
114+
return reinterpret_cast<const T &>(Storage);
115+
}
116+
117+
/// Return a reference to a union member, asserting that the current
118+
/// kind matches the type being extracted.
119+
template <class T>
120+
T &get(int index) {
121+
constexpr int typeIndex = indexOf<T, Members...>::value;
122+
static_assert(typeIndex != -1, "type not in union");
123+
assert(index == typeIndex && "current kind is wrong for access");
124+
125+
return reinterpret_cast<T &>(Storage);
126+
}
127+
128+
/// Return a reference to a union member, asserting that the current
129+
/// kind matches the type being extracted.
130+
template <class T>
131+
const T &get(int index) const {
132+
constexpr int typeIndex = indexOf<T, Members...>::value;
133+
static_assert(typeIndex != -1, "type not in union");
134+
assert(index == typeIndex && "current kind is wrong for access");
135+
136+
return reinterpret_cast<const T &>(Storage);
137+
}
138+
139+
/// Copy-construct the union from another union.
140+
void copyConstruct(int index, const BasicExternalUnion &other) {
141+
if (index != -1) {
142+
SpecialMembers<Members...>::copyConstruct(Storage, index, other.Storage);
143+
}
144+
}
145+
146+
/// Move-construct the union from another union.
147+
void moveConstruct(int index, BasicExternalUnion &&other) {
148+
if (index != -1) {
149+
SpecialMembers<Members...>::moveConstruct(Storage, index, other.Storage);
150+
}
151+
}
152+
153+
/// Copy-assign the union from another union.
154+
void copyAssign(int thisIndex, int otherIndex,
155+
const BasicExternalUnion &other) {
156+
if (this == &other) {
157+
// do nothing
158+
} else if (thisIndex == otherIndex) {
159+
if (thisIndex != -1) {
160+
SpecialMembers<Members...>::copyAssignSame(thisIndex, Storage,
161+
other.Storage);
162+
}
163+
} else {
164+
destruct(thisIndex, Storage);
165+
copyConstruct(otherIndex, other);
166+
}
167+
}
168+
169+
/// Move-assign the union from another union.
170+
void moveAssign(int thisIndex, int otherIndex,
171+
BasicExternalUnion &&other) {
172+
assert(this != &other && "move-constructing value into itself?");
173+
174+
if (thisIndex == otherIndex) {
175+
if (thisIndex != -1) {
176+
SpecialMembers<Members...>::moveAssignSame(thisIndex, Storage,
177+
other.Storage);
178+
}
179+
} else {
180+
destruct(thisIndex);
181+
moveConstruct(otherIndex, std::move(other));
182+
}
183+
}
184+
185+
/// Destroy the union from another union.
186+
void destruct(int index) {
187+
if (index != -1) {
188+
SpecialMembers<Members...>::destruct(index, Storage);
189+
}
190+
}
191+
};
192+
193+
/// An external union whose membership is determined by a kind type
194+
/// whose members are not necessarily 1-1 with the members of the union.
195+
///
196+
/// Clients must provide a function which translates the kind type
197+
/// into an index into the union's Members list, or -1 for kind values
198+
/// which do not require data in the union.
199+
template <class Kind, int (&GetIndexForKind)(Kind), class... Members>
200+
class ExternalUnion {
201+
BasicExternalUnion<Members...> Union;
202+
203+
public:
204+
/// Construct a union member in-place.
205+
template <class T, class... Args>
206+
T &emplace(Kind kind, Args &&... args) {
207+
#ifndef NDEBUG
208+
return Union.template emplace<T>(GetIndexForKind(kind),
209+
std::forward<Args>(args)...);
210+
#else
211+
return Union.template emplaceWithoutIndex<T>(std::forward<Args>(args)...);
212+
#endif
213+
}
214+
215+
/// Return a reference to a union member, asserting that the current
216+
/// kind is right.
217+
template <class T>
218+
T &get(Kind kind) {
219+
#ifndef NDEBUG
220+
return Union.template get<T>(GetIndexForKind(kind));
221+
#else
222+
return Union.template getWithoutIndex<T>();
223+
#endif
224+
}
225+
226+
/// Return a reference to a union member, asserting that the current
227+
/// kind is right.
228+
template <class T>
229+
const T &get(Kind kind) const {
230+
#ifndef NDEBUG
231+
return Union.template get<T>(GetIndexForKind(kind));
232+
#else
233+
return Union.template getWithoutIndex<T>();
234+
#endif
235+
}
236+
237+
/// Copy-construct the union from another union.
238+
void copyConstruct(Kind kind, const ExternalUnion &other) {
239+
Union.copyConstruct(GetIndexForKind(kind), other.Union);
240+
}
241+
242+
/// Move-construct the union from another union.
243+
void moveConstruct(Kind kind, ExternalUnion &&other) {
244+
Union.moveConstruct(GetIndexForKind(kind), std::move(other.Union));
245+
}
246+
247+
/// Copy-assign the union from another union.
248+
void copyAssign(Kind thisKind, Kind otherKind, const ExternalUnion &other) {
249+
Union.copyAssign(GetIndexForKind(thisKind), GetIndexForKind(otherKind),
250+
other.Union);
251+
}
252+
253+
/// Move-assign the union from another union.
254+
void moveAssign(Kind thisKind, Kind otherKind, ExternalUnion &&other) {
255+
Union.moveAssign(GetIndexForKind(thisKind), GetIndexForKind(otherKind),
256+
std::move(other.Union));
257+
}
258+
259+
/// Destroy the union from another union.
260+
void destruct(Kind kind) {
261+
Union.destruct(GetIndexForKind(kind));
262+
}
263+
};
264+
265+
/// A helper class for defining special members.
266+
template <>
267+
struct SpecialMembers<> {
268+
LLVM_ATTRIBUTE_ALWAYS_INLINE
269+
static void copyConstruct(void *self, int index, const void *other) {
270+
llvm_unreachable("bad index");
271+
}
272+
273+
LLVM_ATTRIBUTE_ALWAYS_INLINE
274+
static void moveConstruct(void *self, int index, void *other) {
275+
llvm_unreachable("bad index");
276+
}
277+
278+
LLVM_ATTRIBUTE_ALWAYS_INLINE
279+
static void copyAssignSame(int index, void *self, const void *other) {
280+
llvm_unreachable("bad index");
281+
}
282+
283+
LLVM_ATTRIBUTE_ALWAYS_INLINE
284+
static void moveAssignSame(int index, void *self, void *other) {
285+
llvm_unreachable("bad index");
286+
}
287+
288+
LLVM_ATTRIBUTE_ALWAYS_INLINE
289+
static void destruct(int index, void *self) {
290+
llvm_unreachable("bad index");
291+
}
292+
};
293+
294+
template <class T, class... Others>
295+
struct SpecialMembers<T, Others...> {
296+
LLVM_ATTRIBUTE_ALWAYS_INLINE
297+
static void copyConstruct(void *self, int index, const void *other) {
298+
if (index == 0) {
299+
::new (self) T(*static_cast<const T *>(other));
300+
} else {
301+
SpecialMembers<Others...>::copyConstruct(self, index - 1, other);
302+
}
303+
}
304+
305+
LLVM_ATTRIBUTE_ALWAYS_INLINE
306+
static void moveConstruct(void *self, int index, void *other) {
307+
if (index == 0) {
308+
::new (self) T(std::move(*static_cast<T *>(other)));
309+
} else {
310+
SpecialMembers<Others...>::moveConstruct(self, index - 1, other);
311+
}
312+
}
313+
314+
LLVM_ATTRIBUTE_ALWAYS_INLINE
315+
static void copyAssignSame(int index, void *self, const void *other) {
316+
if (index == 0) {
317+
*static_cast<T*>(self) = *static_cast<const T *>(other);
318+
} else {
319+
SpecialMembers<Others...>::copyAssignSame(index - 1, self, other);
320+
}
321+
}
322+
323+
LLVM_ATTRIBUTE_ALWAYS_INLINE
324+
static void moveAssignSame(int index, void *self, void *other) {
325+
if (index == 0) {
326+
*static_cast<T*>(self) = std::move(*static_cast<T *>(other));
327+
} else {
328+
SpecialMembers<Others...>::moveAssignSame(index - 1, self, other);
329+
}
330+
}
331+
332+
LLVM_ATTRIBUTE_ALWAYS_INLINE
333+
static void destruct(int index, void *self) {
334+
if (index == 0) {
335+
static_cast<T*>(self)->T::~T();
336+
} else {
337+
SpecialMembers<Others...>::destruct(index - 1, self);
338+
}
339+
}
340+
};
341+
342+
} // end namespace swift
343+
344+
#endif // SWIFT_BASIC_CLUSTEREDBITVECTOR_H

include/swift/SIL/SILType.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,9 @@ class SILType {
521521
/// Get the builtin word type as a SILType;
522522
static SILType getBuiltinWordType(const ASTContext &C);
523523

524+
/// Given a value type, return an optional type wrapping it.
525+
static SILType getOptionalType(SILType valueType);
526+
524527
/// Get the standard exception type.
525528
static SILType getExceptionType(const ASTContext &C);
526529

0 commit comments

Comments
 (0)