blob: 8ff3da518b7b7687def682aef203f18e0d2ed145 [file] [log] [blame]
Stephen Hines292e00a2011-03-18 19:11:30 -07001/*
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
Logan Chienab992e52011-07-20 22:06:52 +080021#include "llvm/Support/Casting.h"
22
Stephen Hines292e00a2011-03-18 19:11:30 -070023namespace slang {
24
25void 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.
Logan Chienab992e52011-07-20 22:06:52 +080035 mOldExpr = llvm::dyn_cast<clang::Expr>(OldStmt);
Stephen Hines292e00a2011-03-18 19:11:30 -070036 if (mOldExpr) {
Logan Chienab992e52011-07-20 22:06:52 +080037 mNewExpr = llvm::dyn_cast<clang::Expr>(NewStmt);
Stephen Hines292e00a2011-03-18 19:11:30 -070038 }
39 Visit(mOuterStmt);
40}
41
42void 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
64void 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
80void RSASTReplace::VisitCompoundStmt(clang::CompoundStmt *CS) {
81 VisitStmt(CS);
82 ReplaceInCompoundStmt(CS);
83 return;
84}
85
86void RSASTReplace::VisitCaseStmt(clang::CaseStmt *CS) {
87 if (matchesStmt(CS->getSubStmt())) {
88 CS->setSubStmt(mNewStmt);
89 } else {
90 VisitStmt(CS);
91 }
92 return;
93}
94
95void RSASTReplace::VisitDefaultStmt(clang::DefaultStmt *DS) {
96 if (matchesStmt(DS->getSubStmt())) {
97 DS->setSubStmt(mNewStmt);
98 } else {
99 VisitStmt(DS);
100 }
101 return;
102}
103
104void 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
115void 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
130void 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
143void RSASTReplace::VisitSwitchCase(clang::SwitchCase *SC) {
144 slangAssert(false && "Both case and default have specialized handlers");
145 VisitStmt(SC);
146 return;
147}
148
149void RSASTReplace::VisitSwitchStmt(clang::SwitchStmt *SS) {
150 if (matchesExpr(SS->getCond())) {
151 SS->setCond(mNewExpr);
152 } else {
153 VisitStmt(SS);
154 }
155 return;
156}
157
158void 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