Skip to content

[libSyntax] Require RawSyntax to always live inside a SyntaxArena #35648

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 19 additions & 52 deletions include/swift/Syntax/RawSyntax.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,15 +262,11 @@ class RawSyntax final
int NewRefCount = RefCount.fetch_sub(1, std::memory_order_acq_rel) - 1;
assert(NewRefCount >= 0 && "Reference count was already zero.");
if (NewRefCount == 0) {
if (Arena) {
// The node was allocated inside a SyntaxArena and thus doesn't own its
// own memory region. Hence we cannot free it. It will be deleted once
// the last RawSyntax node allocated with it will release its reference
// to the arena.
this->~RawSyntax();
} else {
delete this;
}
// The node was allocated inside a SyntaxArena and thus doesn't own its
// own memory region. Hence we cannot free it. It will be deleted once
// the last RawSyntax node allocated with it will release its reference
// to the arena.
this->~RawSyntax();
}
}

Expand All @@ -280,18 +276,13 @@ class RawSyntax final
/// Make a raw "layout" syntax node.
static RC<RawSyntax> make(SyntaxKind Kind, ArrayRef<RC<RawSyntax>> Layout,
size_t TextLength, SourcePresence Presence,
const RC<SyntaxArena> &Arena,
const RC<SyntaxArena> &Arena = SyntaxArena::make(),
llvm::Optional<SyntaxNodeId> NodeId = llvm::None);

static RC<RawSyntax> make(SyntaxKind Kind, ArrayRef<RC<RawSyntax>> Layout,
size_t TextLength, SourcePresence Presence,
llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
return make(Kind, Layout, TextLength, Presence, /*Arena=*/nullptr, NodeId);
}

