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


    在这一节中,对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     return ret;
    12 }
    13 
    14 
    15 int main() {
    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 namespace clang;
     25 using namespace clang::driver;
     26 using namespace clang::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 class LoopBound {
     33 public:
     34   int initVal;
     35   int maxVal;
     36   int incVal;
     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 = new LoopBound();
     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     return conditionMap;
    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 : public ASTConsumer {
    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 : public ASTFrontendAction {
    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 }

    结果展示如下:

  • 相关阅读:
    复制构造函数
    c++运算符优先级
    std::condition_variable(二)
    std::condition_variable
    std::unique_lock
    std::lock_guard
    Oracle 11gR2 11.2.0.1 ( 11.2.0.1的BUG?):ohasd不能正常启动:ioctl操作:npohasd的问题:【chmod a+wr /var/tmp/.oracle/npohasd】
    bat、cmd、dos窗口:后台调用,不显示黑色的控制台dos(命令行)窗口
    Ubuntu 安装 Oracle11gR2:'install' of makefile '/home/oracle/app/oracle/product/11.2.0/dbhome_1/ctx/lib/ins_ctx.mk'
    Ubuntu 10.04 安装 Oracle11gR2
  • 原文地址:https://www.cnblogs.com/jourluohua/p/14525428.html
Copyright © 2020-2023  润新知