Skip to content

Commit 5b3c24f

Browse files
committed
[Macros] Serialization support for macro declarations.
1 parent 372489f commit 5b3c24f

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
@@ -2326,6 +2326,8 @@ Expected<DeclContext *> ModuleFile::getDeclContextChecked(DeclContextID DCID) {
23262326
return SD;
23272327
if (auto EED = dyn_cast<EnumElementDecl>(D))
23282328
return EED;
2329+
if (auto MD = dyn_cast<MacroDecl>(D))
2330+
return MD;
23292331

23302332
llvm_unreachable("Unknown Decl : DeclContext kind");
23312333
}
@@ -4502,6 +4504,99 @@ class DeclDeserializer {
45024504
return dtor;
45034505
}
45044506

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

52575353
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 = 722; // has_symbol SIL serialization
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 723; // macro declarations
6262

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

1665+
using MacroLayout = BCRecordLayout<
1666+
MACRO_DECL,
1667+
DeclContextIDField, // context decl
1668+
BCFixed<1>, // implicit?
1669+
GenericSignatureIDField, // generic environment
1670+
BCFixed<1>, // whether there is a parameter list
1671+
TypeIDField, // result interface type
1672+
AccessLevelField, // access level
1673+
BCVBR<5>, // number of parameter name components
1674+
IdentifierIDField, // external module name
1675+
IdentifierIDField, // external type name
1676+
BCArray<IdentifierIDField> // name components,
1677+
// followed by TypeID dependencies
1678+
// The record is trailed by:
1679+
// - its generic parameters, if any
1680+
// - parameter list, if present
1681+
>;
1682+
16651683
using InlinableBodyTextLayout = BCRecordLayout<
16661684
INLINABLE_BODY_TEXT,
16671685
BCBlob // body text
@@ -2193,6 +2211,8 @@ static inline decls_block::RecordKind getKindForTable(const Decl *D) {
21932211
return decls_block::CONSTRUCTOR_DECL;
21942212
case DeclKind::Destructor:
21952213
return decls_block::DESTRUCTOR_DECL;
2214+
case DeclKind::Macro:
2215+
return decls_block::MACRO_DECL;
21962216

21972217
default:
21982218
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
@@ -4286,6 +4286,49 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
42864286
writeInlinableBodyTextIfNeeded(dtor);
42874287
}
42884288

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

4317-
void visitMacroDecl(const MacroDecl *) {
4318-
llvm_unreachable("macro decls shouldn't be serialized");
4319-
}
4320-
43214360
void visitMacroExpansionDecl(const MacroExpansionDecl *) {
43224361
llvm_unreachable("macro expansion decls shouldn't be serialized");
43234362
}
@@ -5210,6 +5249,7 @@ void Serializer::writeAllDeclsAndTypes() {
52105249
registerDeclTypeAbbr<SubscriptLayout>();
52115250
registerDeclTypeAbbr<ExtensionLayout>();
52125251
registerDeclTypeAbbr<DestructorLayout>();
5252+
registerDeclTypeAbbr<MacroLayout>();
52135253

52145254
registerDeclTypeAbbr<ParameterListLayout>();
52155255

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)