Skip to content
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
3 changes: 3 additions & 0 deletions Sources/SwiftSyntax/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,6 @@ add_swift_syntax_library(SwiftSyntax
generated/syntaxNodes/SyntaxNodesQRS.swift
generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift
)

target_link_swift_syntax_libraries(SwiftSyntax PRIVATE
_SwiftSyntaxCShims)
32 changes: 12 additions & 20 deletions Sources/SwiftSyntax/SyntaxArena.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,10 @@
//
//===----------------------------------------------------------------------===//

#if SWIFT_SYNTAX_BUILD_USING_CMAKE
// The CMake bulid of swift-syntax does not build the _AtomicBool module because swift-syntax's CMake build is
// Swift-only. Fake an `AtomicBool` type that is not actually atomic. This should be acceptable for the following
// reasons:
// - `AtomicBool` is only used for the `hasParent` assertion, so release compilers don't rely on it
// - The compiler is single-threaded so it it is safe from race conditions on `AtomicBool`.
fileprivate struct AtomicBool {
var value: Bool

init(initialValue: Bool) {
self.value = initialValue
}
}
#if swift(>=6.0)
private import _SwiftSyntaxCShims
#else
import _SwiftSyntaxCShims
@_implementationOnly import _SwiftSyntaxCShims
#endif

/// A syntax arena owns the memory for all syntax nodes within it.
Expand Down Expand Up @@ -69,7 +58,7 @@ public class SyntaxArena {
///
/// - Important: This is only intended to be used for assertions to catch
/// retain cycles in syntax arenas.
fileprivate var hasParent: AtomicBool
fileprivate let hasParent: UnsafeMutablePointer<AtomicBool>
#endif

/// Construct a new ``SyntaxArena`` in which syntax nodes can be allocated.
Expand All @@ -81,14 +70,17 @@ public class SyntaxArena {
self.allocator = BumpPtrAllocator(initialSlabSize: slabSize)
self.childRefs = []
#if DEBUG || SWIFTSYNTAX_ENABLE_ASSERTIONS
self.hasParent = AtomicBool(initialValue: false)
self.hasParent = swiftsyntax_atomic_bool_create(false)
#endif
}

deinit {
for child in childRefs {
child.release()
}
#if DEBUG || SWIFTSYNTAX_ENABLE_ASSERTIONS
swiftsyntax_atomic_bool_destroy(self.hasParent)
#endif
}

/// Allocates a buffer of `RawSyntax?` with the given count, then returns the
Expand Down Expand Up @@ -158,7 +150,7 @@ public class SyntaxArena {

#if DEBUG || SWIFTSYNTAX_ENABLE_ASSERTIONS
precondition(
!self.hasParent.value,
!swiftsyntax_atomic_bool_get(self.hasParent),
"an arena can't have a new child once it's owned by other arenas"
)
#endif
Expand Down Expand Up @@ -300,14 +292,14 @@ struct SyntaxArenaRef: Hashable, @unchecked Sendable {
}

#if DEBUG || SWIFTSYNTAX_ENABLE_ASSERTIONS
/// Accessor for ther underlying's `SyntaxArena.hasParent`
/// Accessor for the underlying's `SyntaxArena.hasParent`
var hasParent: Bool {
value.hasParent.value
swiftsyntax_atomic_bool_get(value.hasParent)
}

/// Sets the `SyntaxArena.hasParent` on the referenced arena.
func setHasParent(_ newValue: Bool) {
value.hasParent.value = newValue
swiftsyntax_atomic_bool_set(value.hasParent, newValue)
}
#endif

Expand Down
18 changes: 10 additions & 8 deletions Sources/_SwiftSyntaxCShims/include/AtomicBool.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,28 @@
#define SWIFTSYNTAX_ATOMICBOOL_H

#include <stdbool.h>
#include <stdlib.h>

typedef struct {
_Atomic(bool) value;
} AtomicBool;

__attribute__((swift_name("AtomicBool.init(initialValue:)")))
static inline AtomicBool atomic_bool_create(bool initialValue) {
AtomicBool atomic;
atomic.value = initialValue;
static inline AtomicBool *_Nonnull swiftsyntax_atomic_bool_create(bool initialValue) {
AtomicBool *atomic = malloc(sizeof(AtomicBool));
atomic->value = initialValue;
return atomic;
}

__attribute__((swift_name("getter:AtomicBool.value(self:)")))
static inline bool atomic_bool_get(AtomicBool *atomic) {
static inline bool swiftsyntax_atomic_bool_get(AtomicBool *_Nonnull atomic) {
return atomic->value;
}

__attribute__((swift_name("setter:AtomicBool.value(self:_:)")))
static inline void atomic_bool_set(AtomicBool *atomic, bool newValue) {
static inline void swiftsyntax_atomic_bool_set(AtomicBool *_Nonnull atomic, bool newValue) {
atomic->value = newValue;
}

static inline void swiftsyntax_atomic_bool_destroy(AtomicBool *_Nonnull atomic) {
free(atomic);
}

#endif // SWIFTSYNTAX_ATOMICBOOL_H