Skip to content

Commit f04fd94

Browse files
committed
[Macros] Separate out the expansion of macros into its own source file.
Once we've expanded a macro, create a new source buffer containing the expanded macro contents.
1 parent e2993ea commit f04fd94

File tree

5 files changed

+144
-21
lines changed

5 files changed

+144
-21
lines changed

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public func evaluateMacro(
8383
evaluatedResultPtr[utf8.count] = 0
8484

8585
expandedSourcePointer.pointee = UnsafePointer(evaluatedResultPtr)
86-
expandedSourceLength.pointee = utf8.count + 1
86+
expandedSourceLength.pointee = utf8.count
8787
}
8888

8989
return 0

lib/Sema/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ add_swift_host_library(swiftSema STATIC
5858
TypeCheckExpr.cpp
5959
TypeCheckExprObjC.cpp
6060
TypeCheckGeneric.cpp
61+
TypeCheckMacros.cpp
6162
TypeCheckNameLookup.cpp
6263
TypeCheckPattern.cpp
6364
TypeCheckPropertyWrapper.cpp

lib/Sema/CSApply.cpp

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "CodeSynthesis.h"
2121
#include "MiscDiagnostics.h"
2222
#include "TypeCheckConcurrency.h"
23+
#include "TypeCheckMacros.h"
2324
#include "TypeCheckProtocol.h"
2425
#include "TypeCheckType.h"
2526
#include "swift/AST/ASTVisitor.h"
@@ -54,10 +55,6 @@
5455
using namespace swift;
5556
using namespace constraints;
5657

57-
extern "C" ptrdiff_t swift_ASTGen_evaluateMacro(
58-
void *sourceFile, const void *sourceLocation,
59-
const char **evaluatedSource, ptrdiff_t *evaluatedSourceLength);
60-
6158
bool Solution::hasFixedType(TypeVariableType *typeVar) const {
6259
auto knownBinding = typeBindings.find(typeVar);
6360
return knownBinding != typeBindings.end();
@@ -2977,22 +2974,13 @@ namespace {
29772974
#if SWIFT_SWIFT_PARSER
29782975
auto &ctx = cs.getASTContext();
29792976
if (ctx.LangOpts.hasFeature(Feature::BuiltinMacros)) {
2980-
if (auto sf = dc->getParentSourceFile()) {
2981-
if (auto astGenSF = sf->exportedSourceFile) {
2982-
const char *evaluatedSource;
2983-
ptrdiff_t evaluatedSourceLength;
2984-
swift_ASTGen_evaluateMacro(
2985-
astGenSF, expr->getStartLoc().getOpaquePointerValue(),
2986-
&evaluatedSource, &evaluatedSourceLength);
2987-
if (evaluatedSource) {
2988-
llvm::outs() << "Macro rewrite: "
2989-
<< MagicIdentifierLiteralExpr::getKindString(expr->getKind())
2990-
<< " --> " << StringRef(evaluatedSource, evaluatedSourceLength)
2991-
<< "\n";
2992-
free((void*)evaluatedSource);
2993-
}
2994-
}
2995-
}
2977+
auto kind = MagicIdentifierLiteralExpr::getKindString(expr->getKind())
2978+
.drop_front();
2979+
auto expandedType = solution.simplifyType(solution.getType(expr));
2980+
if (auto newExpr = expandMacroExpr(dc, expr, kind, expandedType))
2981+
return newExpr;
2982+
2983+
// Fall through to use old implementation.
29962984
}
29972985
#endif
29982986

lib/Sema/TypeCheckMacros.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//===--- TypeCheckMacros.cpp - Macro Handling ----------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file implements support for the evaluation of macros.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "TypeCheckMacros.h"
18+
#include "swift/AST/ASTContext.h"
19+
#include "swift/AST/Expr.h"
20+
#include "swift/AST/SourceFile.h"
21+
#include "swift/Basic/SourceManager.h"
22+
#include "swift/Parse/Lexer.h"
23+
24+
using namespace swift;
25+
26+
extern "C" ptrdiff_t swift_ASTGen_evaluateMacro(
27+
void *sourceFile, const void *sourceLocation,
28+
const char **evaluatedSource, ptrdiff_t *evaluatedSourceLength);
29+
30+
#if SWIFT_SWIFT_PARSER
31+
Expr *swift::expandMacroExpr(
32+
DeclContext *dc, Expr *expr, StringRef macroName, Type expandedType
33+
) {
34+
ASTContext &ctx = dc->getASTContext();
35+
36+
// FIXME: Introduce a more robust way to ensure that we can get the "exported"
37+
// source file for a given context. If it's within a macro expansion, it
38+
// may not have a C++ SourceFile, but will have a Syntax tree.
39+
//
40+
// FIXME^2: And find a better name for "exportedSourceFile".
41+
auto sourceFile = dc->getParentSourceFile();
42+
if (!sourceFile)
43+
return nullptr;
44+
45+
auto astGenSourceFile = sourceFile->exportedSourceFile;
46+
if (!astGenSourceFile)
47+
return nullptr;
48+
49+
// Evaluate the macro.
50+
const char *evaluatedSource;
51+
ptrdiff_t evaluatedSourceLength;
52+
swift_ASTGen_evaluateMacro(
53+
astGenSourceFile, expr->getStartLoc().getOpaquePointerValue(),
54+
&evaluatedSource, &evaluatedSourceLength);
55+
if (!evaluatedSource)
56+
return nullptr;
57+
58+
SourceManager &sourceMgr = ctx.SourceMgr;
59+
60+
// Figure out a reasonable name for the macro expansion buffer.
61+
std::string bufferName;
62+
{
63+
llvm::raw_string_ostream out(bufferName);
64+
65+
out << "Macro expansion of #" << macroName;
66+
if (auto bufferID = sourceFile->getBufferID()) {
67+
unsigned startLine, startColumn;
68+
std::tie(startLine, startColumn) =
69+
sourceMgr.getLineAndColumnInBuffer(expr->getStartLoc(), *bufferID);
70+
71+
SourceLoc endLoc =
72+
Lexer::getLocForEndOfToken(sourceMgr, expr->getEndLoc());
73+
unsigned endLine, endColumn;
74+
std::tie(endLine, endColumn) =
75+
sourceMgr.getLineAndColumnInBuffer(endLoc, *bufferID);
76+
77+
out << sourceMgr.getIdentifierForBuffer(*bufferID) << ":"
78+
<< startLine << ":" << startColumn
79+
<< "-" << endLine << ":" << endColumn;
80+
}
81+
}
82+
83+
// Create a new source buffer with the contents of the expanded macro.
84+
auto macroBuffer =
85+
llvm::MemoryBuffer::getMemBuffer(
86+
StringRef(evaluatedSource, evaluatedSourceLength), bufferName);
87+
unsigned macroBufferID = sourceMgr.addNewSourceBuffer(std::move(macroBuffer));
88+
89+
// FIXME: Debug output.
90+
llvm::outs() << "Macro rewrite: "
91+
<< "#" << macroName
92+
<< " --> " << sourceMgr.getEntireTextForBuffer(macroBufferID)
93+
<< "\n";
94+
95+
return nullptr;
96+
}
97+
98+
#endif // SWIFT_SWIFT_PARSER

lib/Sema/TypeCheckMacros.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===--- TypeCheckConcurrency.h - Concurrency -------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file provides type checking support for macros.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
#ifndef SWIFT_SEMA_TYPECHECKMACROS_H
17+
#define SWIFT_SEMA_TYPECHECKMACROS_H
18+
19+
#include "swift/AST/Type.h"
20+
21+
namespace swift {
22+
23+
class Expr;
24+
25+
/// Expands the given macro expression and type-check the result with
26+
/// the given expanded type.
27+
///
28+
/// \returns the type-checked replacement expression, or NULL if the
29+
// macro could not be expanded.
30+
Expr *expandMacroExpr(
31+
DeclContext *dc, Expr *expr, StringRef macroName, Type expandedType);
32+
33+
} // end namespace swift
34+
35+
#endif /* SWIFT_SEMA_TYPECHECKMACROS_H */
36+

0 commit comments

Comments
 (0)