-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[Draft] Summary Based Analysis Prototype #144224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 30 commits
7fba0ad
3d7d23a
2592f08
43c1b90
f1ea491
6fb6404
a45d2c0
e6b2107
da80bdb
4964c96
d8c26d3
b5465c1
1754b30
7e27c32
4f8acb9
d635e32
757c0d6
f511c22
6964f2c
81b039f
016dcdb
1155844
49937a6
2499ff2
d44d9d0
9e94174
41c286b
103956b
8a5a967
f71dd84
daccc50
0daa24f
e08fac7
8739704
8dfc609
da96155
03fc645
b125329
cfd792c
a2b8e2d
d3923ce
449adeb
8449340
767e3f9
0e88fa8
5d72937
bbfa385
cc3e507
6451e5b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| #ifndef LLVM_CLANG_SUMMARY_SUMMARYATTRIBUTE_H | ||
| #define LLVM_CLANG_SUMMARY_SUMMARYATTRIBUTE_H | ||
|
|
||
| #include "clang/AST/Decl.h" | ||
| #include "clang/ASTMatchers/ASTMatchFinder.h" | ||
|
|
||
| namespace clang { | ||
| enum SummaryAttrKind { | ||
| NO_WRITE_GLOBAL, | ||
| }; | ||
|
|
||
| class FunctionSummary; | ||
| class SummaryContext; | ||
|
|
||
| class SummaryAttr { | ||
| const SummaryAttrKind Kind; | ||
| const char *Spelling; | ||
|
|
||
| protected: | ||
| SummaryAttr(SummaryAttrKind Kind, const char *Spelling) | ||
| : Kind(Kind), Spelling(Spelling) {}; | ||
|
|
||
| public: | ||
| virtual ~SummaryAttr() = default; | ||
|
|
||
| SummaryAttrKind getKind() const { return Kind; } | ||
| const char *getSpelling() const { return Spelling; } | ||
|
|
||
| virtual bool infer(const FunctionDecl *FD) const = 0; | ||
| virtual bool merge(const FunctionSummary &Caller, | ||
| const FunctionSummary &Callee) const = 0; | ||
|
|
||
| virtual std::string serialize() const { return std::string(Spelling); }; | ||
| virtual bool parse(std::string_view input) const { | ||
| return input == Spelling; | ||
| }; | ||
| }; | ||
|
|
||
| class NoWriteGlobalAttr : public SummaryAttr { | ||
| NoWriteGlobalAttr() : SummaryAttr(NO_WRITE_GLOBAL, "no_write_global") {} | ||
|
|
||
| public: | ||
| bool infer(const FunctionDecl *FD) const override final; | ||
| bool merge(const FunctionSummary &Caller, | ||
| const FunctionSummary &Callee) const override final; | ||
|
|
||
| static bool classof(const SummaryAttr *A) { | ||
| return A->getKind() == NO_WRITE_GLOBAL; | ||
| } | ||
| friend class SummaryContext; | ||
| }; | ||
| } // namespace clang | ||
|
|
||
| #endif // LLVM_CLANG_SUMMARY_SUMMARYATTRIBUTEH |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| #ifndef LLVM_CLANG_SUMMARY_SUMMARYCONSUMER_H | ||
| #define LLVM_CLANG_SUMMARY_SUMMARYCONSUMER_H | ||
|
|
||
| #include "clang/Basic/LLVM.h" | ||
| #include "llvm/Support/JSON.h" | ||
| namespace clang { | ||
| class FunctionSummary; | ||
| class SummaryContext; | ||
|
|
||
| class SummaryConsumer { | ||
| protected: | ||
| const SummaryContext *SummaryCtx; | ||
|
|
||
| public: | ||
| SummaryConsumer(const SummaryContext &SummaryCtx) : SummaryCtx(&SummaryCtx) {} | ||
| virtual ~SummaryConsumer() = default; | ||
|
|
||
| virtual void ProcessStartOfSourceFile() {}; | ||
| virtual void ProcessFunctionSummary(const FunctionSummary &) {}; | ||
| virtual void ProcessEndOfSourceFile() {}; | ||
| }; | ||
|
|
||
| class PrintingSummaryConsumer : public SummaryConsumer { | ||
| public: | ||
| PrintingSummaryConsumer(const SummaryContext &SummaryCtx, raw_ostream &OS) | ||
| : SummaryConsumer(SummaryCtx) {} | ||
| }; | ||
|
|
||
| class JSONPrintingSummaryConsumer : public PrintingSummaryConsumer { | ||
| llvm::json::OStream JOS; | ||
|
|
||
| public: | ||
| JSONPrintingSummaryConsumer(const SummaryContext &SummaryCtx, raw_ostream &OS) | ||
| : PrintingSummaryConsumer(SummaryCtx, OS), JOS(OS, 2) {} | ||
|
|
||
| void ProcessStartOfSourceFile() override { JOS.arrayBegin(); }; | ||
| void ProcessFunctionSummary(const FunctionSummary &) override; | ||
| void ProcessEndOfSourceFile() override { | ||
| JOS.arrayEnd(); | ||
| JOS.flush(); | ||
| }; | ||
| }; | ||
| } // namespace clang | ||
|
|
||
| #endif // LLVM_CLANG_SUMMARY_SUMMARYCONSUMER_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| #ifndef LLVM_CLANG_SUMMARY_SUMMARYCONTEXT_H | ||
| #define LLVM_CLANG_SUMMARY_SUMMARYCONTEXT_H | ||
|
|
||
| #include "clang/Summary/SummaryAttribute.h" | ||
| #include "clang/Summary/SummaryConsumer.h" | ||
| #include <set> | ||
|
|
||
| namespace clang { | ||
| class FunctionSummary { | ||
| SmallVector<char> ID; | ||
|
||
| std::set<const SummaryAttr *> Attrs; | ||
| std::set<SmallVector<char>> Calls; | ||
|
|
||
| public: | ||
| FunctionSummary(SmallVector<char> ID, std::set<const SummaryAttr *> Attrs, | ||
| std::set<SmallVector<char>> Calls); | ||
|
|
||
| SmallVector<char> getID() const { return ID; } | ||
|
||
| const std::set<const SummaryAttr *> &getAttributes() const { return Attrs; } | ||
| const std::set<SmallVector<char>> &getCalls() const { return Calls; } | ||
|
|
||
| template <typename T> bool hasAttribute() const { | ||
| for (auto &&attr : Attrs) { | ||
| if (llvm::isa<T>(attr)) | ||
| return true; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| void replaceAttributes(std::set<const SummaryAttr *> Attrs) { | ||
| this->Attrs = std::move(Attrs); | ||
| } | ||
| }; | ||
|
|
||
| class SummaryContext { | ||
| std::map<SmallVector<char>, const FunctionSummary *> IDToSummary; | ||
| std::vector<std::unique_ptr<FunctionSummary>> FunctionSummaries; | ||
|
|
||
| std::map<SummaryAttrKind, const SummaryAttr *> KindToAttribute; | ||
| std::vector<std::unique_ptr<SummaryAttr>> Attributes; | ||
|
|
||
| void CreateSummary(SmallVector<char> ID, std::set<const SummaryAttr *> Attrs, | ||
| std::set<SmallVector<char>> Calls); | ||
| bool ReduceFunctionSummary(FunctionSummary &FunctionSummary); | ||
|
|
||
| template <typename T> void registerAttr(); | ||
|
|
||
| public: | ||
| SummaryContext(); | ||
|
|
||
| const FunctionSummary *GetSummary(const FunctionDecl *FD) const; | ||
| void SummarizeFunctionBody(const FunctionDecl *FD); | ||
|
|
||
| void ParseSummaryFromJSON(const llvm::json::Array &Summary); | ||
| void ReduceSummaries(); | ||
| }; | ||
| } // namespace clang | ||
|
|
||
| #endif // LLVM_CLANG_SUMMARY_SUMMARYCONTEXTH | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we assert here that we don't have a summary context yet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure tbh. I just mirrored what other create functions such as
CompilerInstance::createSema()do. Those don't assert the existence, so maybe the consumers of the class expect this kind of behaviour.