Skip to content

Commit db15d82

Browse files
committed
[NFC] Miscellaneous improvements to Playground and PCMacro transforms
1 parent 3570905 commit db15d82

File tree

3 files changed

+84
-88
lines changed

3 files changed

+84
-88
lines changed

include/swift/Subsystems.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,8 @@ namespace swift {
167167

168168
/// Once parsing and name-binding are complete this optionally walks the ASTs
169169
/// to add calls to externally provided functions that simulate
170-
/// "program counter"-like debugging events.
170+
/// "program counter"-like debugging events. See the comment at the top of
171+
/// lib/Sema/PCMacro.cpp for a description of the calls inserted.
171172
void performPCMacro(SourceFile &SF);
172173

173174
/// Creates a type checker instance on the given AST context, if it

lib/Sema/PCMacro.cpp

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,35 @@
1313
// This file implements the 'program counter simulation' for Swift.
1414
// Based off the PlaygroundTransform, PCMacro instruments code to call
1515
// functions at times that a debugger would show the program counter move.
16+
// It can be used to collect and display information about the flow of control
17+
// through Swift code in "live coding" environments like Playgrounds without
18+
// resorting to more heavyweight mechanisms like profiling.
19+
//
20+
// More specifically, this transformation inserts calls to visible functions
21+
// with these names and signatures (other integer types should work too):
22+
//
23+
// func __builtin_pc_before(
24+
// _ startLine: Int, _ endLine: Int,
25+
// _ startColumn: Int, _ endColumn: Int,
26+
// _ moduleID: Int, _ fileID: Int
27+
// ) -> Void
28+
// func __builtin_pc_after(
29+
// _ startLine: Int, _ endLine: Int,
30+
// _ startColumn: Int, _ endColumn: Int,
31+
// _ moduleID: Int, _ fileID: Int
32+
// ) -> Void
33+
//
34+
// The `startLine`, `endLine`, `startColumn`, and `endColumn` parameters are
35+
// passed 1-based integer literals; 0 is used for invalid (i.e.
36+
// compiler-generated) code. The `moduleID` and `fileID` parameters are passed
37+
// the values of visible variables or constants named
38+
// `__builtin_pg_module_<module name>` and
39+
// `__builtin_pg_file_<file base name>`, or an integer literal 0 if suitable
40+
// variables are not found.
41+
//
42+
// The transform inserts these calls before and after each statement, as well
43+
// as before and after expressions nested inside statements, such as `if` and
44+
// `while` conditions and `var` and `let` initial values.
1645
//
1746
//===----------------------------------------------------------------------===//
1847

@@ -347,8 +376,8 @@ class Instrumenter : InstrumenterBase {
347376
if (auto *E = Element.dyn_cast<Expr *>()) {
348377
E->walk(CF);
349378

350-
Added<Stmt *> LogBefore = buildLoggerCall(E->getSourceRange(), true);
351-
Added<Stmt *> LogAfter = buildLoggerCall(E->getSourceRange(), false);
379+
Added<Stmt *> LogBefore = buildLoggerCall(LogBeforeName, E->getSourceRange());
380+
Added<Stmt *> LogAfter = buildLoggerCall(LogAfterName, E->getSourceRange());
352381

353382
if (*LogBefore && *LogAfter) {
354383
Elements[EI] = *LogBefore;
@@ -372,9 +401,9 @@ class Instrumenter : InstrumenterBase {
372401
ReturnStmt *NRS = new (Context) ReturnStmt(SourceLoc(), DRE,
373402
true); // implicit
374403
Added<Stmt *> LogBefore =
375-
buildLoggerCall(RS->getSourceRange(), true);
404+
buildLoggerCall(LogBeforeName, RS->getSourceRange());
376405
Added<Stmt *> LogAfter =
377-
buildLoggerCall(RS->getSourceRange(), false);
406+
buildLoggerCall(LogAfterName, RS->getSourceRange());
378407
if (*LogBefore && *LogAfter) {
379408
Elements[EI] = *LogBefore;
380409
Elements.insert(Elements.begin() + (EI + 1), PV.first);
@@ -385,9 +414,9 @@ class Instrumenter : InstrumenterBase {
385414
}
386415
} else {
387416
Added<Stmt *> LogBefore =
388-
buildLoggerCall(RS->getSourceRange(), true);
417+
buildLoggerCall(LogBeforeName, RS->getSourceRange());
389418
Added<Stmt *> LogAfter =
390-
buildLoggerCall(RS->getSourceRange(), false);
419+
buildLoggerCall(LogAfterName, RS->getSourceRange());
391420
if (*LogBefore && *LogAfter) {
392421
Elements[EI] = *LogBefore;
393422
Elements.insert(Elements.begin() + (EI + 1), *LogAfter);
@@ -396,8 +425,8 @@ class Instrumenter : InstrumenterBase {
396425
}
397426
}
398427
} else if (auto *CS = dyn_cast<ContinueStmt>(S)) {
399-
Added<Stmt *> LogBefore = buildLoggerCall(CS->getSourceRange(), true);
400-
Added<Stmt *> LogAfter = buildLoggerCall(CS->getSourceRange(), false);
428+
Added<Stmt *> LogBefore = buildLoggerCall(LogBeforeName, CS->getSourceRange());
429+
Added<Stmt *> LogAfter = buildLoggerCall(LogAfterName, CS->getSourceRange());
401430
if (*LogBefore && *LogAfter) {
402431
Elements[EI] = *LogBefore;
403432
Elements.insert(Elements.begin() + (EI + 1), *LogAfter);
@@ -406,8 +435,8 @@ class Instrumenter : InstrumenterBase {
406435
}
407436

408437
} else if (auto *BS = dyn_cast<BreakStmt>(S)) {
409-
Added<Stmt *> LogBefore = buildLoggerCall(BS->getSourceRange(), true);
410-
Added<Stmt *> LogAfter = buildLoggerCall(BS->getSourceRange(), false);
438+
Added<Stmt *> LogBefore = buildLoggerCall(LogBeforeName, BS->getSourceRange());
439+
Added<Stmt *> LogAfter = buildLoggerCall(LogAfterName, BS->getSourceRange());
411440
if (*LogBefore && *LogAfter) {
412441
Elements[EI] = *LogBefore;
413442
Elements.insert(Elements.begin() + (EI + 1), *LogAfter);
@@ -416,8 +445,8 @@ class Instrumenter : InstrumenterBase {
416445
}
417446

418447
} else if (auto *FS = dyn_cast<FallthroughStmt>(S)) {
419-
Added<Stmt *> LogBefore = buildLoggerCall(FS->getSourceRange(), true);
420-
Added<Stmt *> LogAfter = buildLoggerCall(FS->getSourceRange(), false);
448+
Added<Stmt *> LogBefore = buildLoggerCall(LogBeforeName, FS->getSourceRange());
449+
Added<Stmt *> LogAfter = buildLoggerCall(LogAfterName, FS->getSourceRange());
421450
if (*LogBefore && *LogAfter) {
422451
Elements[EI] = *LogBefore;
423452
Elements.insert(Elements.begin() + (EI + 1), *LogAfter);
@@ -443,8 +472,8 @@ class Instrumenter : InstrumenterBase {
443472
SR = PBD->getOriginalInitRange(0);
444473
}
445474

446-
Added<Stmt *> LogBefore = buildLoggerCall(SR, true);
447-
Added<Stmt *> LogAfter = buildLoggerCall(SR, false);
475+
Added<Stmt *> LogBefore = buildLoggerCall(LogBeforeName, SR);
476+
Added<Stmt *> LogAfter = buildLoggerCall(LogAfterName, SR);
448477

449478
if (*LogBefore && *LogAfter) {
450479
Elements[EI] = *LogBefore;
@@ -466,10 +495,8 @@ class Instrumenter : InstrumenterBase {
466495

467496
std::pair<PatternBindingDecl *, VarDecl *>
468497
buildPatternAndVariable(Expr *InitExpr) {
469-
// This is 16 because "pctmp" is 5 chars, %u is at most 10 digits long plus
470-
// a null terminator.
471-
char NameBuf[16] = {0};
472-
snprintf(NameBuf, sizeof(NameBuf), "pctmp%u", TmpNameIndex);
498+
SmallString<16> NameBuf;
499+
(Twine("pctmp") + Twine(TmpNameIndex)).toVector(NameBuf);
473500
TmpNameIndex++;
474501

475502
Expr *MaybeLoadInitExpr = nullptr;
@@ -496,19 +523,11 @@ class Instrumenter : InstrumenterBase {
496523
return std::make_pair(PBD, VD);
497524
}
498525

499-
Added<Stmt *> buildLoggerCall(SourceRange SR, bool isBefore) {
500-
if (isBefore) {
501-
return buildLoggerCallWithArgs(LogBeforeName, SR);
502-
} else {
503-
return buildLoggerCallWithArgs(LogAfterName, SR);
504-
}
505-
}
506-
507526
// Puts a pair of before/after calls at the start of the body, pointing at
508527
// that range.
509528
BraceStmt *prependLoggerCall(BraceStmt *BS, SourceRange SR) {
510-
Added<Stmt *> Before = buildLoggerCall(SR, true);
511-
Added<Stmt *> After = buildLoggerCall(SR, false);
529+
Added<Stmt *> Before = buildLoggerCall(LogBeforeName, SR);
530+
Added<Stmt *> After = buildLoggerCall(LogAfterName, SR);
512531

513532
ArrayRef<ASTNode> OriginalElements = BS->getElements();
514533
SmallVector<swift::ASTNode, 3> Elements(OriginalElements.begin(),
@@ -592,8 +611,7 @@ class Instrumenter : InstrumenterBase {
592611
return *AddedGet;
593612
}
594613

595-
Added<Stmt *> buildLoggerCallWithArgs(DeclNameRef LoggerName,
596-
SourceRange SR) {
614+
Added<Stmt *> buildLoggerCall(DeclNameRef LoggerName, SourceRange SR) {
597615
if (!SR.isValid()) {
598616
return nullptr;
599617
}
@@ -612,10 +630,9 @@ class Instrumenter : InstrumenterBase {
612630
Expr *ModuleExpr = buildIDArgumentExpr(ModuleIdentifier, SR);
613631
Expr *FileExpr = buildIDArgumentExpr(FileIdentifier, SR);
614632

615-
llvm::SmallVector<Expr *, 6> ArgsWithSourceRange{};
616-
617-
ArgsWithSourceRange.append(
618-
{StartLine, EndLine, StartColumn, EndColumn, ModuleExpr, FileExpr});
633+
llvm::SmallVector<Expr *, 6> ArgsWithSourceRange{
634+
StartLine, EndLine, StartColumn, EndColumn, ModuleExpr, FileExpr
635+
};
619636

620637
UnresolvedDeclRefExpr *LoggerRef = new (Context)
621638
UnresolvedDeclRefExpr(LoggerName,

lib/Sema/PlaygroundTransform.cpp

Lines changed: 31 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -342,14 +342,14 @@ class Instrumenter : InstrumenterBase {
342342
}
343343
}
344344

345-
std::string digForName(Expr *E) {
345+
DeclBaseName digForName(Expr *E) {
346346
Added<Expr *> RE = nullptr;
347347
ValueDecl *VD = nullptr;
348348
std::tie(RE, VD) = digForVariable(E);
349349
if (VD) {
350-
return VD->getBaseName().getIdentifier().str();
350+
return VD->getBaseName();
351351
} else {
352-
return std::string("");
352+
return DeclBaseName();
353353
}
354354
}
355355

@@ -417,14 +417,14 @@ class Instrumenter : InstrumenterBase {
417417
true); // implicit
418418
NAE->setType(Context.TheEmptyTupleType);
419419
AE->setImplicit(true);
420-
std::string Name = digForName(AE->getDest());
421420

422-
Added<Stmt *> Log(buildLoggerCall(
423-
new (Context) DeclRefExpr(
424-
ConcreteDeclRef(PV.second), DeclNameLoc(),
425-
true, // implicit
426-
AccessSemantics::Ordinary, AE->getSrc()->getType()),
427-
AE->getSrc()->getSourceRange(), Name.c_str()));
421+
DeclBaseName Name = digForName(AE->getDest());
422+
Expr * PVVarRef = new (Context) DeclRefExpr(
423+
ConcreteDeclRef(PV.second), DeclNameLoc(), /*implicit=*/ true,
424+
AccessSemantics::Ordinary, AE->getSrc()->getType());
425+
Added<Stmt *> Log(
426+
buildLoggerCall(PVVarRef, AE->getSrc()->getSourceRange(),
427+
Name.getIdentifier().str()));
428428

429429
if (*Log) {
430430
Elements[EI] = PV.first;
@@ -439,11 +439,11 @@ class Instrumenter : InstrumenterBase {
439439
if (auto *DRE = dyn_cast<DeclRefExpr>(AE->getFn())) {
440440
auto *FnD = dyn_cast<AbstractFunctionDecl>(DRE->getDecl());
441441
if (FnD && FnD->getModuleContext() == Context.TheStdlibModule) {
442-
StringRef FnName = FnD->getNameStr();
443-
if (FnName.equals("print") || FnName.equals("debugPrint")) {
442+
DeclBaseName FnName = FnD->getBaseName();
443+
if (FnName == "print" || FnName == "debugPrint") {
444444
const bool isOldStyle = false;
445445
if (isOldStyle) {
446-
const bool isDebugPrint = FnName.equals("debugPrint");
446+
const bool isDebugPrint = (FnName == "debugPrint");
447447
PatternBindingDecl *ArgPattern = nullptr;
448448
VarDecl *ArgVariable = nullptr;
449449
Added<Stmt *> Log =
@@ -620,39 +620,36 @@ class Instrumenter : InstrumenterBase {
620620
new (Context) DeclRefExpr(ConcreteDeclRef(VD), DeclNameLoc(),
621621
true, // implicit
622622
AccessSemantics::Ordinary, Type()),
623-
VD->getSourceRange(), VD->getName().str().str().c_str());
623+
VD->getSourceRange(), VD->getName().str());
624624
}
625625

626626
Added<Stmt *> logDeclOrMemberRef(Added<Expr *> RE) {
627627
if (auto *DRE = dyn_cast<DeclRefExpr>(*RE)) {
628628
VarDecl *VD = cast<VarDecl>(DRE->getDecl());
629629

630-
if (isa<ConstructorDecl>(TypeCheckDC) &&
631-
VD->getNameStr().equals("self")) {
630+
if (isa<ConstructorDecl>(TypeCheckDC) && VD->getBaseName() == "self") {
632631
// Don't log "self" in a constructor
633632
return nullptr;
634633
}
635634

636635
return buildLoggerCall(
637636
new (Context) DeclRefExpr(ConcreteDeclRef(VD), DeclNameLoc(),
638-
true, // implicit
639-
AccessSemantics::Ordinary, Type()),
640-
DRE->getSourceRange(), VD->getName().str().str().c_str());
637+
/*implicit=*/true),
638+
DRE->getSourceRange(), VD->getName().str());
641639
} else if (auto *MRE = dyn_cast<MemberRefExpr>(*RE)) {
642640
Expr *B = MRE->getBase();
643641
ConcreteDeclRef M = MRE->getMember();
644642

645-
if (isa<ConstructorDecl>(TypeCheckDC) && !digForName(B).compare("self")) {
643+
if (isa<ConstructorDecl>(TypeCheckDC) && digForName(B) == "self") {
646644
// Don't log attributes of "self" in a constructor
647645
return nullptr;
648646
}
649647

650648
return buildLoggerCall(
651649
new (Context) MemberRefExpr(B, SourceLoc(), M, DeclNameLoc(),
652-
true, // implicit
653-
AccessSemantics::Ordinary),
650+
/*implicit=*/true),
654651
MRE->getSourceRange(),
655-
M.getDecl()->getBaseName().getIdentifier().str().str().c_str());
652+
M.getDecl()->getBaseName().userFacingName());
656653
} else {
657654
return nullptr;
658655
}
@@ -738,11 +735,8 @@ class Instrumenter : InstrumenterBase {
738735

739736
std::pair<PatternBindingDecl *, VarDecl *>
740737
buildPatternAndVariable(Expr *InitExpr) {
741-
// This is 14 because "tmp" is 3 chars, %u is at most 10 digits long plus a
742-
// null terminator.
743-
char NameBuf[14] = {0};
744-
snprintf(NameBuf, sizeof(NameBuf), "tmp%u", TmpNameIndex);
745-
TmpNameIndex++;
738+
SmallString<16> NameBuf;
739+
(Twine("tmp") + Twine(TmpNameIndex)).toVector(NameBuf);
746740

747741
Expr *MaybeLoadInitExpr = nullptr;
748742

@@ -769,40 +763,27 @@ class Instrumenter : InstrumenterBase {
769763
}
770764

771765
Added<Stmt *> buildLoggerCall(Added<Expr *> E, SourceRange SR,
772-
const char *Name) {
773-
assert(Name);
774-
std::string *NameInContext = Context.AllocateObjectCopy(std::string(Name));
775-
776-
Expr *NameExpr =
777-
new (Context) StringLiteralExpr(NameInContext->c_str(), SourceRange());
778-
NameExpr->setImplicit(true);
766+
StringRef Name) {
767+
Expr *NameExpr = new (Context) StringLiteralExpr(
768+
Context.AllocateCopy(Name), SourceRange(), /*implicit=*/true);
779769

780770
std::uniform_int_distribution<unsigned> Distribution(0, 0x7fffffffu);
781771
const unsigned id_num = Distribution(RNG);
782772
Expr *IDExpr = IntegerLiteralExpr::createFromUnsigned(Context, id_num);
783773

784-
Expr *LoggerArgExprs[] = {*E, NameExpr, IDExpr};
785-
786-
return buildLoggerCallWithArgs(LogWithIDName,
787-
MutableArrayRef<Expr *>(LoggerArgExprs), SR);
774+
return buildLoggerCallWithArgs(LogWithIDName, { *E, NameExpr, IDExpr }, SR);
788775
}
789776

790777
Added<Stmt *> buildScopeEntry(SourceRange SR) {
791-
return buildScopeCall(SR, false);
778+
return buildLoggerCallWithArgs(LogScopeEntryName, {}, SR);
792779
}
793780

794781
Added<Stmt *> buildScopeExit(SourceRange SR) {
795-
return buildScopeCall(SR, true);
796-
}
797-
798-
Added<Stmt *> buildScopeCall(SourceRange SR, bool IsExit) {
799-
auto LoggerName = IsExit ? LogScopeExitName : LogScopeEntryName;
800-
801-
return buildLoggerCallWithArgs(LoggerName, MutableArrayRef<Expr *>(), SR);
782+
return buildLoggerCallWithArgs(LogScopeExitName, {}, SR);
802783
}
803784

804785
Added<Stmt *> buildLoggerCallWithArgs(DeclNameRef LoggerName,
805-
MutableArrayRef<Expr *> Args,
786+
ArrayRef<Expr *> Args,
806787
SourceRange SR) {
807788
// If something doesn't have a valid source range it can not be playground
808789
// logged. For example, a PC Macro event.
@@ -832,13 +813,10 @@ class Instrumenter : InstrumenterBase {
832813
UnresolvedDeclRefExpr *LoggerRef = new (Context)
833814
UnresolvedDeclRefExpr(LoggerName, DeclRefKind::Ordinary,
834815
DeclNameLoc(SR.End));
835-
836816
LoggerRef->setImplicit(true);
837817

838-
SmallVector<Identifier, 6> ArgLabels(ArgsWithSourceRange.size(),
839-
Identifier());
840-
ApplyExpr *LoggerCall = CallExpr::createImplicit(
841-
Context, LoggerRef, ArgsWithSourceRange, ArgLabels);
818+
ApplyExpr *LoggerCall = CallExpr::createImplicit(Context, LoggerRef,
819+
ArgsWithSourceRange, {});
842820
Added<ApplyExpr *> AddedLogger(LoggerCall);
843821

844822
if (!doTypeCheck(Context, TypeCheckDC, AddedLogger)) {

0 commit comments

Comments
 (0)