Skip to content

Commit 4f6ec8e

Browse files
committed
[Macros] Create llvm::MemoryBuffer directly from macro expansion result
Saves one memory copy. No need to create a temporary NullTerminatedStringRef. (cherry picked from commit a0eb32e)
1 parent 0e5c2e8 commit 4f6ec8e

File tree

2 files changed

+102
-82
lines changed

2 files changed

+102
-82
lines changed

include/swift/Basic/Lazy.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,41 @@
1414
#define SWIFT_BASIC_LAZY_H
1515

1616
#include <memory>
17+
#include <functional>
1718

1819
#include "swift/Basic/Malloc.h"
1920
#include "swift/Basic/type_traits.h"
2021
#include "swift/Threading/Once.h"
2122

2223
namespace swift {
2324

25+
/// A template for lazy-initialized values.
26+
/// Usage:
27+
///
28+
/// LazyValue<std::string> value([]() { return createString(); })
29+
/// if (condition) {
30+
/// // 'createString()' is evaluated only when 'value` is dereferenced.
31+
/// doSomething(*value);
32+
/// }
33+
template <typename T, typename Initializer = std::function<T()>>
34+
class LazyValue {
35+
Initializer Init;
36+
llvm::Optional<T> Value;
37+
38+
public:
39+
LazyValue(Initializer Init) : Init(Init){};
40+
41+
T &get() {
42+
if (!Value.hasValue()) {
43+
Value = Init();
44+
}
45+
return Value.value();
46+
}
47+
48+
T *operator->() { return &get(); }
49+
T &operator*() { return get(); }
50+
};
51+
2452
/// A template for lazily-constructed, zero-initialized, leaked-on-exit
2553
/// global objects.
2654
template <class T> class Lazy {

lib/Sema/TypeCheckMacros.cpp

Lines changed: 74 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/AST/SourceFile.h"
3131
#include "swift/AST/TypeCheckRequests.h"
3232
#include "swift/Basic/Defer.h"
33+
#include "swift/Basic/Lazy.h"
3334
#include "swift/Basic/SourceManager.h"
3435
#include "swift/Basic/StringExtras.h"
3536
#include "swift/Demangling/Demangler.h"
@@ -457,6 +458,9 @@ ExternalMacroDefinitionRequest::evaluate(Evaluator &evaluator, ASTContext *ctx,
457458
/// Adjust the given mangled name for a macro expansion to produce a valid
458459
/// buffer name.
459460
static std::string adjustMacroExpansionBufferName(StringRef name) {
461+
if (name.empty()) {
462+
return "<macro-expansion>";
463+
}
460464
std::string result;
461465
if (name.startswith(MANGLING_PREFIX_STR)) {
462466
result += MACRO_EXPANSION_BUFFER_MANGLING_PREFIX;
@@ -689,31 +693,26 @@ Expr *swift::expandMacroExpr(
689693
if (!sourceFile)
690694
return nullptr;
691695

692-
// Evaluate the macro.
693-
NullTerminatedStringRef evaluatedSource;
694-
695696
MacroDecl *macro = cast<MacroDecl>(macroRef.getDecl());
696697

697698
if (isFromExpansionOfMacro(sourceFile, macro, MacroRole::Expression)) {
698699
ctx.Diags.diagnose(expr->getLoc(), diag::macro_recursive, macro->getName());
699700
return nullptr;
700701
}
701702

702-
/// The discriminator used for the macro.
703-
std::string cachedDiscriminator;
704-
auto getDiscriminator = [&]() -> StringRef {
705-
if (!cachedDiscriminator.empty())
706-
return cachedDiscriminator;
703+
// Evaluate the macro.
704+
std::unique_ptr<llvm::MemoryBuffer> evaluatedSource;
707705

706+
/// The discriminator used for the macro.
707+
LazyValue<std::string> discriminator([&]() -> std::string {
708708
#if SWIFT_SWIFT_PARSER
709709
if (auto expansionExpr = dyn_cast<MacroExpansionExpr>(expr)) {
710710
Mangle::ASTMangler mangler;
711-
cachedDiscriminator = mangler.mangleMacroExpansion(expansionExpr);
711+
return mangler.mangleMacroExpansion(expansionExpr);
712712
}
713713
#endif
714-
715-
return cachedDiscriminator;
716-
};
714+
return "";
715+
});
717716

718717
auto macroDef = macro->getDefinition();
719718
switch (macroDef.kind) {
@@ -735,8 +734,8 @@ Expr *swift::expandMacroExpr(
735734
// Expand the definition with the given arguments.
736735
auto result = expandMacroDefinition(
737736
macroDef.getExpanded(), macro, expr->getArgs());
738-
llvm::MallocAllocator allocator;
739-
evaluatedSource = NullTerminatedStringRef(result, allocator);
737+
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
738+
result, adjustMacroExpansionBufferName(*discriminator));
740739
break;
741740
}
742741

@@ -770,14 +769,16 @@ Expr *swift::expandMacroExpr(
770769
ptrdiff_t evaluatedSourceLength;
771770
swift_ASTGen_expandFreestandingMacro(
772771
&ctx.Diags, externalDef->opaqueHandle,
773-
static_cast<uint32_t>(externalDef->kind), getDiscriminator().data(),
774-
getDiscriminator().size(), astGenSourceFile,
772+
static_cast<uint32_t>(externalDef->kind), discriminator->data(),
773+
discriminator->size(), astGenSourceFile,
775774
expr->getStartLoc().getOpaquePointerValue(), &evaluatedSourceAddress,
776775
&evaluatedSourceLength);
777776
if (!evaluatedSourceAddress)
778777
return nullptr;
779-
evaluatedSource = NullTerminatedStringRef(evaluatedSourceAddress,
780-
(size_t)evaluatedSourceLength);
778+
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
779+
{evaluatedSourceAddress, (size_t)evaluatedSourceLength},
780+
adjustMacroExpansionBufferName(*discriminator));
781+
free((void *)evaluatedSourceAddress);
781782
break;
782783
#else
783784
ctx.Diags.diagnose(expr->getLoc(), diag::macro_unsupported);
@@ -786,26 +787,18 @@ Expr *swift::expandMacroExpr(
786787
}
787788
}
788789

789-
// Figure out a reasonable name for the macro expansion buffer.
790-
std::string bufferName;
791-
if (getDiscriminator().empty())
792-
bufferName = "macro-expansion";
793-
else {
794-
bufferName = adjustMacroExpansionBufferName(getDiscriminator());
795-
}
796-
797790
// Dump macro expansions to standard output, if requested.
798791
if (ctx.LangOpts.DumpMacroExpansions) {
799-
llvm::errs() << bufferName << " as " << expandedType.getString()
792+
llvm::errs() << evaluatedSource->getBufferIdentifier() << " as "
793+
<< expandedType.getString()
800794
<< "\n------------------------------\n"
801-
<< evaluatedSource
795+
<< evaluatedSource->getBuffer()
802796
<< "\n------------------------------\n";
803797
}
804798

805799
// Create a new source buffer with the contents of the expanded macro.
806-
auto macroBuffer =
807-
llvm::MemoryBuffer::getMemBufferCopy(evaluatedSource, bufferName);
808-
unsigned macroBufferID = sourceMgr.addNewSourceBuffer(std::move(macroBuffer));
800+
unsigned macroBufferID =
801+
sourceMgr.addNewSourceBuffer(std::move(evaluatedSource));
809802
auto macroBufferRange = sourceMgr.getRangeForBuffer(macroBufferID);
810803
GeneratedSourceInfo sourceInfo{
811804
GeneratedSourceInfo::ExpressionMacroExpansion,
@@ -816,7 +809,6 @@ Expr *swift::expandMacroExpr(
816809
dc
817810
};
818811
sourceMgr.setGeneratedSourceInfo(macroBufferID, sourceInfo);
819-
free((void*)evaluatedSource.data());
820812

821813
// Create a source file to hold the macro buffer. This is automatically
822814
// registered with the enclosing module.
@@ -878,9 +870,6 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
878870
if (!sourceFile)
879871
return None;
880872

881-
// Evaluate the macro.
882-
NullTerminatedStringRef evaluatedSource;
883-
884873
MacroDecl *macro = cast<MacroDecl>(med->getMacroRef().getDecl());
885874
auto macroRoles = macro->getMacroRoles();
886875
assert(macroRoles.contains(MacroRole::Declaration) ||
@@ -893,6 +882,19 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
893882
return None;
894883
}
895884

885+
// Evaluate the macro.
886+
std::unique_ptr<llvm::MemoryBuffer> evaluatedSource;
887+
888+
/// The discriminator used for the macro.
889+
LazyValue<std::string> discriminator([&]() -> std::string {
890+
#if SWIFT_SWIFT_PARSER
891+
Mangle::ASTMangler mangler;
892+
return mangler.mangleMacroExpansion(med);
893+
#else
894+
return "";
895+
#endif
896+
});
897+
896898
auto macroDef = macro->getDefinition();
897899
switch (macroDef.kind) {
898900
case MacroDefinition::Kind::Undefined:
@@ -912,8 +914,8 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
912914
// Expand the definition with the given arguments.
913915
auto result = expandMacroDefinition(
914916
macroDef.getExpanded(), macro, med->getArgs());
915-
llvm::MallocAllocator allocator;
916-
evaluatedSource = NullTerminatedStringRef(result, allocator);
917+
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
918+
result, adjustMacroExpansionBufferName(*discriminator));
917919
break;
918920
}
919921

@@ -958,21 +960,20 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
958960
if (!astGenSourceFile)
959961
return None;
960962

961-
Mangle::ASTMangler mangler;
962-
auto discriminator = mangler.mangleMacroExpansion(med);
963-
964963
const char *evaluatedSourceAddress;
965964
ptrdiff_t evaluatedSourceLength;
966965
swift_ASTGen_expandFreestandingMacro(
967966
&ctx.Diags, externalDef->opaqueHandle,
968-
static_cast<uint32_t>(externalDef->kind), discriminator.data(),
969-
discriminator.size(), astGenSourceFile,
967+
static_cast<uint32_t>(externalDef->kind), discriminator->data(),
968+
discriminator->size(), astGenSourceFile,
970969
med->getStartLoc().getOpaquePointerValue(), &evaluatedSourceAddress,
971970
&evaluatedSourceLength);
972971
if (!evaluatedSourceAddress)
973972
return None;
974-
evaluatedSource = NullTerminatedStringRef(evaluatedSourceAddress,
975-
(size_t)evaluatedSourceLength);
973+
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
974+
{evaluatedSourceAddress, (size_t)evaluatedSourceLength},
975+
adjustMacroExpansionBufferName(*discriminator));
976+
free((void *)evaluatedSourceAddress);
976977
break;
977978
#else
978979
med->diagnose(diag::macro_unsupported);
@@ -981,26 +982,17 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
981982
}
982983
}
983984

984-
// Figure out a reasonable name for the macro expansion buffer.
985-
std::string bufferName;
986-
{
987-
Mangle::ASTMangler mangler;
988-
bufferName = adjustMacroExpansionBufferName(
989-
mangler.mangleMacroExpansion(med));
990-
}
991-
992985
// Dump macro expansions to standard output, if requested.
993986
if (ctx.LangOpts.DumpMacroExpansions) {
994-
llvm::errs() << bufferName
987+
llvm::errs() << evaluatedSource->getBufferIdentifier()
995988
<< "\n------------------------------\n"
996-
<< evaluatedSource
989+
<< evaluatedSource->getBuffer()
997990
<< "\n------------------------------\n";
998991
}
999992

1000993
// Create a new source buffer with the contents of the expanded macro.
1001-
auto macroBuffer =
1002-
llvm::MemoryBuffer::getMemBufferCopy(evaluatedSource, bufferName);
1003-
unsigned macroBufferID = sourceMgr.addNewSourceBuffer(std::move(macroBuffer));
994+
unsigned macroBufferID =
995+
sourceMgr.addNewSourceBuffer(std::move(evaluatedSource));
1004996
auto macroBufferRange = sourceMgr.getRangeForBuffer(macroBufferID);
1005997
GeneratedSourceInfo sourceInfo{
1006998
GeneratedSourceInfo::FreestandingDeclMacroExpansion,
@@ -1011,7 +1003,6 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
10111003
dc
10121004
};
10131005
sourceMgr.setGeneratedSourceInfo(macroBufferID, sourceInfo);
1014-
free((void*)evaluatedSource.data());
10151006

10161007
// Create a source file to hold the macro buffer. This is automatically
10171008
// registered with the enclosing module.
@@ -1105,9 +1096,18 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
11051096
}
11061097

11071098
// Evaluate the macro.
1108-
NullTerminatedStringRef evaluatedSource;
1099+
std::unique_ptr<llvm::MemoryBuffer> evaluatedSource;
1100+
1101+
/// The discriminator used for the macro.
1102+
LazyValue<std::string> discriminator([&]() -> std::string {
1103+
#if SWIFT_SWIFT_PARSER
1104+
Mangle::ASTMangler mangler;
1105+
return mangler.mangleAttachedMacroExpansion(attachedTo, attr, role);
1106+
#else
1107+
return "";
1108+
#endif
1109+
});
11091110

1110-
std::string discriminator;
11111111
auto macroDef = macro->getDefinition();
11121112
switch (macroDef.kind) {
11131113
case MacroDefinition::Kind::Undefined:
@@ -1128,7 +1128,8 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
11281128
auto result = expandMacroDefinition(
11291129
macroDef.getExpanded(), macro, attr->getArgs());
11301130
llvm::MallocAllocator allocator;
1131-
evaluatedSource = NullTerminatedStringRef(result, allocator);
1131+
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
1132+
result, adjustMacroExpansionBufferName(*discriminator));
11321133
break;
11331134
}
11341135

