Home | History | Annotate | Download | only in slang
      1 /*
      2  * Copyright 2011, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "slang_rs_ast_replace.h"
     18 
     19 #include "slang_assert.h"
     20 
     21 #include "llvm/Support/Casting.h"
     22 
     23 namespace slang {
     24 
     25 void RSASTReplace::ReplaceStmt(
     26     clang::Stmt *OuterStmt,
     27     clang::Stmt *OldStmt,
     28     clang::Stmt *NewStmt) {
     29   mOldStmt = OldStmt;
     30   mNewStmt = NewStmt;
     31   mOuterStmt = OuterStmt;
     32 
     33   // This simplifies use in various Stmt visitor passes where the only
     34   // valid type is an Expr.
     35   mOldExpr = llvm::dyn_cast<clang::Expr>(OldStmt);
     36   if (mOldExpr) {
     37     mNewExpr = llvm::dyn_cast<clang::Expr>(NewStmt);
     38   }
     39   Visit(mOuterStmt);
     40 }
     41 
     42 void RSASTReplace::ReplaceInCompoundStmt(clang::CompoundStmt *CS) {
     43   clang::Stmt **UpdatedStmtList = new clang::Stmt*[CS->size()];
     44 
     45   unsigned UpdatedStmtCount = 0;
     46   clang::CompoundStmt::body_iterator bI = CS->body_begin();
     47   clang::CompoundStmt::body_iterator bE = CS->body_end();
     48 
     49   for ( ; bI != bE; bI++) {
     50     if (matchesStmt(*bI)) {
     51       UpdatedStmtList[UpdatedStmtCount++] = mNewStmt;
     52     } else {
     53       UpdatedStmtList[UpdatedStmtCount++] = *bI;
     54     }
     55   }
     56 
     57   CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
     58 
     59   delete [] UpdatedStmtList;
     60 
     61   return;
     62 }
     63 
     64 void RSASTReplace::VisitStmt(clang::Stmt *S) {
     65   // This function does the actual iteration through all sub-Stmt's within
     66   // a given Stmt. Note that this function is skipped by all of the other
     67   // Visit* functions if we have already found a higher-level match.
     68   for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
     69        I != E;
     70        I++) {
     71     if (clang::Stmt *Child = *I) {
     72       if (!matchesStmt(Child)) {
     73         Visit(Child);
     74       }
     75     }
     76   }
     77   return;
     78 }
     79 
     80 void RSASTReplace::VisitCompoundStmt(clang::CompoundStmt *CS) {
     81   VisitStmt(CS);
     82   ReplaceInCompoundStmt(CS);
     83   return;
     84 }
     85 
     86 void RSASTReplace::VisitCaseStmt(clang::CaseStmt *CS) {
     87   if (matchesStmt(CS->getSubStmt())) {
     88     CS->setSubStmt(mNewStmt);
     89   } else {
     90     VisitStmt(CS);
     91   }
     92   return;
     93 }
     94 
     95 void RSASTReplace::VisitDefaultStmt(clang::DefaultStmt *DS) {
     96   if (matchesStmt(DS->getSubStmt())) {
     97     DS->setSubStmt(mNewStmt);
     98   } else {
     99     VisitStmt(DS);
    100   }
    101   return;
    102 }
    103 
    104 void RSASTReplace::VisitDoStmt(clang::DoStmt *DS) {
    105   if (matchesExpr(DS->getCond())) {
    106     DS->setCond(mNewExpr);
    107   } else if (matchesStmt(DS->getBody())) {
    108     DS->setBody(mNewStmt);
    109   } else {
    110     VisitStmt(DS);
    111   }
    112   return;
    113 }
    114 
    115 void RSASTReplace::VisitForStmt(clang::ForStmt *FS) {
    116   if (matchesStmt(FS->getInit())) {
    117     FS->setInit(mNewStmt);
    118   } else if (matchesExpr(FS->getCond())) {
    119     FS->setCond(mNewExpr);
    120   } else if (matchesExpr(FS->getInc())) {
    121     FS->setInc(mNewExpr);
    122   } else if (matchesStmt(FS->getBody())) {
    123     FS->setBody(mNewStmt);
    124   } else {
    125     VisitStmt(FS);
    126   }
    127   return;
    128 }
    129 
    130 void RSASTReplace::VisitIfStmt(clang::IfStmt *IS) {
    131   if (matchesExpr(IS->getCond())) {
    132     IS->setCond(mNewExpr);
    133   } else if (matchesStmt(IS->getThen())) {
    134     IS->setThen(mNewStmt);
    135   } else if (matchesStmt(IS->getElse())) {
    136     IS->setElse(mNewStmt);
    137   } else {
    138     VisitStmt(IS);
    139   }
    140   return;
    141 }
    142 
    143 void RSASTReplace::VisitSwitchCase(clang::SwitchCase *SC) {
    144   slangAssert(false && "Both case and default have specialized handlers");
    145   VisitStmt(SC);
    146   return;
    147 }
    148 
    149 void RSASTReplace::VisitSwitchStmt(clang::SwitchStmt *SS) {
    150   if (matchesExpr(SS->getCond())) {
    151     SS->setCond(mNewExpr);
    152   } else {
    153     VisitStmt(SS);
    154   }
    155   return;
    156 }
    157 
    158 void RSASTReplace::VisitWhileStmt(clang::WhileStmt *WS) {
    159   if (matchesExpr(WS->getCond())) {
    160     WS->setCond(mNewExpr);
    161   } else if (matchesStmt(WS->getBody())) {
    162     WS->setBody(mNewStmt);
    163   } else {
    164     VisitStmt(WS);
    165   }
    166   return;
    167 }
    168 
    169 }  // namespace slang
    170