13
13
// This file implements the 'program counter simulation' for Swift.
14
14
// Based off the PlaygroundTransform, PCMacro instruments code to call
15
15
// 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.
16
45
//
17
46
// ===----------------------------------------------------------------------===//
18
47
@@ -347,8 +376,8 @@ class Instrumenter : InstrumenterBase {
347
376
if (auto *E = Element.dyn_cast <Expr *>()) {
348
377
E->walk (CF);
349
378
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 ());
352
381
353
382
if (*LogBefore && *LogAfter) {
354
383
Elements[EI] = *LogBefore;
@@ -372,9 +401,9 @@ class Instrumenter : InstrumenterBase {
372
401
ReturnStmt *NRS = new (Context) ReturnStmt (SourceLoc (), DRE,
373
402
true ); // implicit
374
403
Added<Stmt *> LogBefore =
375
- buildLoggerCall (RS->getSourceRange (), true );
404
+ buildLoggerCall (LogBeforeName, RS->getSourceRange ());
376
405
Added<Stmt *> LogAfter =
377
- buildLoggerCall (RS->getSourceRange (), false );
406
+ buildLoggerCall (LogAfterName, RS->getSourceRange ());
378
407
if (*LogBefore && *LogAfter) {
379
408
Elements[EI] = *LogBefore;
380
409
Elements.insert (Elements.begin () + (EI + 1 ), PV.first );
@@ -385,9 +414,9 @@ class Instrumenter : InstrumenterBase {
385
414
}
386
415
} else {
387
416
Added<Stmt *> LogBefore =
388
- buildLoggerCall (RS->getSourceRange (), true );
417
+ buildLoggerCall (LogBeforeName, RS->getSourceRange ());
389
418
Added<Stmt *> LogAfter =
390
- buildLoggerCall (RS->getSourceRange (), false );
419
+ buildLoggerCall (LogAfterName, RS->getSourceRange ());
391
420
if (*LogBefore && *LogAfter) {
392
421
Elements[EI] = *LogBefore;
393
422
Elements.insert (Elements.begin () + (EI + 1 ), *LogAfter);
@@ -396,8 +425,8 @@ class Instrumenter : InstrumenterBase {
396
425
}
397
426
}
398
427
} 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 ());
401
430
if (*LogBefore && *LogAfter) {
402
431
Elements[EI] = *LogBefore;
403
432
Elements.insert (Elements.begin () + (EI + 1 ), *LogAfter);
@@ -406,8 +435,8 @@ class Instrumenter : InstrumenterBase {
406
435
}
407
436
408
437
} 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 ());
411
440
if (*LogBefore && *LogAfter) {
412
441
Elements[EI] = *LogBefore;
413
442
Elements.insert (Elements.begin () + (EI + 1 ), *LogAfter);
@@ -416,8 +445,8 @@ class Instrumenter : InstrumenterBase {
416
445
}
417
446
418
447
} 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 ());
421
450
if (*LogBefore && *LogAfter) {
422
451
Elements[EI] = *LogBefore;
423
452
Elements.insert (Elements.begin () + (EI + 1 ), *LogAfter);
@@ -443,8 +472,8 @@ class Instrumenter : InstrumenterBase {
443
472
SR = PBD->getOriginalInitRange (0 );
444
473
}
445
474
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 );
448
477
449
478
if (*LogBefore && *LogAfter) {
450
479
Elements[EI] = *LogBefore;
@@ -466,10 +495,8 @@ class Instrumenter : InstrumenterBase {
466
495
467
496
std::pair<PatternBindingDecl *, VarDecl *>
468
497
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);
473
500
TmpNameIndex++;
474
501
475
502
Expr *MaybeLoadInitExpr = nullptr ;
@@ -496,19 +523,11 @@ class Instrumenter : InstrumenterBase {
496
523
return std::make_pair (PBD, VD);
497
524
}
498
525
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
-
507
526
// Puts a pair of before/after calls at the start of the body, pointing at
508
527
// that range.
509
528
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 );
512
531
513
532
ArrayRef<ASTNode> OriginalElements = BS->getElements ();
514
533
SmallVector<swift::ASTNode, 3 > Elements (OriginalElements.begin (),
@@ -592,8 +611,7 @@ class Instrumenter : InstrumenterBase {
592
611
return *AddedGet;
593
612
}
594
613
595
- Added<Stmt *> buildLoggerCallWithArgs (DeclNameRef LoggerName,
596
- SourceRange SR) {
614
+ Added<Stmt *> buildLoggerCall (DeclNameRef LoggerName, SourceRange SR) {
597
615
if (!SR.isValid ()) {
598
616
return nullptr ;
599
617
}
@@ -612,10 +630,9 @@ class Instrumenter : InstrumenterBase {
612
630
Expr *ModuleExpr = buildIDArgumentExpr (ModuleIdentifier, SR);
613
631
Expr *FileExpr = buildIDArgumentExpr (FileIdentifier, SR);
614
632
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
+ };
619
636
620
637
UnresolvedDeclRefExpr *LoggerRef = new (Context)
621
638
UnresolvedDeclRefExpr (LoggerName,
0 commit comments