@@ -1174,26 +1175,22 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
11741175
if (auto var = dyn_cast<VarDecl>(attachedTo))
11751176
searchDecl = var->getParentPatternBinding();
11761177

1177-
{
1178-
Mangle::ASTMangler mangler;
1179-
discriminator =
1180-
mangler.mangleAttachedMacroExpansion(attachedTo, attr, role);
1181-
}
1182-
11831178
const char *evaluatedSourceAddress;
11841179
ptrdiff_t evaluatedSourceLength;
11851180
swift_ASTGen_expandAttachedMacro(
11861181
&ctx.Diags, externalDef->opaqueHandle,
1187-
static_cast<uint32_t>(externalDef->kind), discriminator.data(),
1188-
discriminator.size(), static_cast<uint32_t>(role), astGenAttrSourceFile,
1189-
attr->AtLoc.getOpaquePointerValue(), astGenDeclSourceFile,
1190-
searchDecl->getStartLoc().getOpaquePointerValue(),
1182+
static_cast<uint32_t>(externalDef->kind), discriminator->data(),
1183+
discriminator->size(), static_cast<uint32_t>(role),
1184+
astGenAttrSourceFile, attr->AtLoc.getOpaquePointerValue(),
1185+
astGenDeclSourceFile, searchDecl->getStartLoc().getOpaquePointerValue(),
11911186
astGenParentDeclSourceFile, parentDeclLoc, &evaluatedSourceAddress,
11921187
&evaluatedSourceLength);
11931188
if (!evaluatedSourceAddress)
11941189
return nullptr;
1195-
evaluatedSource = NullTerminatedStringRef(evaluatedSourceAddress,
1196-
(size_t)evaluatedSourceLength);
1190+
evaluatedSource = llvm::MemoryBuffer::getMemBufferCopy(
1191+
{evaluatedSourceAddress, (size_t)evaluatedSourceLength},
1192+
adjustMacroExpansionBufferName(*discriminator));
1193+
free((void *)evaluatedSourceAddress);
11971194
break;
11981195
#else
11991196
attachedTo->diagnose(diag::macro_unsupported);
@@ -1202,14 +1199,11 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
12021199
}
12031200
}
12041201

