Clang教程之实现源源变化(4)

摘要:
在这一节中,对loop-convert的例子进行了修改,以展示对ForStmt的处理。这里主要是通过AST树结构的判断,增加对类似for这种循环的循环界判断,在实际程序优化中,意义不是特别大,但是作为示例和练习还是不错的。主要使用的testcase是:1intfoo{2intret=0;3if(a˃b){4ret=a;5}else{6ret=b;7}8for{9*c=;10}11returnret;12}131415intmain(){16inta=1,b=2;17intc=0;18intd=foo;19return0;20}对ForStmt的处理在Visitor的VisitForStmt中进行1//------------------------------------------------------------------------------2//Toolingsample.Demonstrates:3//4//ForStmtDemotoshowhowtouseForStmt5//6//jourluohua7//Thiscodeisinthepublicdomain8//------------------------------------------------------------------------------9#include10#include11#include1213#include"clang/AST/AST.h"14#include"clang/AST/ASTConsumer.h"15#include"clang/AST/RecursiveASTVisitor.h"16#include"clang/Frontend/ASTConsumers.h"17#include"clang/Frontend/CompilerInstance.h"18#include"clang/Frontend/FrontendActions.h"19#include"clang/Rewrite/Core/Rewriter.h"20#include"clang/Tooling/CommonOptionsParser.h"21#include"clang/Tooling/Tooling.h"22#include"llvm/Support/raw_ostream.h"2324usingnamespaceclang;25usingnamespaceclang::driver;26usingnamespaceclang::tooling;2728staticllvm::cl::OptionCategoryToolingSampleCategory;2930//ByimplementingRecursiveASTVisitor,wecanspecifywhichASTnodes31//we'reinterestedinbyoverridingrelevantmethods.32classLoopBound{33public:34intinitVal;35intmaxVal;36intincVal;37LoopBound(){38initVal=0;39maxVal=0;40incVal=0;41}42};43classMyASTVisitor:publicRecursiveASTVisitor{44public:45MyASTVisitor:TheRewriter{}4647boolVisitForStmt{48//OnlycareaboutForStmtstatements.49//nowwejustjudgeforcase50VarDecl*initVar=nullptr;51Expr*initExpr=nullptr;52LoopBound*lpBound=newLoopBound();53DeclStmt*DS=nullptr;5455if((DS=dyn_cast_or_null(dyn_cast(forStmt)-˃getInit()))!

在这一节中,对loop-convert的例子进行了修改,以展示对ForStmt的处理。

这里主要是通过AST树结构的判断,增加对类似for(int i=0;i<5;i++)这种循环的循环界判断,在实际程序优化中,意义不是特别大,但是作为示例和练习还是不错的。

主要使用的test case是:

1 int foo(int a, int b, int *c) {
2     int ret = 0;
3     if (a >b) {
4         ret =a;
5     } else{
6         ret =b;
7 }
8     for (int temp = 0; temp < 100; ++temp) {
9         *c = (*c +temp);
10 }
11     returnret;
12 }
13 
14 
15 intmain() {
16     int a = 1, b = 2;
17     int c = 0;
18     int d = foo(a, b, &c);
19     return 0;
20 }

对ForStmt的处理在Visitor的VisitForStmt中进行(前排提示,不要尝试在RecursiveASTVisitor中对节点进行修改,大的节点修改会破坏整个AST树的Context,这里的Visitor仅建议作为遍历读取使用)