static RC<RawSyntax>
makeAndCalcLength(SyntaxKind Kind, ArrayRef<RC<RawSyntax>> Layout,
SourcePresence Presence, const RC<SyntaxArena> &Arena,
SourcePresence Presence,
const RC<SyntaxArena> &Arena = SyntaxArena::make(),
llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
size_t TextLength = 0;
for (auto Child : Layout) {
Expand All @@ -302,37 +293,20 @@ class RawSyntax final
return make(Kind, Layout, TextLength, Presence, Arena, NodeId);
}

static RC<RawSyntax>
makeAndCalcLength(SyntaxKind Kind, ArrayRef<RC<RawSyntax>> Layout,
SourcePresence Presence,
llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
return makeAndCalcLength(Kind, Layout, Presence, /*Arena=*/nullptr, NodeId);
}

/// Make a raw "token" syntax node.
static RC<RawSyntax> make(tok TokKind, OwnedString Text, size_t TextLength,
ArrayRef<TriviaPiece> LeadingTrivia,
ArrayRef<TriviaPiece> TrailingTrivia,
SourcePresence Presence,
const RC<SyntaxArena> &Arena,
const RC<SyntaxArena> &Arena = SyntaxArena::make(),
llvm::Optional<SyntaxNodeId> NodeId = llvm::None);

static RC<RawSyntax> make(tok TokKind, OwnedString Text, size_t TextLength,
ArrayRef<TriviaPiece> LeadingTrivia,
ArrayRef<TriviaPiece> TrailingTrivia,
SourcePresence Presence,
llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
return make(TokKind, Text, TextLength, LeadingTrivia, TrailingTrivia,
Presence, /*Arena=*/nullptr, NodeId);
}

/// Make a raw "token" syntax node that was allocated in \p Arena.
static RC<RawSyntax>
makeAndCalcLength(tok TokKind, OwnedString Text,
ArrayRef<TriviaPiece> LeadingTrivia,
ArrayRef<TriviaPiece> TrailingTrivia,
SourcePresence Presence, const RC<SyntaxArena> &Arena,
llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
static RC<RawSyntax> makeAndCalcLength(
tok TokKind, OwnedString Text, ArrayRef<TriviaPiece> LeadingTrivia,
ArrayRef<TriviaPiece> TrailingTrivia, SourcePresence Presence,
const RC<SyntaxArena> &Arena = SyntaxArena::make(),
llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
size_t TextLength = 0;
if (Presence != SourcePresence::Missing) {
for (auto Trivia : LeadingTrivia) {
Expand All @@ -347,23 +321,16 @@ class RawSyntax final
Presence, Arena, NodeId);
}

static RC<RawSyntax> makeAndCalcLength(
tok TokKind, OwnedString Text, ArrayRef<TriviaPiece> LeadingTrivia,
ArrayRef<TriviaPiece> TrailingTrivia, SourcePresence Presence,
llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
return makeAndCalcLength(TokKind, Text, LeadingTrivia, TrailingTrivia,
Presence, /*Arena=*/nullptr, NodeId);
}

/// Make a missing raw "layout" syntax node.
static RC<RawSyntax> missing(SyntaxKind Kind,
RC<SyntaxArena> Arena = nullptr) {
static RC<RawSyntax>
missing(SyntaxKind Kind, const RC<SyntaxArena> &Arena = SyntaxArena::make()) {
return make(Kind, {}, /*TextLength=*/0, SourcePresence::Missing, Arena);
}

/// Make a missing raw "token" syntax node.
static RC<RawSyntax> missing(tok TokKind, OwnedString Text,
RC<SyntaxArena> Arena = nullptr) {
static RC<RawSyntax>
missing(tok TokKind, OwnedString Text,
const RC<SyntaxArena> &Arena = SyntaxArena::make()) {
return make(TokKind, Text, /*TextLength=*/0, {}, {},
SourcePresence::Missing, Arena);
}
Expand Down
6 changes: 3 additions & 3 deletions include/swift/Syntax/Serialization/SyntaxDeserialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ template <> struct MappingTraits<swift::RC<swift::RawSyntax>> {
unsigned nodeId = std::atoi(nodeIdString.data());
value = swift::RawSyntax::makeAndCalcLength(
tokenKind, swift::OwnedString::makeRefCounted(text), leadingTrivia,
trailingTrivia, presence, /*Arena=*/nullptr, nodeId);
trailingTrivia, presence, swift::SyntaxArena::make(), nodeId);
} else {
swift::SyntaxKind kind;
in.mapRequired("kind", kind);
Expand All @@ -178,8 +178,8 @@ template <> struct MappingTraits<swift::RC<swift::RawSyntax>> {
StringRef nodeIdString;
in.mapRequired("id", nodeIdString);
unsigned nodeId = std::atoi(nodeIdString.data());
value = swift::RawSyntax::makeAndCalcLength(kind, layout, presence,
/*Arena=*/nullptr, nodeId);
value = swift::RawSyntax::makeAndCalcLength(
kind, layout, presence, swift::SyntaxArena::make(), nodeId);
}
}
};
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Syntax/SyntaxArena.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef SWIFT_SYNTAX_SYNTAXARENA_H
#define SWIFT_SYNTAX_SYNTAXARENA_H

#include "swift/Syntax/References.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/Allocator.h"

Expand All @@ -33,6 +34,8 @@ class SyntaxArena : public llvm::ThreadSafeRefCountedBase<SyntaxArena> {
public:
SyntaxArena() {}

static RC<SyntaxArena> make() { return RC<SyntaxArena>(new SyntaxArena()); }

llvm::BumpPtrAllocator &getAllocator() { return Allocator; }
void *Allocate(size_t size, size_t alignment) {
return Allocator.Allocate(size, alignment);
Expand Down
6 changes: 3 additions & 3 deletions include/swift/Syntax/SyntaxBuilders.h.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ class SyntaxArena;
% if node.is_buildable():
% child_count = len(node.children)
class ${node.name}Builder {
RC<SyntaxArena> Arena = nullptr;
RC<SyntaxArena> Arena;
RC<RawSyntax> Layout[${child_count}] = {
% for child in node.children:
nullptr,
% end
};

public:
${node.name}Builder() = default;
${node.name}Builder(const RC<SyntaxArena> &Arena) : Arena(Arena) {}
${node.name}Builder(const RC<SyntaxArena> &Arena = SyntaxArena::make())
: Arena(Arena) {}

% for child in node.children:
${node.name}Builder &use${child.name}(${child.type_name} ${child.name});
Expand Down
90 changes: 52 additions & 38 deletions include/swift/Syntax/SyntaxFactory.h.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,25 @@ class SyntaxArena;
struct SyntaxFactory {
/// Make any kind of token.
static TokenSyntax makeToken(tok Kind,
OwnedString Text, const Trivia &LeadingTrivia,
const Trivia &TrailingTrivia,
SourcePresence Presence,
RC<SyntaxArena> Arena = nullptr);
OwnedString Text, const Trivia &LeadingTrivia,
const Trivia &TrailingTrivia, SourcePresence Presence,
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

/// Collect a list of tokens into a piece of "unknown" syntax.
static UnknownSyntax makeUnknownSyntax(llvm::ArrayRef<TokenSyntax> Tokens,
RC<SyntaxArena> Arena = nullptr);
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

static Optional<Syntax> createSyntax(SyntaxKind Kind,
llvm::ArrayRef<Syntax> Elements,
RC<SyntaxArena> Arena = nullptr);
llvm::ArrayRef<Syntax> Elements,
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

static RC<RawSyntax> createRaw(SyntaxKind Kind,
llvm::ArrayRef<RC<RawSyntax>> Elements,
RC<SyntaxArena> Arena = nullptr);
llvm::ArrayRef<RC<RawSyntax>> Elements,
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

/// Count the number of children for a given syntax node kind,
/// returning a pair of mininum and maximum count of children. The gap
Expand All @@ -83,90 +86,101 @@ struct SyntaxFactory {
% end
% child_params = ', '.join(child_params)
static ${node.name} make${node.syntax_kind}(${child_params},
RC<SyntaxArena> Arena = nullptr);
const RC<SyntaxArena> &Arena = SyntaxArena::make());
% elif node.is_syntax_collection():
static ${node.name} make${node.syntax_kind}(
const std::vector<${node.collection_element_type}> &elts,
RC<SyntaxArena> Arena = nullptr);
const RC<SyntaxArena> &Arena = SyntaxArena::make());
% end

static ${node.name} makeBlank${node.syntax_kind}(RC<SyntaxArena> Arena = nullptr);
static ${node.name} makeBlank${node.syntax_kind}(
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);
% end

% for token in SYNTAX_TOKENS:
% if token.is_keyword:
static TokenSyntax make${token.name}Keyword(const Trivia &LeadingTrivia,
const Trivia &TrailingTrivia,
RC<SyntaxArena> Arena = nullptr);
const Trivia &TrailingTrivia,
const RC<SyntaxArena> &Arena = SyntaxArena::make());
% elif token.text:
static TokenSyntax make${token.name}Token(const Trivia &LeadingTrivia,
const Trivia &TrailingTrivia,
RC<SyntaxArena> Arena = nullptr);
const Trivia &TrailingTrivia,
const RC<SyntaxArena> &Arena = SyntaxArena::make());
% else:
static TokenSyntax make${token.name}(OwnedString Text,
const Trivia &LeadingTrivia,
const Trivia &TrailingTrivia,
RC<SyntaxArena> Arena = nullptr);
const Trivia &LeadingTrivia, const Trivia &TrailingTrivia,
const RC<SyntaxArena> &Arena = SyntaxArena::make());
% end
% end

#pragma mark - Convenience APIs

static TupleTypeSyntax makeVoidTupleType(RC<SyntaxArena> Arena = nullptr);
static TupleTypeSyntax makeVoidTupleType(
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

/// Creates an labelled TupleTypeElementSyntax with the provided label,
/// colon, type and optional trailing comma.
static TupleTypeElementSyntax makeTupleTypeElement(
llvm::Optional<TokenSyntax> Label,
llvm::Optional<TokenSyntax> Colon, TypeSyntax Type,
llvm::Optional<TokenSyntax> TrailingComma = llvm::None,
RC<SyntaxArena> Arena = nullptr);
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

/// Creates an unlabelled TupleTypeElementSyntax with the provided type and
/// optional trailing comma.
static TupleTypeElementSyntax
makeTupleTypeElement(TypeSyntax Type,
llvm::Optional<TokenSyntax> TrailingComma = llvm::None,
RC<SyntaxArena> Arena = nullptr);
llvm::Optional<TokenSyntax> TrailingComma = llvm::None,
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

/// Creates a TypeIdentifierSyntax with the provided name and leading/trailing
/// trivia.
static TypeSyntax makeTypeIdentifier(OwnedString TypeName,
const Trivia &LeadingTrivia = {},
const Trivia &TrailingTrivia = {},
RC<SyntaxArena> Arena = nullptr);
const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {},
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

/// Creates a GenericParameterSyntax with no inheritance clause and an
/// optional trailing comma.
static GenericParameterSyntax
makeGenericParameter(TokenSyntax Name,
llvm::Optional<TokenSyntax> TrailingComma,
RC<SyntaxArena> Arena = nullptr);
llvm::Optional<TokenSyntax> TrailingComma,
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

/// Creates a TypeIdentifierSyntax for the `Any` type.
static TypeSyntax makeAnyTypeIdentifier(const Trivia &LeadingTrivia = {},
const Trivia &TrailingTrivia = {},
RC<SyntaxArena> Arena = nullptr);
const Trivia &TrailingTrivia = {},
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

/// Creates a TypeIdentifierSyntax for the `Self` type.
static TypeSyntax makeSelfTypeIdentifier(const Trivia &LeadingTrivia = {},
const Trivia &TrailingTrivia = {},
RC<SyntaxArena> Arena = nullptr);
const Trivia &TrailingTrivia = {},
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

/// Creates a TokenSyntax for the `Type` identifier.
static TokenSyntax makeTypeToken(const Trivia &LeadingTrivia = {},
const Trivia &TrailingTrivia = {},
RC<SyntaxArena> Arena = nullptr);
const Trivia &TrailingTrivia = {},
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

/// Creates a TokenSyntax for the `Protocol` identifier.
static TokenSyntax makeProtocolToken(const Trivia &LeadingTrivia = {},
const Trivia &TrailingTrivia = {},
RC<SyntaxArena> Arena = nullptr);
const Trivia &TrailingTrivia = {},
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

/// Creates an `==` operator token.
static TokenSyntax makeEqualityOperator(const Trivia &LeadingTrivia = {},
const Trivia &TrailingTrivia = {},
RC<SyntaxArena> Arena = nullptr);
const Trivia &TrailingTrivia = {},
const RC<SyntaxArena> &Arena = SyntaxArena::make()
);

/// Whether a raw node kind `MemberKind` can serve as a member in a syntax
/// collection of the given syntax collection kind.
Expand Down
Loading