1205-
// Figure out a reasonable name for the macro expansion buffer.
1206-
std::string bufferName = adjustMacroExpansionBufferName(discriminator);
1207-
12081202
// Dump macro expansions to standard output, if requested.
12091203
if (ctx.LangOpts.DumpMacroExpansions) {
1210-
llvm::errs() << bufferName
1204+
llvm::errs() << evaluatedSource->getBufferIdentifier()
12111205
<< "\n------------------------------\n"
1212-
<< evaluatedSource
1206+
<< evaluatedSource->getBuffer()
12131207
<< "\n------------------------------\n";
12141208
}
12151209

@@ -1297,9 +1291,8 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
12971291
}
12981292

12991293
// Create a new source buffer with the contents of the expanded macro.
1300-
auto macroBuffer =
1301-
llvm::MemoryBuffer::getMemBufferCopy(evaluatedSource, bufferName);
1302-
unsigned macroBufferID = sourceMgr.addNewSourceBuffer(std::move(macroBuffer));
1294+
unsigned macroBufferID =
1295+
sourceMgr.addNewSourceBuffer(std::move(evaluatedSource));
13031296
auto macroBufferRange = sourceMgr.getRangeForBuffer(macroBufferID);
13041297
GeneratedSourceInfo sourceInfo{
13051298
generatedSourceKind,
@@ -1310,7 +1303,6 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
13101303
attr
13111304
};
13121305
sourceMgr.setGeneratedSourceInfo(macroBufferID, sourceInfo);
1313-
free((void*)evaluatedSource.data());
13141306

13151307
// Create a source file to hold the macro buffer. This is automatically
13161308
// registered with the enclosing module.

0 commit comments

Comments
 (0)