1 //------------------------------------------------------------------------------
2 //Tooling sample. Demonstrates:
3 //
4 //ForStmt Demo to show how to use ForStmt
5 //
6 //jourluohua (jourluohua@sina.com)
7 //This code is in the public domain
8 //------------------------------------------------------------------------------
9 #include <sstream>
10 #include <string>
11 #include <map>
12 
13 #include "clang/AST/AST.h"
14 #include "clang/AST/ASTConsumer.h"
15 #include "clang/AST/RecursiveASTVisitor.h"
16 #include "clang/Frontend/ASTConsumers.h"
17 #include "clang/Frontend/CompilerInstance.h"
18 #include "clang/Frontend/FrontendActions.h"
19 #include "clang/Rewrite/Core/Rewriter.h"
20 #include "clang/Tooling/CommonOptionsParser.h"
21 #include "clang/Tooling/Tooling.h"
22 #include "llvm/Support/raw_ostream.h"
23 
24 using namespaceclang;
25 using namespaceclang::driver;
26 using namespaceclang::tooling;
27 
28 static llvm::cl::OptionCategory ToolingSampleCategory("Tooling Sample");
29 
30 //By implementing RecursiveASTVisitor, we can specify which AST nodes
31 //we're interested in by overriding relevant methods.
32 classLoopBound {
33 public:
34   intinitVal;
35   intmaxVal;
36   intincVal;
37 LoopBound(){
38     initVal = 0;
39     maxVal  = 0;
40     incVal  = 0;
41 }
42 };
43 class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor>{
44 public:
45   MyASTVisitor(Rewriter &R) : TheRewriter(R) {}
46 
47   bool VisitForStmt(ForStmt *forStmt) {
48     //Only care about ForStmt statements.
49     //now we just judge for(int i=0;i<100;i++) case
50     VarDecl* initVar =nullptr;
51     Expr* initExpr =nullptr;
52     LoopBound* lpBound = newLoopBound();
53         DeclStmt* DS =nullptr;
54 
55     if ((DS = dyn_cast_or_null<DeclStmt>(dyn_cast<ForStmt>(forStmt)->getInit())) != 0 && DS->isSingleDecl() && 
56                (initVar = dyn_cast<VarDecl>(DS->getSingleDecl())) != 0){
57             initExpr = initVar->getInit();
58 }
59     else{
60       return true;
61 }
62     IntegerLiteral* initInteg = dyn_cast_or_null<IntegerLiteral>(initExpr);
63     lpBound->initVal = initInteg->getValue().getSExtValue();
64 
65     Expr *expCond = dyn_cast<ForStmt>(forStmt)->getCond();
66     if(isa<BinaryOperator>(expCond))
67 {
68       BinaryOperator *binaryOpCond = dyn_cast<BinaryOperator>(expCond);
69       if(binaryOpCond->getOpcode() ==BO_LT)
70 {
71         Expr * condExpr  = binaryOpCond ->getRHS();
72         assert(condExpr && "condExpr  ");
73         if(isa<IntegerLiteral>(condExpr))
74 {
75           lpBound->maxVal=(dyn_cast<IntegerLiteral>(condExpr)->getValue()).getSExtValue();
76 }
77         else
78 {
79           return true;
80 }
81 }
82       else
83 {
84         return true;
85 }
86 }
87     else
88 {
89       return true;
90 }
91 
92     Expr *incExpr = dyn_cast<ForStmt>(forStmt)->getInc();
93     assert(incExpr && "forStmt->getInc() cannot be NULL");
94     if(isa<UnaryOperator>(incExpr)){    
95       UnaryOperator *unaryInc = dyn_cast<UnaryOperator>(incExpr);
96       if(unaryInc->isIncrementOp () )        //just like '++i' or 'i++', we think that they work same  
97 {
98         lpBound->incVal = 1;
99 }
100       else
101 {
102         return true;
103 }
104       
105 }
106     conditionMap[initVar] =lpBound;
107     return true;
108 }
109 
110   std::map<VarDecl*, LoopBound*>&getCondMap(){
111     returnconditionMap;
112 }
113 
114 
115 private:
116   Rewriter &TheRewriter;
117   std::map<VarDecl*, LoopBound*>conditionMap;
118 };
119 
120 //Implementation of the ASTConsumer interface for reading an AST produced
121 //by the Clang parser.
122 class MyASTConsumer : publicASTConsumer {
123 public:
124   MyASTConsumer(Rewriter &R) : Visitor(R) {}
125 
126   //Override the method that gets called for each parsed top-level
127   //declaration.
128   bool HandleTopLevelDecl(DeclGroupRef DR) override{
129     for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
130       //Traverse the declaration using our AST visitor.
131       Visitor.TraverseDecl(*b);
132       (*b)->dump();
133 }
134     std::map<VarDecl*, LoopBound*> conditionMap =Visitor.getCondMap();
135     if(conditionMap.size()>0){
136       auto iter =conditionMap.begin();
137       LoopBound *lpFirst = iter->second;
138       VarDecl* varFirst = iter->first;
139       llvm::errs()<<varFirst->getDeclName().getAsString()<<"["<<lpFirst->initVal<<" "
140                   <<lpFirst->maxVal <<" "<<lpFirst->incVal<<"]
";
141 }
142     else{
143       llvm::errs()<<"conditionMap.size()==0
";
144 }
145     return true;
146 }
147 
148 private:
149 MyASTVisitor Visitor;
150 };
151 
152 //For each source file provided to the tool, a new FrontendAction is created.
153 class MyFrontendAction : publicASTFrontendAction {
154 public:
155 MyFrontendAction() {}
156   void EndSourceFileAction() override{
157     SourceManager &SM =TheRewriter.getSourceMgr();
158     llvm::errs() << "** EndSourceFileAction for: "
159                  << SM.getFileEntryForID(SM.getMainFileID())->getName() << "";
160 
161     //Now emit the rewritten buffer.
162 TheRewriter.getEditBuffer(SM.getMainFileID()).write(llvm::outs());
163 }
164 
165   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
166                                                  StringRef file) override{
167     llvm::errs() << "** Creating AST consumer for: " << file << "";
168 TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
169     return std::make_unique<MyASTConsumer>(TheRewriter);
170 }
171 
172 private:
173 Rewriter TheRewriter;
174 };
175 
176 int main(int argc, const char **argv) {
177   llvm::Expected<CommonOptionsParser> op=CommonOptionsParser::create(argc, argv, ToolingSampleCategory);
178   
179   ClangTool Tool(op.get().getCompilations(), op.get().getSourcePathList());
180 
181   //ClangTool::run accepts a FrontendActionFactory, which is then used to
182   //create new objects implementing the FrontendAction interface. Here we use
183   //the helper newFrontendActionFactory to create a default factory that will
184   //return a new MyFrontendAction object every time.
185   //To further customize this, we could create our own factory class.
186   return Tool.run(newFrontendActionFactory<MyFrontendAction>().get());
187 }

