@@ -120,6 +120,27 @@ using llvm::StringRef;
120
120
#define syntax_assert_token_is (Tok, Kind, Text )
121
121
#endif
122
122
123
+ namespace {
124
+ // / If the \p Str is not allocated in \p Arena, copy it to \p Arena and adjust
125
+ // / \p Str to point to the string's copy in \p Arena.
126
+ void copyToArenaIfNecessary (
127
+ StringRef &Str, const swift::RC<swift::syntax::SyntaxArena> &Arena) {
128
+ if (Str.empty ()) {
129
+ // Empty strings can live wherever they want. Nothing to do.
130
+ return ;
131
+ }
132
+ if (Arena->containsPointer (Str.data ())) {
133
+ // String already in arena. Nothing to do.
134
+ return ;
135
+ }
136
+ // Copy string to arena
137
+ char *Data = (char *)Arena->Allocate (Str.size (), alignof (char *));
138
+ std::uninitialized_copy (Str.begin (), Str.end (), Data);
139
+ Str = StringRef (Data, Str.size ());
140
+ }
141
+ } // namespace
142
+ // end anonymous namespace
143
+
123
144
namespace swift {
124
145
namespace syntax {
125
146
@@ -223,7 +244,39 @@ class RawSyntax final
223
244
// / the caller needs to assure that the node ID has not been used yet.
224
245
RawSyntax (SyntaxKind Kind, ArrayRef<const RawSyntax *> Layout,
225
246
size_t TextLength, SourcePresence Presence,
226
- const RC<SyntaxArena> &Arena, llvm::Optional<SyntaxNodeId> NodeId);
247
+ const RC<SyntaxArena> &Arena, llvm::Optional<SyntaxNodeId> NodeId)
248
+ : Arena(Arena.get()),
249
+ Bits({{unsigned (TextLength), unsigned (Presence), false }}) {
250
+ assert (Arena && " RawSyntax nodes must always be allocated in an arena" );
251
+ assert (
252
+ Kind != SyntaxKind::Token &&
253
+ " 'token' syntax node must be constructed with dedicated constructor" );
254
+
255
+ size_t TotalSubNodeCount = 0 ;
256
+ for (auto Child : Layout) {
257
+ if (Child) {
258
+ TotalSubNodeCount += Child->getTotalSubNodeCount () + 1 ;
259
+ // If the child is stored in a different arena, it needs to stay alive
260
+ // as long as this node's arena is alive.
261
+ Arena->addChildArena (Child->Arena );
262
+ }
263
+ }
264
+
265
+ if (NodeId.hasValue ()) {
266
+ this ->NodeId = NodeId.getValue ();
267
+ NextFreeNodeId = std::max (this ->NodeId + 1 , NextFreeNodeId);
268
+ } else {
269
+ this ->NodeId = NextFreeNodeId++;
270
+ }
271
+ Bits.Layout .NumChildren = Layout.size ();
272
+ Bits.Layout .TotalSubNodeCount = TotalSubNodeCount;
273
+ Bits.Layout .Kind = unsigned (Kind);
274
+
275
+ // Initialize layout data.
276
+ std::uninitialized_copy (Layout.begin (), Layout.end (),
277
+ getTrailingObjects<const RawSyntax *>());
278
+ }
279
+
227
280
// / Constructor for creating token nodes
228
281
// / \c SyntaxArena, that arena must be passed as \p Arena to retain the node's
229
282
// / underlying storage.
@@ -232,7 +285,35 @@ class RawSyntax final
232
285
RawSyntax (tok TokKind, StringRef Text, size_t TextLength,
233
286
StringRef LeadingTrivia, StringRef TrailingTrivia,
234
287
SourcePresence Presence, const RC<SyntaxArena> &Arena,
235
- llvm::Optional<SyntaxNodeId> NodeId);
288
+ llvm::Optional<SyntaxNodeId> NodeId)
289
+ : Arena(Arena.get()),
290
+ Bits({{unsigned (TextLength), unsigned (Presence), true }}) {
291
+ assert (Arena && " RawSyntax nodes must always be allocated in an arena" );
292
+ copyToArenaIfNecessary (LeadingTrivia, Arena);
293
+ copyToArenaIfNecessary (Text, Arena);
294
+ copyToArenaIfNecessary (TrailingTrivia, Arena);
295
+
296
+ if (Presence == SourcePresence::Missing) {
297
+ assert (TextLength == 0 );
298
+ } else {
299
+ assert (TextLength ==
300
+ LeadingTrivia.size () + Text.size () + TrailingTrivia.size ());
301
+ }
302
+
303
+ if (NodeId.hasValue ()) {
304
+ this ->NodeId = NodeId.getValue ();
305
+ NextFreeNodeId = std::max (this ->NodeId + 1 , NextFreeNodeId);
306
+ } else {
307
+ this ->NodeId = NextFreeNodeId++;
308
+ }
309
+ Bits.Token .LeadingTrivia = LeadingTrivia.data ();
310
+ Bits.Token .TokenText = Text.data ();
311
+ Bits.Token .TrailingTrivia = TrailingTrivia.data ();
312
+ Bits.Token .LeadingTriviaLength = LeadingTrivia.size ();
313
+ Bits.Token .TokenLength = Text.size ();
314
+ Bits.Token .TrailingTriviaLength = TrailingTrivia.size ();
315
+ Bits.Token .TokenKind = unsigned (TokKind);
316
+ }
236
317
237
318
// / Compute the node's text length by summing up the length of its childern
238
319
size_t computeTextLength () {
@@ -254,7 +335,13 @@ class RawSyntax final
254
335
static const RawSyntax *
255
336
make (SyntaxKind Kind, ArrayRef<const RawSyntax *> Layout, size_t TextLength,
256
337
SourcePresence Presence, const RC<SyntaxArena> &Arena,
257
- llvm::Optional<SyntaxNodeId> NodeId = llvm::None);
338
+ llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
339
+ assert (Arena && " RawSyntax nodes must always be allocated in an arena" );
340
+ auto size = totalSizeToAlloc<const RawSyntax *>(Layout.size ());
341
+ void *data = Arena->Allocate (size, alignof (RawSyntax));
342
+ return new (data)
343
+ RawSyntax (Kind, Layout, TextLength, Presence, Arena, NodeId);
344
+ }
258
345
259
346
static const RawSyntax *
260
347
makeAndCalcLength (SyntaxKind Kind, ArrayRef<const RawSyntax *> Layout,
@@ -274,7 +361,13 @@ class RawSyntax final
274
361
make (tok TokKind, StringRef Text, size_t TextLength, StringRef LeadingTrivia,
275
362
StringRef TrailingTrivia, SourcePresence Presence,
276
363
const RC<SyntaxArena> &Arena,
277
- llvm::Optional<SyntaxNodeId> NodeId = llvm::None);
364
+ llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
365
+ assert (Arena && " RawSyntax nodes must always be allocated in an arena" );
366
+ auto size = totalSizeToAlloc<const RawSyntax *>(0 );
367
+ void *data = Arena->Allocate (size, alignof (RawSyntax));
368
+ return new (data) RawSyntax (TokKind, Text, TextLength, LeadingTrivia,
369
+ TrailingTrivia, Presence, Arena, NodeId);
370
+ }
278
371
279
372
// / Make a raw "token" syntax node that was allocated in \p Arena.
280
373
static const RawSyntax *
0 commit comments