Skip to content

Commit 049f1ac

Browse files
committed
[WIP] Function body macros
1 parent 9c35b08 commit 049f1ac

29 files changed

+445
-14
lines changed

docs/ABI/Mangling.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,9 @@ Entities
407407
macro-expansion-operator ::= decl-name identifier 'fMm' // attached member macro
408408
macro-expansion-operator ::= decl-name identifier 'fMp' // attached peer macro
409409
macro-expansion-operator ::= decl-name identifier 'fMc' // attached conformance macro
410+
macro-expansion-operator ::= decl-name identifier 'fMe' // attached extension macro
411+
macro-expansion-operator ::= decl-name identifier 'fMq' // attached preamble macro
412+
macro-expansion-operator ::= decl-name identifier 'fMb' // attached body macro
410413
macro-expansion-operator ::= decl-name identifier 'fMu' // uniquely-named entity
411414

412415
file-discriminator ::= identifier 'Ll' // anonymous file-discriminated declaration

include/swift/AST/Decl.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,13 +464,16 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
464464
SWIFT_INLINE_BITFIELD(SubscriptDecl, VarDecl, 2,
465465
StaticSpelling : 2
466466
);
467-
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+2+2+8+1+1+1+1+1+1+1,
467+
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+2+2+2+8+1+1+1+1+1+1+1,
468468
/// \see AbstractFunctionDecl::BodyKind
469469
BodyKind : 3,
470470

471471
/// \see AbstractFunctionDecl::BodySkippedStatus
472472
BodySkippedStatus : 2,
473473

474+
/// \see AbstractFunctionDecl::BodyExpandedStatus
475+
BodyExpandedStatus : 2,
476+
474477
/// \see AbstractFunctionDecl::SILSynthesizeKind
475478
SILSynthesizeKind : 2,
476479

@@ -7005,6 +7008,19 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
70057008
// This enum needs to fit in a 2-bit bitfield.
70067009
};
70077010

7011+
enum class BodyExpandedStatus {
7012+
/// We haven't tried to expand any body macros.
7013+
NotExpanded,
7014+
7015+
/// We tried to expand body macros, and there weren't any.
7016+
NoMacros,
7017+
7018+
/// The body was expanded from a body macro.
7019+
Expanded,
7020+
7021+
// This enum needs to fit in a 2-bit bitfield.
7022+
};
7023+
70087024
BodyKind getBodyKind() const {
70097025
return BodyKind(Bits.AbstractFunctionDecl.BodyKind);
70107026
}
@@ -7091,6 +7107,7 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
70917107
ValueDecl(Kind, Parent, Name, NameLoc), BodyAndFP(), AsyncLoc(AsyncLoc),
70927108
ThrowsLoc(ThrowsLoc), ThrownType(ThrownTy) {
70937109
setBodyKind(BodyKind::None);
7110+
setBodyExpandedStatus(BodyExpandedStatus::NotExpanded);
70947111
Bits.AbstractFunctionDecl.HasImplicitSelfDecl = HasImplicitSelfDecl;
70957112
Bits.AbstractFunctionDecl.Overridden = false;
70967113
Bits.AbstractFunctionDecl.Async = Async;
@@ -7112,6 +7129,14 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
71127129
Bits.AbstractFunctionDecl.BodySkippedStatus = unsigned(status);
71137130
}
71147131

7132+
BodyExpandedStatus getBodyExpandedStatus() const {
7133+
return BodyExpandedStatus(Bits.AbstractFunctionDecl.BodyExpandedStatus);
7134+
}
7135+
7136+
void setBodyExpandedStatus(BodyExpandedStatus status) {
7137+
Bits.AbstractFunctionDecl.BodyExpandedStatus = unsigned(status);
7138+
}
7139+
71157140
void setSILSynthesizeKind(SILSynthesizeKind K) {
71167141
Bits.AbstractFunctionDecl.SILSynthesizeKind = unsigned(K);
71177142
}
@@ -7260,6 +7285,10 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
72607285
/// \sa hasBody()
72617286
BraceStmt *getBody(bool canSynthesize = true) const;
72627287