结果展示如下:

Clang教程之实现源源变化(4)第1张

免责声明:文章转载自《Clang教程之实现源源变化(4)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇mysql数据库binlog日志的异地备份A Simple OpenCASCADE Qt Demo-occQt下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

clang: error: linker command failed with exit code 1

之前在 macOS 10.13 上参照官方文档 build 了 LLVM 和 Clang,而在使用 clang++ 编译时有时会遇到如题的问题,具体报错信息如下: Undefined symbols for architecture x86_64: "std::string::compare(char const*) const", reference...

vs code C++ 代码格式化

简介 vscode 没有 vs 输入就格式化但是 也很方面右键点击 Format Document 格式化。 代码就很漂亮了。 其实还是推荐自动化保存C++ https://www.cnblogs.com/x_wukong/p/12643095.htmlclang-format 如果失效 参考链接 https://github.com/microsoft/...

C/C++ GCC/Clang生成和链接静态库/动态库

{ //http://www.360doc.com/content/14/0413/16/15099545_368549362.shtml } GCC/Clang生成和链接静态库/动态库 { 1 2 3 4 5 //add.cpp intadd(inta, intb) { returna + b; } 1 2 3 4 5 6 7...

Qt Creator- Beautifier插件代码格式化,使用 Clang Code Model

一 . 使用Clang Code模式来提醒语法和格式错误: 1. 在插件中勾选 ClangCodeModle选项 2. 新建检测配置, 进入 Tools→Options→C++, 在Code Model标签页,点击Manage按照需要编辑   ClangCodeModle配置(供参考): -Weverything -Wno-unused-macros -...

Zircon

 zircon代码下载 https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/zircon/ git clone https://github.com/timniederhausen/gn.git gn的编译需要使用clang编译器,并且gn使用了C++17的语法,所以需要使用较高版本的c...

LLVM每日谈之十四 如何给Clang添加一个属性

每次内容主要出自文档: “Clang” CFE Internals Manual地址: http://clang.llvm.org/docs/InternalsManual.html 在这个文档中,以简明的的一个例子说明了如何按照这个方式在Clang中添加一个属性。讲的很清楚,我在这里不再累述,只是将例子中的部分代码和文档结合起来,一起展现给大家。...