-
Notifications
You must be signed in to change notification settings - Fork 10.4k
/
Copy pathInstrumenterSupport.h
114 lines (98 loc) · 3.48 KB
/
InstrumenterSupport.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//===--- InstrumenterSupport.h - Instrumenter Support -----------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements the supporting functions for writing instrumenters of
// the Swift AST.
//
//===----------------------------------------------------------------------===//
#include "TypeChecker.h"
#include "swift/AST/ASTWalker.h"
namespace swift {
namespace instrumenter_support {
template <class E> class Added {
private:
E Contents;
public:
Added() {}
Added(E NewContents) : Contents(NewContents) {}
Added(const Added<E> &rhs) : Contents(rhs.Contents) {}
const Added<E> &operator=(const Added<E> &rhs) {
Contents = rhs.Contents;
return *this;
}
E &operator*() { return Contents; }
E &operator->() { return Contents; }
};
class InstrumenterBase {
protected:
ASTContext &Context;
DeclContext *TypeCheckDC;
std::optional<DeclNameRef> ModuleIdentifier;
std::optional<DeclNameRef> FileIdentifier;
InstrumenterBase(ASTContext &C, DeclContext *DC);
virtual ~InstrumenterBase() = default;
virtual void anchor();
virtual BraceStmt *transformBraceStmt(BraceStmt *BS,
const ParameterList *PL = nullptr,
bool TopLevel = false) = 0;
/// Create an expression which retrieves a valid ModuleIdentifier or
/// FileIdentifier, if available.
Expr *buildIDArgumentExpr(std::optional<DeclNameRef> name, SourceRange SR);
class ClosureFinder : public ASTWalker {
private:
InstrumenterBase &I;
public:
ClosureFinder(InstrumenterBase &Inst) : I(Inst) {}
/// Walk only the expansion of the macro.
MacroWalking getMacroWalkingBehavior() const override {
return MacroWalking::Expansion;
}
PreWalkResult<Stmt *> walkToStmtPre(Stmt *S) override {
if (isa<BraceStmt>(S)) {
return Action::SkipNode(S); // don't walk into brace statements; we
// need to respect nesting!
} else {
return Action::Continue(S);
}
}
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
if (auto *CE = dyn_cast<ClosureExpr>(E)) {
BraceStmt *B = CE->getBody();
if (B) {
const ParameterList *PL = CE->getParameters();
BraceStmt *NB = I.transformBraceStmt(B, PL);
CE->setBody(NB);
// just with the entry and exit logging this is going to
// be more than a single expression!
}
}
return Action::Continue(E);
}
};
ClosureFinder CF;
template <class T>
bool doTypeCheck(ASTContext &Ctx, DeclContext *DC, Added<T *> &parsedExpr) {
Expr *E = *parsedExpr;
bool result = doTypeCheckImpl(Ctx, DC, E);
parsedExpr = Added<T *>(dyn_cast<T>(E));
return result;
}
// Type-check parsedExpr. Note that parsedExpr could end up being changed to
// a different kind of expr by the type checker.
bool doTypeCheckExpr(ASTContext &Ctx, DeclContext *DC, Expr *&parsedExpr) {
return doTypeCheckImpl(Ctx, DC, parsedExpr);
}
private:
bool doTypeCheckImpl(ASTContext &Ctx, DeclContext *DC, Expr * &parsedExpr);
};
}
}