7288+
/// Retrieve the body after macro expansion, which might also have been
7289+
/// type-checked.
7290+
BraceStmt *getMacroExpandedBody() const;
7291+
72637292
/// Retrieve the type-checked body of the given function, or \c nullptr if
72647293
/// there's no body available.
72657294
BraceStmt *getTypecheckedBody() const;

include/swift/AST/TypeCheckRequests.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4398,6 +4398,44 @@ class ExpandPeerMacroRequest
43984398
void noteCycleStep(DiagnosticEngine &diags) const;
43994399
};
44004400

4401+
class ExpandPreambleMacroRequest
4402+
: public SimpleRequest<ExpandPreambleMacroRequest,
4403+
ArrayRef<unsigned>(AbstractFunctionDecl *),
4404+
RequestFlags::Cached> {
4405+
public:
4406+
using SimpleRequest::SimpleRequest;
4407+
4408+
private:
4409+
friend SimpleRequest;
4410+
4411+
ArrayRef<unsigned> evaluate(
4412+
Evaluator &evaluator, AbstractFunctionDecl *fn) const;
4413+
4414+
public:
4415+
bool isCached() const { return true; }
4416+
void diagnoseCycle(DiagnosticEngine &diags) const;
4417+
void noteCycleStep(DiagnosticEngine &diags) const;
4418+
};
4419+
4420+
class ExpandBodyMacroRequest
4421+
: public SimpleRequest<ExpandBodyMacroRequest,
4422+
llvm::Optional<unsigned>(AbstractFunctionDecl *),
4423+
RequestFlags::Cached> {
4424+
public:
4425+
using SimpleRequest::SimpleRequest;
4426+
4427+
private:
4428+
friend SimpleRequest;
4429+
4430+
llvm::Optional<unsigned> evaluate(
4431+
Evaluator &evaluator, AbstractFunctionDecl *fn) const;
4432+
4433+
public:
4434+
bool isCached() const { return true; }
4435+
void diagnoseCycle(DiagnosticEngine &diags) const;
4436+
void noteCycleStep(DiagnosticEngine &diags) const;
4437+
};
4438+
44014439
/// Resolve an external macro given its module and type name.
44024440
class ExternalMacroDefinitionRequest
44034441
: public SimpleRequest<ExternalMacroDefinitionRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,12 @@ SWIFT_REQUEST(TypeChecker, ExpandSynthesizedMemberMacroRequest,
493493
SWIFT_REQUEST(TypeChecker, ExpandPeerMacroRequest,
494494
ArrayRef<unsigned>(Decl *),
495495
Cached, NoLocationInfo)
496+
SWIFT_REQUEST(TypeChecker, ExpandPreambleMacroRequest,
497+
ArrayRef<unsigned>(AbstractFunctionDecl *),
498+
Cached, NoLocationInfo)
499+
SWIFT_REQUEST(TypeChecker, ExpandBodyMacroRequest,
500+
llvm::Optional<unsigned>(AbstractFunctionDecl *),
501+
Cached, NoLocationInfo)
496502
SWIFT_REQUEST(TypeChecker, LocalDiscriminatorsRequest,
497503
unsigned(DeclContext *),
498504
Cached, NoLocationInfo)

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ EXPERIMENTAL_FEATURE(StaticAssert, false)
126126
EXPERIMENTAL_FEATURE(NamedOpaqueTypes, false)
127127
EXPERIMENTAL_FEATURE(FlowSensitiveConcurrencyCaptures, false)
128128
EXPERIMENTAL_FEATURE(CodeItemMacros, false)
129+
EXPERIMENTAL_FEATURE(BodyMacros, true)
129130
EXPERIMENTAL_FEATURE(TupleConformances, false)
130131

131132
SUPPRESSIBLE_LANGUAGE_FEATURE(ExtensionMacroAttr, 0, "@attached(extension)", true)

include/swift/Basic/MacroRoles.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ EXPERIMENTAL_FREESTANDING_MACRO_ROLE(CodeItem, "codeItem", CodeItemMacros)
6969
/// macro is attached to.
7070
ATTACHED_MACRO_ROLE(Extension, "extension", "e")
7171

72+
/// An attached macro that expands to a preamble to a function.
73+
EXPERIMENTAL_ATTACHED_MACRO_ROLE(Preamble, "preamble", "q", BodyMacros)
74+
75+
/// An attached macro that expands to a function body.
76+
EXPERIMENTAL_ATTACHED_MACRO_ROLE(Body, "body", "b", BodyMacros)
77+
7278
#undef ATTACHED_MACRO_ROLE
7379
#undef FREESTANDING_MACRO_ROLE
7480
#undef EXPERIMENTAL_ATTACHED_MACRO_ROLE

include/swift/Demangling/DemangleNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ NODE(AccessorAttachedMacroExpansion)
3636
NODE(AssociatedTypeWitnessTableAccessor)
3737
NODE(BaseWitnessTableAccessor)
3838
NODE(AutoClosureType)
39+
NODE(BodyAttachedMacroExpansion)
3940
NODE(BoundGenericClass)
4041
NODE(BoundGenericEnum)
4142
NODE(BoundGenericStructure)
@@ -189,6 +190,7 @@ NODE(PartialApplyForwarder)
189190
NODE(PartialApplyObjCForwarder)
190191
NODE(PeerAttachedMacroExpansion)
191192
NODE(PostfixOperator)
193+
NODE(PreambleAttachedMacroExpansion)
192194
NODE(PrefixOperator)
193195
NODE(PrivateDeclName)
194196
NODE(PropertyDescriptor)

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6133,6 +6133,7 @@ void AbstractFunctionDecl::keepOriginalBodySourceRange() {
61336133
auto result =
61346134
impl.OriginalBodySourceRanges.insert({this, getBodySourceRange()});
61356135
assert((!result.second ||
6136+
result.first->getSecond().isInvalid() ||
61366137
isSourceLocInOrignalBuffer(this, result.first->getSecond().Start)) &&
61376138
"This function must be called before setting new body range");
61386139
(void)result;

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2940,6 +2940,10 @@ static bool usesFeatureExtensionMacros(Decl *decl) {
29402940
return macro->getMacroRoles().contains(MacroRole::Extension);
29412941
}
29422942

2943+
static bool usesFeatureBodyMacros(Decl *decl) {
2944+
return false;
2945+
}
2946+
29432947
static bool usesFeatureExtensionMacroAttr(Decl *decl) {
29442948
return usesFeatureExtensionMacros(decl);
29452949
}

lib/AST/ASTScopeCreation.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ ASTSourceFileScope::ASTSourceFileScope(SourceFile *SF,
266266
auto expansion = SF->getMacroExpansion();
267267

268268
// Determine the parent source location based on the macro role.
269+
AbstractFunctionDecl *bodyForDecl = nullptr;
269270
switch (*macroRole) {
270271
case MacroRole::Expression:
271272
case MacroRole::Declaration:
@@ -274,8 +275,13 @@ ASTSourceFileScope::ASTSourceFileScope(SourceFile *SF,
274275
case MacroRole::MemberAttribute:
275276
case MacroRole::Conformance:
276277
case MacroRole::Extension:
278+
case MacroRole::Preamble:
277279
parentLoc = expansion.getStartLoc();
278280
break;
281+
case MacroRole::Body:
282+
parentLoc = expansion.getEndLoc();
283+
bodyForDecl = cast<AbstractFunctionDecl>(expansion.get<Decl *>());
284+
break;
279285
case MacroRole::Peer: {
280286
ASTContext &ctx = SF->getASTContext();
281287
SourceManager &sourceMgr = ctx.SourceMgr;
@@ -297,6 +303,18 @@ ASTSourceFileScope::ASTSourceFileScope(SourceFile *SF,
297303
}
298304

299305
if (auto parentScope = findStartingScopeForLookup(enclosingSF, parentLoc)) {
306+
if (bodyForDecl) {
307+
#if false
308+
scopeCreator->constructExpandAndInsert<FunctionBodyScope>(
309+
const_cast<ASTScopeImpl *>(parentScope), bodyForDecl);
310+
parentScope = parentScope->getChildren().back();
311+
#else
312+
auto bodyScope = new (bodyForDecl->getASTContext()) FunctionBodyScope(bodyForDecl);
313+
bodyScope->parentAndWasExpanded.setPointer(const_cast<ASTScopeImpl *>(parentScope));
314+
parentScope = bodyScope;
315+
#endif
316+
}
317+
300318
parentAndWasExpanded.setPointer(const_cast<ASTScopeImpl *>(parentScope));
301319
}
302320
}
@@ -986,7 +1004,7 @@ void AbstractFunctionDeclScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
9861004
// Create scope for the body.
9871005
// We create body scopes when there is no body for source kit to complete
9881006
// erroneous code in bodies.
989-
if (decl->getBodySourceRange().isValid()) {
1007+
if (decl->getOriginalBodySourceRange().isValid()) {
9901008
scopeCreator.constructExpandAndInsert<FunctionBodyScope>(leaf, decl);
9911009
}
9921010
}

lib/AST/ASTScopeSourceRange.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,13 @@ SourceRange DifferentiableAttributeScope::getSourceRangeOfThisASTNode(
125125

126126
SourceRange FunctionBodyScope::getSourceRangeOfThisASTNode(
127127
const bool omitAssertions) const {
128+
// If this function body scope is synthesized for a body macro, use the
129+
// real source range.
130+
if (getChildren().size() == 1 &&
131+
getChildren()[0]->getClassName() == "ASTSourceFileScope") {
132+
return decl->getBodySourceRange();
133+
}
134+
128135
return decl->getOriginalBodySourceRange();
129136
}
130137

lib/AST/Decl.cpp

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,7 @@ Expr *AbstractFunctionDecl::getSingleExpressionBody() const {
10291029

10301030
void AbstractFunctionDecl::setSingleExpressionBody(Expr *NewBody) {
10311031
assert(hasSingleExpressionBody() && "Not a single-expression body");
1032-
auto body = getBody()->getLastElement();
1032+
auto body = getBody(/*canSynthesize=*/false)->getLastElement();
10331033
if (auto *stmt = body.dyn_cast<Stmt *>()) {
10341034
if (auto *returnStmt = dyn_cast<ReturnStmt>(stmt)) {
10351035
returnStmt->setResult(NewBody);
@@ -9120,6 +9120,63 @@ bool AbstractFunctionDecl::hasBody() const {
91209120
}
91219121

91229122

9123+
static BraceStmt *expandBodyMacro(AbstractFunctionDecl *fn) {
9124+
ASTContext &ctx = fn->getASTContext();
9125+
9126+
auto bufferID = evaluateOrDefault(
9127+
ctx.evaluator, ExpandBodyMacroRequest{fn}, llvm::None);
9128+
if (!bufferID) {
9129+
return nullptr;
9130+
}
9131+
9132+
CharSourceRange bufferRange = ctx.SourceMgr.getRangeForBuffer(*bufferID);
9133+
auto bufferStart = bufferRange.getStart();
9134+
auto module = fn->getParentModule();
9135+
auto macroSourceFile = module->getSourceFileContainingLocation(bufferStart);
9136+
9137+
return BraceStmt::create(
9138+
ctx, bufferRange.getStart(), macroSourceFile->getTopLevelItems(),
9139+
bufferRange.getEnd());
9140+
}
9141+
9142+
BraceStmt *AbstractFunctionDecl::getMacroExpandedBody() const {
9143+
auto mutableThis = const_cast<AbstractFunctionDecl *>(this);
9144+
switch (getBodyKind()) {
9145+
case BodyKind::None:
9146+
case BodyKind::Unparsed:
9147+
case BodyKind::Parsed:
9148+
switch (getBodyExpandedStatus()) {
9149+
case BodyExpandedStatus::NotExpanded:
9150+
if (auto expandedBody = expandBodyMacro(mutableThis)) {
9151+
// Save the original body's source range.
9152+
mutableThis->keepOriginalBodySourceRange();
9153+
9154+
// Cache the expanded macro body as the parsed body of the function.
9155+
mutableThis->setBodyExpandedStatus(BodyExpandedStatus::Expanded);
9156+
mutableThis->setBodyParsed(expandedBody);
9157+
9158+
return expandedBody;
9159+
}
9160+
9161+
mutableThis->setBodyExpandedStatus(BodyExpandedStatus::NoMacros);
9162+
break;
9163+
9164+
case BodyExpandedStatus::NoMacros:
9165+
case BodyExpandedStatus::Expanded:
9166+
break;
9167+
}
9168+
9169+
// Fall through to get the body.
9170+
LLVM_FALLTHROUGH;
9171+
9172+
case BodyKind::Synthesize:
9173+
case BodyKind::TypeChecked:
9174+
case BodyKind::SILSynthesize:
9175+
case BodyKind::Deserialized:
9176+
return getBody(/*canSynthesize=*/true);
9177+
}
9178+
}
9179+
91239180
BraceStmt *AbstractFunctionDecl::getBody(bool canSynthesize) const {
91249181
if ((getBodyKind() == BodyKind::Synthesize ||
91259182
getBodyKind() == BodyKind::Unparsed) &&
@@ -11319,6 +11376,8 @@ void MacroDecl::getIntroducedNames(MacroRole role, ValueDecl *attachedTo,
1131911376
case MacroRole::Accessor:
1132011377
case MacroRole::Conformance:
1132111378
case MacroRole::MemberAttribute:
11379+
case MacroRole::Preamble:
11380+
case MacroRole::Body:
1132211381
break;
1132311382
}
1132411383
}

lib/AST/Module.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,6 @@ SourceFile *ModuleDecl::getSourceFileContainingLocation(SourceLoc loc) {
851851
if (loc.isInvalid())
852852
return nullptr;
853853

854-
855854
// Check whether this location is in a "replaced" range, in which case
856855
// we want to use the original source file.
857856
auto &sourceMgr = getASTContext().SourceMgr;

lib/AST/TypeCheckRequests.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,3 +2178,35 @@ void UniqueUnderlyingTypeSubstitutionsRequest::cacheResult(
21782178
const_cast<OpaqueTypeDecl *>(decl)
21792179
->LazySemanticInfo.UniqueUnderlyingTypeComputed = true;
21802180
}
2181+
2182+
void ExpandPreambleMacroRequest::diagnoseCycle(DiagnosticEngine &diags) const {
2183+
auto decl = std::get<0>(getStorage());
2184+
diags.diagnose(decl->getLoc(),
2185+
diag::macro_expand_circular_reference_entity,
2186+
"preamble",
2187+
decl->getName());
2188+
}
2189+
2190+
void ExpandPreambleMacroRequest::noteCycleStep(DiagnosticEngine &diags) const {
2191+
auto decl = std::get<0>(getStorage());
2192+
diags.diagnose(decl->getLoc(),
2193+
diag::macro_expand_circular_reference_entity_through,
2194+
"preamble",
2195+
decl->getName());
2196+
}
2197+
2198+
void ExpandBodyMacroRequest::diagnoseCycle(DiagnosticEngine &diags) const {
2199+
auto decl = std::get<0>(getStorage());
2200+
diags.diagnose(decl->getLoc(),
2201+
diag::macro_expand_circular_reference_entity,
2202+
"body",
2203+
decl->getName());
2204+
}
2205+
2206+
void ExpandBodyMacroRequest::noteCycleStep(DiagnosticEngine &diags) const {
2207+
auto decl = std::get<0>(getStorage());
2208+
diags.diagnose(decl->getLoc(),
2209+
diag::macro_expand_circular_reference_entity_through,
2210+
"body",
2211+
decl->getName());
2212+
}

0 commit comments

Comments
 (0)