Skip to content

Commit 4ce0834

Browse files
committed
[Macros] Serialization support for macro declarations.
1 parent e67c546 commit 4ce0834

File tree

8 files changed

+182
-8
lines changed

8 files changed

+182
-8
lines changed

lib/AST/AccessRequests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ AccessLevelRequest::evaluate(Evaluator &evaluator, ValueDecl *D) const {
128128
case DeclContextKind::ExtensionDecl:
129129
return cast<ExtensionDecl>(DC)->getDefaultAccessLevel();
130130
case DeclContextKind::MacroDecl:
131-
// Macros are always public.
132-
return AccessLevel::Public;
131+
// There are no declarations inside a macro.
132+
return AccessLevel::Private;
133133
}
134134
llvm_unreachable("unhandled kind");
135135
}

lib/Parse/ParseDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8986,7 +8986,7 @@ Parser::parseDeclPrecedenceGroup(ParseDeclOptions flags,
89868986
return makeParserResult(result);
89878987
}
89888988

8989-
ParserResult<MacroDecl> Parser::parseDeclMacro(DeclAttributes &Attributes) {
8989+
ParserResult<MacroDecl> Parser::parseDeclMacro(DeclAttributes &attributes) {
89908990
assert(Tok.isContextualKeyword("macro"));
89918991
SourceLoc macroLoc = consumeToken(); // 'macro'
89928992

@@ -9088,6 +9088,7 @@ ParserResult<MacroDecl> Parser::parseDeclMacro(DeclAttributes &Attributes) {
90889088
macroLoc, macroFullName, macroNameLoc, genericParams, parameterList,
90899089
arrowOrColonLoc, resultType, externalMacroModule, externalMacroModuleLoc,
90909090
externalMacroTypeName, externalMacroTypeNameLoc, CurDeclContext);
9091+
macro->getAttrs() = attributes;
90919092

90929093
// Parse a 'where' clause if present.
90939094
if (Tok.is(tok::kw_where)) {

lib/Serialization/DeclTypeRecordNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ DECL(EXTENSION)
144144
DECL(DESTRUCTOR)
145145
DECL(PRECEDENCE_GROUP)
146146
DECL(ACCESSOR)
147+
DECL(MACRO)
147148

148149
FIRST_PATTERN(PAREN, 80)
149150
PATTERN(TUPLE)

lib/Serialization/Deserialization.cpp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2332,6 +2332,8 @@ Expected<DeclContext *> ModuleFile::getDeclContextChecked(DeclContextID DCID) {
23322332
return SD;
23332333
if (auto EED = dyn_cast<EnumElementDecl>(D))
23342334
return EED;
2335+
if (auto MD = dyn_cast<MacroDecl>(D))
2336+
return MD;
23352337

23362338
llvm_unreachable("Unknown Decl : DeclContext kind");
23372339
}
@@ -4508,6 +4510,99 @@ class DeclDeserializer {
45084510
return dtor;
45094511
}
45104512

4513+
Expected<Decl *> deserializeMacro(ArrayRef<uint64_t> scratch,
4514+
StringRef blobData) {
4515+
DeclContextID contextID;
4516+
bool isImplicit, hasParameterList;
4517+
GenericSignatureID genericSigID;
4518+
TypeID resultInterfaceTypeID;
4519+
uint8_t rawAccessLevel;
4520+
unsigned numArgNames;
4521+
IdentifierID externalModuleNameID;
4522+
IdentifierID externalMacroTypeNameID;
4523+
4524+
ArrayRef<uint64_t> argNameAndDependencyIDs;
4525+
4526+
decls_block::MacroLayout::readRecord(scratch, contextID,
4527+
isImplicit,
4528+
genericSigID,
4529+
hasParameterList,
4530+
resultInterfaceTypeID,
4531+
rawAccessLevel,
4532+
numArgNames,
4533+
externalModuleNameID,
4534+
externalMacroTypeNameID,
4535+
argNameAndDependencyIDs);
4536+
4537+
// Get the base name.
4538+
DeclBaseName baseName = MF.getDeclBaseName(argNameAndDependencyIDs.front());
4539+
argNameAndDependencyIDs = argNameAndDependencyIDs.drop_front();
4540+
4541+
// Resolve the name ids.
4542+
DeclName name;
4543+
if (numArgNames > 0) {
4544+
SmallVector<Identifier, 2> argNames;
4545+
for (auto argNameID : argNameAndDependencyIDs.slice(0, numArgNames))
4546+
argNames.push_back(MF.getIdentifier(argNameID));
4547+
name = DeclName(ctx, baseName, argNames);
4548+
} else {
4549+
name = baseName;
4550+
}
4551+
PrettySupplementalDeclNameTrace trace(name);
4552+
4553+
argNameAndDependencyIDs = argNameAndDependencyIDs.slice(numArgNames);
4554+
4555+
// Check dependency types.
4556+
for (TypeID dependencyID : argNameAndDependencyIDs) {
4557+
auto dependency = MF.getTypeChecked(dependencyID);
4558+
if (!dependency) {
4559+
DeclDeserializationError::Flags errorFlags;
4560+
return llvm::make_error<TypeError>(
4561+
name, takeErrorInfo(dependency.takeError()),
4562+
errorFlags);
4563+
}
4564+
}
4565+
4566+
auto parent = MF.getDeclContext(contextID);
4567+
if (declOrOffset.isComplete())
4568+
return declOrOffset;
4569+
4570+
auto *genericParams = MF.maybeReadGenericParams(parent);
4571+
if (declOrOffset.isComplete())
4572+
return declOrOffset;
4573+
4574+
const auto resultInterfaceType = MF.getType(resultInterfaceTypeID);
4575+
if (declOrOffset.isComplete())
4576+
return declOrOffset;
4577+
4578+
auto *macro = new (ctx) MacroDecl(SourceLoc(), name, SourceLoc(),
4579+
genericParams, nullptr,
4580+
SourceLoc(),
4581+
nullptr,
4582+
MF.getIdentifier(externalModuleNameID),
4583+
SourceLoc(),
4584+
MF.getIdentifier(externalMacroTypeNameID),
4585+
SourceLoc(),
4586+
parent);
4587+
declOrOffset = macro;
4588+
4589+
macro->setGenericSignature(MF.getGenericSignature(genericSigID));
4590+
macro->resultType.setType(resultInterfaceType);
4591+
4592+
if (hasParameterList)
4593+
macro->parameterList = MF.readParameterList();
4594+
4595+
if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
4596+
macro->setAccess(*accessLevel);
4597+
else
4598+
MF.fatal();
4599+
4600+
if (isImplicit)
4601+
macro->setImplicit();
4602+
4603+
return macro;
4604+
}
4605+
45114606
AvailableAttr *readAvailable_DECL_ATTR(SmallVectorImpl<uint64_t> &scratch,
45124607
StringRef blobData);
45134608
};
@@ -5258,6 +5353,7 @@ DeclDeserializer::getDeclCheckedImpl(
52585353
CASE(Subscript)
52595354
CASE(Extension)
52605355
CASE(Destructor)
5356+
CASE(Macro)
52615357
#undef CASE
52625358

52635359
case decls_block::XREF: {

lib/Serialization/ModuleFormat.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 724; // allowable client serialization
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 725; // macro declarations
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -1668,6 +1668,24 @@ namespace decls_block {
16681668
// This record is trailed by its inlinable body text
16691669
>;
16701670

1671+
using MacroLayout = BCRecordLayout<
1672+
MACRO_DECL,
1673+
DeclContextIDField, // context decl
1674+
BCFixed<1>, // implicit?
1675+
GenericSignatureIDField, // generic environment
1676+
BCFixed<1>, // whether there is a parameter list
1677+
TypeIDField, // result interface type
1678+
AccessLevelField, // access level
1679+
BCVBR<5>, // number of parameter name components
1680+
IdentifierIDField, // external module name
1681+
IdentifierIDField, // external type name
1682+
BCArray<IdentifierIDField> // name components,
1683+
// followed by TypeID dependencies
1684+
// The record is trailed by:
1685+
// - its generic parameters, if any
1686+
// - parameter list, if present
1687+
>;
1688+
16711689
using InlinableBodyTextLayout = BCRecordLayout<
16721690
INLINABLE_BODY_TEXT,
16731691
BCBlob // body text
@@ -2200,6 +2218,8 @@ static inline decls_block::RecordKind getKindForTable(const Decl *D) {
22002218
return decls_block::CONSTRUCTOR_DECL;
22012219
case DeclKind::Destructor:
22022220
return decls_block::DESTRUCTOR_DECL;
2221+
case DeclKind::Macro:
2222+
return decls_block::MACRO_DECL;
22032223

22042224
default:
22052225
llvm_unreachable("cannot store this kind of decl in a hash table");

lib/Serialization/Serialization.cpp

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4295,6 +4295,49 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
42954295
writeInlinableBodyTextIfNeeded(dtor);
42964296
}
42974297

4298+
void visitMacroDecl(const MacroDecl *macro) {
4299+
using namespace decls_block;
4300+
verifyAttrSerializable(macro);
4301+
4302+
auto contextID = S.addDeclContextRef(macro->getDeclContext());
4303+
4304+
SmallVector<IdentifierID, 4> nameComponentsAndDependencies;
4305+
nameComponentsAndDependencies.push_back(
4306+
S.addDeclBaseNameRef(macro->getName().getBaseName()));
4307+
for (auto argName : macro->getName().getArgumentNames())
4308+
nameComponentsAndDependencies.push_back(S.addDeclBaseNameRef(argName));
4309+
4310+
Type ty = macro->getInterfaceType();
4311+
for (Type dependency : collectDependenciesFromType(ty->getCanonicalType()))
4312+
nameComponentsAndDependencies.push_back(S.addTypeRef(dependency));
4313+
4314+
uint8_t rawAccessLevel =
4315+
getRawStableAccessLevel(macro->getFormalAccess());
4316+
4317+
Type resultType = evaluateOrDefault(
4318+
S.getASTContext().evaluator,
4319+
ResultTypeRequest{const_cast<MacroDecl *>(macro)},
4320+
Type());
4321+
4322+
unsigned abbrCode = S.DeclTypeAbbrCodes[MacroLayout::Code];
4323+
MacroLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
4324+
contextID.getOpaqueValue(),
4325+
macro->isImplicit(),
4326+
S.addGenericSignatureRef(
4327+
macro->getGenericSignature()),
4328+
macro->parameterList != nullptr,
4329+
S.addTypeRef(resultType),
4330+
rawAccessLevel,
4331+
macro->getName().getArgumentNames().size(),
4332+
S.addDeclBaseNameRef(macro->externalModuleName),
4333+
S.addDeclBaseNameRef(macro->externalMacroTypeName),
4334+
nameComponentsAndDependencies);
4335+
4336+
writeGenericParams(macro->getGenericParams());
4337+
if (macro->parameterList)
4338+
writeParameterList(macro->parameterList);
4339+
}
4340+
42984341
void visitTopLevelCodeDecl(const TopLevelCodeDecl *) {
42994342
// Top-level code is ignored; external clients don't need to know about it.
43004343
}
@@ -4323,10 +4366,6 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
43234366
llvm_unreachable("member placeholders shouldn't be serialized");
43244367
}
43254368

4326-
void visitMacroDecl(const MacroDecl *) {
4327-
llvm_unreachable("macro decls shouldn't be serialized");
4328-
}
4329-
43304369
void visitMacroExpansionDecl(const MacroExpansionDecl *) {
43314370
llvm_unreachable("macro expansion decls shouldn't be serialized");
43324371
}
@@ -5219,6 +5258,7 @@ void Serializer::writeAllDeclsAndTypes() {
52195258
registerDeclTypeAbbr<SubscriptLayout>();
52205259
registerDeclTypeAbbr<ExtensionLayout>();
52215260
registerDeclTypeAbbr<DestructorLayout>();
5261+
registerDeclTypeAbbr<MacroLayout>();
52225262

52235263
registerDeclTypeAbbr<ParameterListLayout>();
52245264

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public macro publicStringify<T>(_ value: T) -> (T, String) = _SwiftSyntaxMacros.StringifyMacro
2+
3+
macro internalStringify<T>(_ value: T) -> (T, String) = _SwiftSyntaxMacros.StringifyMacro

test/Serialization/macros.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t-scratch)
3+
// RUN: %target-swift-frontend -emit-module -o %t/def_macros.swiftmodule %S/Inputs/def_macros.swift -module-name def_macros -enable-experimental-feature Macros
4+
// RUN: %target-swift-frontend -typecheck -I%t -verify %s -verify-ignore-unknown -enable-experimental-feature Macros
5+
6+
import def_macros
7+
8+
func test(a: Int, b: Int) {
9+
_ = #publicStringify(a + b)
10+
11+
_ = #internalStringify(a + b)
12+
// expected-error@-1{{macro 'internalStringify' is undefined}}
13+
}

0 commit comments

Comments
 (0)