3232#include " tsar/Support/Clang/Diagnostic.h"
3333#include " tsar/Support/Clang/Utils.h"
3434
35- #include " tsar/Analysis/Clang/GlobalInfoExtractor.h"
36-
3735#include < clang/AST/TypeLoc.h>
3836#include < clang/AST/Decl.h>
3937#include < clang/AST/Type.h>
4442#include < llvm/ADT/SmallString.h>
4543#include < clang/Basic/SourceLocation.h>
4644#include < llvm/ADT/StringSet.h>
47- // #include <llvm/IR/GlobalVariable.h>
4845#include < llvm/IR/DebugInfoMetadata.h>
4946#include < llvm/IR/Function.h>
5047#include < llvm/IR/Module.h>
5552#include < stack>
5653#include < iostream>
5754#include < deque>
55+ #include < map>
5856
5957using namespace llvm ;
6058using namespace clang ;
@@ -65,6 +63,19 @@ using namespace tsar;
6563
6664char ClangSplitDeclsPass::ID = 0 ;
6765
66+ struct notSingleDecl {
67+ bool isNotSingleFlag = false ;
68+ int varDeclsNum = 0 ;
69+ bool isFirstVar = true ;
70+ SourceLocation notSingleDeclStart;
71+ SourceLocation notSingleDeclEnd;
72+ std::deque<SourceLocation> starts;
73+ std::deque<SourceLocation> ends;
74+ std::deque<std::string> names;
75+ std::string varDeclType;
76+ };
77+
78+
6879INITIALIZE_PASS_IN_GROUP_BEGIN (ClangSplitDeclsPass, " clang-split" ,
6980 " Separation of variable declaration statements (Clang)" , false , false ,
7081 tsar::TransformationQueryManager::getPassRegistry ())
@@ -90,9 +101,9 @@ namespace {
90101// / other warnings.
91102class ClangSplitter : public RecursiveASTVisitor <ClangSplitter> {
92103public:
93- ClangSplitter (TransformationContext &TfmCtx, const ASTImportInfo &ImportInfo,
104+ ClangSplitter (TransformationContext &TfmCtx, const ASTImportInfo &ImportInfo, const GlobalInfoExtractor &GlobalInfo,
94105 ClangGlobalInfoPass::RawInfo &RawInfo) :
95- mTfmCtx (&TfmCtx), mImportInfo (ImportInfo),
106+ mTfmCtx (&TfmCtx), mImportInfo (ImportInfo), mGlobalInfo (GlobalInfo),
96107 mRawInfo (&RawInfo), mRewriter (TfmCtx.getRewriter()),
97108 mContext (TfmCtx.getContext()), mSrcMgr (mRewriter .getSourceMgr()),
98109 mLangOpts (mRewriter .getLangOpts()) {}
@@ -102,11 +113,11 @@ class ClangSplitter : public RecursiveASTVisitor<ClangSplitter> {
102113 return RecursiveASTVisitor::TraverseStmt (S);
103114 }
104115 Pragma P (*S); // the Pragma class is used to check if a statement is a pragma or not
116+ splitPragmaFlag = true ;
105117 if (findClause (P, ClauseId::SplitDeclaration, mClauses )) { // mClauses contains all SplitDeclaration pragmas
106118 llvm::SmallVector<clang::CharSourceRange, 8 > ToRemove; // a vector of statements that will match the root in the tree
107119 auto IsPossible = pragmaRangeToRemove (P, mClauses , mSrcMgr , mLangOpts ,
108120 mImportInfo , ToRemove); // ToRemove - the range of positions we want to remove
109- SplitDeclarationFlag = true ;
110121 if (!IsPossible.first )
111122 if (IsPossible.second & PragmaFlags::IsInMacro)
112123 toDiag (mSrcMgr .getDiagnostics (), mClauses .front ()->getBeginLoc (),
@@ -123,29 +134,60 @@ class ClangSplitter : public RecursiveASTVisitor<ClangSplitter> {
123134 RemoveEmptyLine.RemoveLineIfEmpty = false ;
124135 for (auto SR : ToRemove)
125136 mRewriter .RemoveText (SR, RemoveEmptyLine); // delete each range
126- if (isNotSingleFlag) {
127- SourceRange toInsert (notSingleDeclStart, notSingleDeclEnd);
137+ std::map<clang::SourceLocation, notSingleDecl>::iterator it;
138+ for (it = globalVarDeclsMap.begin (); it != globalVarDeclsMap.end (); it++) {
139+ if (it->second .isNotSingleFlag ) {
140+ SourceRange toInsert (it->second .notSingleDeclStart , it->second .notSingleDeclEnd );
141+ ExternalRewriter Canvas (toInsert, mSrcMgr , mLangOpts );
142+ std::cout << " Global range: " << Canvas.getRewrittenText (toInsert).str () << std::endl;
143+ mRewriter .RemoveText (toInsert, RemoveEmptyLine);
144+ }
145+ }
146+ if (localVarDecls.isNotSingleFlag ) {
147+ SourceRange toInsert (localVarDecls.notSingleDeclStart , localVarDecls.notSingleDeclEnd );
128148 mRewriter .RemoveText (toInsert, RemoveEmptyLine);
129149 }
130150 return true ;
131151 }
132152 Rewriter::RewriteOptions RemoveEmptyLine;
133153 RemoveEmptyLine.RemoveLineIfEmpty = false ;
154+ if (splitPragmaFlag) {
155+ if (localVarDecls.isNotSingleFlag ) {
156+ SourceRange toInsert (localVarDecls.notSingleDeclStart , localVarDecls.notSingleDeclEnd );
157+ mRewriter .RemoveText (toInsert, RemoveEmptyLine);
158+ while (localVarDecls.names .size ()) {
159+ if (localVarDecls.isFirstVar ) {
160+ mRewriter .InsertTextAfterToken (localVarDecls.notSingleDeclEnd , localVarDecls.names .back ());
161+ localVarDecls.isFirstVar = false ;
162+ } else {
163+ mRewriter .InsertTextAfterToken (localVarDecls.notSingleDeclEnd , localVarDecls.varDeclType + localVarDecls.names .back ());
164+ }
165+ localVarDecls.names .pop_back ();
166+ }
167+ }
134168
135- if (SplitDeclarationFlag && isNotSingleFlag) {
136- SourceRange toInsert (notSingleDeclStart, notSingleDeclEnd);
137- mRewriter .RemoveText (toInsert, RemoveEmptyLine);
138- while (varDeclsNames.size ()) {
139- if (isFirstVar) {
140- mRewriter .InsertTextAfterToken (notSingleDeclEnd, varDeclsNames.back ());
141- isFirstVar = false ;
142- } else {
143- mRewriter .InsertTextAfterToken (notSingleDeclEnd, varDeclType + varDeclsNames.back ());
169+ std::map<clang::SourceLocation, notSingleDecl>::iterator it;
170+ for (it = globalVarDeclsMap.begin (); it != globalVarDeclsMap.end (); it++) {
171+ if (it->second .isNotSingleFlag ) {
172+ // SourceRange toInsert(it->second.notSingleDeclStart, it->second.ends.back());
173+ SourceRange toInsert (it->second .notSingleDeclStart , it->second .ends .back ());
174+ mRewriter .RemoveText (toInsert, RemoveEmptyLine);
175+ while (it->second .names .size ()) {
176+ if (it->second .isFirstVar ) {
177+ mRewriter .InsertTextAfterToken (it->second .ends .back (), it->second .names .back ());
178+ it->second .isFirstVar = false ;
179+ } else {
180+ if (it->second .names .size () == 1 ) {
181+ mRewriter .InsertTextAfterToken (it->second .ends .back (), it->second .varDeclType + it->second .names .back ());
182+ } else {
183+ mRewriter .InsertTextAfterToken (it->second .ends .back (), it->second .varDeclType + it->second .names .back () + " ;\n " );
184+ }
185+ }
186+ it->second .names .pop_back ();
187+ }
144188 }
145- varDeclsNames.pop_back ();
146189 }
147190 }
148-
149191 if (mClauses .empty () || !isa<CompoundStmt>(S) &&
150192 !isa<ForStmt>(S) && !isa<DoStmt>(S) && !isa<WhileStmt>(S))
151193 return RecursiveASTVisitor::TraverseStmt (S);
@@ -176,72 +218,136 @@ class ClangSplitter : public RecursiveASTVisitor<ClangSplitter> {
176218 return Res;
177219 }
178220
221+ std::string getType (SourceLocation start, SourceLocation endLoc) {
222+ SourceRange varDeclRange (start, endLoc);
223+ std::string type = mRewriter .getRewrittenText (varDeclRange);
224+ std::cout << " type = " << type << std::endl;
225+ return type;
226+ }
227+
179228 bool TraverseTypeLoc (TypeLoc Loc) {
180- if (isNotSingleFlag && varDeclsNum == 1 ) {
181- SourceRange varDeclRange (start, Loc.getEndLoc ());
182- std::string type = mRewriter .getRewrittenText (varDeclRange);
183- std::cout << " type = " << type << std::endl;
184- varDeclType = type;
229+ std::map<clang::SourceLocation, notSingleDecl>::iterator it;
230+ if (localVarDecls.isNotSingleFlag && localVarDecls.varDeclsNum == 1 ) {
231+ localVarDecls.varDeclType = getType (start, Loc.getEndLoc ());
185232 return RecursiveASTVisitor::TraverseTypeLoc (Loc);
186233 }
234+ for (it = globalVarDeclsMap.begin (); it != globalVarDeclsMap.end (); it++) {
235+ if (it->second .varDeclsNum == 1 ) {
236+ it->second .varDeclType = getType (it->first , Loc.getEndLoc ());
237+ return RecursiveASTVisitor::TraverseTypeLoc (Loc);
238+ }
239+ }
187240 return true ;
188241 }
189242
190- bool VisitVarDecl (VarDecl *S) { // to traverse the parse tree and visit each statement
191- if (isNotSingleFlag) {
192- varDeclsNum++;
193- SourceRange toInsert (notSingleDeclStart, notSingleDeclEnd);
194- ExternalRewriter Canvas (toInsert, mSrcMgr , mLangOpts );
243+ void ProcessLocalDeclaration (VarDecl *S, SourceRange toInsert) {
244+ ExternalRewriter Canvas (toInsert, mSrcMgr , mLangOpts );
245+ SourceRange Range (S->getLocation ());
246+ std::cout << " Range: " << Canvas.getRewrittenText (Range).str () << std::endl;
247+ localVarDecls.starts .push_front (S->getBeginLoc ());
248+ localVarDecls.ends .push_front (S->getEndLoc ());
249+ SourceRange varDeclRange (S->getBeginLoc (), S->getEndLoc ());
250+ if (localVarDecls.varDeclsNum == 1 ) {
251+ localVarDecls.isFirstVar = true ;
252+ txtStr = Canvas.getRewrittenText (varDeclRange).str ();
253+ std::cout << " first localVarDeclsNum = " << localVarDecls.varDeclsNum << " " << txtStr << std::endl;
254+ }
255+ if (localVarDecls.varDeclsNum > 1 ) {
256+ SourceRange prevVarDeclRange (localVarDecls.starts .back (), localVarDecls.ends .back ());
257+ localVarDecls.starts .pop_back ();
258+ localVarDecls.ends .pop_back ();
259+ Canvas.ReplaceText (prevVarDeclRange, " " );
260+ txtStr = Canvas.getRewrittenText (varDeclRange).str ();
261+ std::cout << " varDeclsNum = " << localVarDecls.varDeclsNum << " " << txtStr << std::endl;
262+ auto it = std::remove (txtStr.begin (), txtStr.end (), ' ,' );
263+ txtStr.erase (it, txtStr.end ());
264+ std::cout << " varDeclsNum = " << localVarDecls.varDeclsNum << " " << txtStr << std::endl;
265+ }
266+ localVarDecls.names .push_front (txtStr + " ;\n " );
267+ }
268+
269+ void ProcessGlobalDeclaration (VarDecl *S, SourceRange toInsert) {
270+ ExternalRewriter Canvas (toInsert, mSrcMgr , mLangOpts );
271+ SourceRange Range (S->getLocation ());
272+ std::cout << " Range: " << Canvas.getRewrittenText (Range).str () << std::endl;
273+ globalVarDeclsMap[S->getBeginLoc ()].starts .push_front (S->getBeginLoc ());
274+ globalVarDeclsMap[S->getBeginLoc ()].ends .push_front (S->getEndLoc ());
275+ SourceRange varDeclRange (S->getBeginLoc (), S->getEndLoc ());
276+ if (globalVarDeclsMap[S->getBeginLoc ()].varDeclsNum == 1 ) {
277+ globalVarDeclsMap[S->getBeginLoc ()].isFirstVar = true ;
278+ txtStr = Canvas.getRewrittenText (varDeclRange).str ();
279+ std::cout << " first localVarDeclsNum = " << globalVarDeclsMap[S->getBeginLoc ()].varDeclsNum << " " << txtStr << std::endl;
280+
281+ globalVarDeclsMap[S->getBeginLoc ()].notSingleDeclStart = S->getBeginLoc ();
282+ globalVarDeclsMap[S->getBeginLoc ()].names .push_front (txtStr + " ;\n " );
283+ }
284+ if (globalVarDeclsMap[S->getBeginLoc ()].varDeclsNum > 1 ) {
285+ SourceRange prevVarDeclRange (globalVarDeclsMap[S->getBeginLoc ()].starts .back (), globalVarDeclsMap[S->getBeginLoc ()].ends .back ());
286+ globalVarDeclsMap[S->getBeginLoc ()].starts .pop_back ();
287+ globalVarDeclsMap[S->getBeginLoc ()].ends .pop_back ();
288+ Canvas.ReplaceText (prevVarDeclRange, " " );
289+ txtStr = Canvas.getRewrittenText (varDeclRange).str ();
290+ std::cout << " varDeclsNum = " << globalVarDeclsMap[S->getBeginLoc ()].varDeclsNum << " " << txtStr << std::endl;
291+ auto it = std::remove (txtStr.begin (), txtStr.end (), ' ,' );
292+ txtStr.erase (it, txtStr.end ());
293+ std::cout << " varDeclsNum = " << globalVarDeclsMap[S->getBeginLoc ()].varDeclsNum << " " << txtStr << std::endl;
195294
196- SourceRange Range (S->getLocation ());
197- std::cout << " Range: " << Canvas.getRewrittenText (Range).str () << std::endl;
198- varDeclsStarts.push_front (S->getBeginLoc ());
199- varDeclsEnds.push_front (S->getEndLoc ());
200- SourceRange varDeclRange (S->getBeginLoc (), S->getEndLoc ());
201- if (varDeclsNum == 1 ) {
202- isFirstVar = true ;
203- txtStr = Canvas.getRewrittenText (varDeclRange).str ();
204- std::cout << " first varDeclsNum = " << varDeclsNum << " " << txtStr << std::endl;
295+ globalVarDeclsMap[S->getBeginLoc ()].names .push_front (txtStr);
296+ }
297+ globalVarDeclsMap[S->getBeginLoc ()].notSingleDeclEnd = S->getEndLoc ();
298+ }
299+
300+ bool VisitVarDecl (VarDecl *S) { // to traverse the parse tree and visit each statement
301+ if (mGlobalInfo .findOutermostDecl (S)) {
302+ if (globalVarDeclsMap[S->getBeginLoc ()].varDeclsNum == 0 ) {
303+ std::map<clang::SourceLocation, notSingleDecl>::iterator it;
304+ for (it = globalVarDeclsMap.begin (); it != globalVarDeclsMap.end (); it++) {
305+ if (it->first != S->getBeginLoc ()) {
306+ it->second .starts .clear ();
307+ it->second .ends .clear ();
308+ it->second .names .clear ();
309+ globalVarDeclsMap.erase (it->first );
310+ }
311+ }
205312 }
206- if (varDeclsNum > 1 ) {
207- SourceRange prevVarDeclRange (varDeclsStarts.back (), varDeclsEnds.back ());
208- varDeclsStarts.pop_back ();
209- varDeclsEnds.pop_back ();
210- Canvas.ReplaceText (prevVarDeclRange, " " );
211- txtStr = Canvas.getRewrittenText (varDeclRange).str ();
212- auto it = std::remove (txtStr.begin (), txtStr.end (), ' ,' );
213- txtStr.erase (it, txtStr.end ());
214- size_t foundIndex = txtStr.find (" \n " );
215- if (foundIndex != std::string::npos)
216- txtStr.erase (foundIndex, 2 );
217- std::cout << " varDeclsNum = " << varDeclsNum << " " << txtStr << std::endl;
313+ if (globalVarDeclsMap[S->getBeginLoc ()].varDeclsNum == 1 ) {
314+ globalVarDeclsMap[S->getBeginLoc ()].isNotSingleFlag = true ;
218315 }
219- varDeclsNames.push_front (txtStr + " ;\n " );
316+ globalVarDeclsMap[S->getBeginLoc ()].varDeclsNum ++;
317+ SourceRange toInsert (S->getBeginLoc (), S->getEndLoc ());
318+ ProcessGlobalDeclaration (S, toInsert);
319+ }
320+ if (localVarDecls.isNotSingleFlag ) {
321+ localVarDecls.varDeclsNum ++;
322+ SourceRange toInsert (localVarDecls.notSingleDeclStart , localVarDecls.notSingleDeclEnd );
323+ ProcessLocalDeclaration (S, toInsert);
220324 }
221325 return true ;
222326 }
223327
328+
224329 bool VisitDeclStmt (DeclStmt *S) {
225330 if (!(S->isSingleDecl ())) {
226331 start = S->getBeginLoc ();
227- // if (!isNotSingleFlag) {
228- varDeclsNum = 0 ;
229- // }
230- varDeclsStarts .clear ();
231- varDeclsEnds. clear () ;
232- varDeclsNames. clear () ;
233- isNotSingleFlag = true ;
234- notSingleDeclStart = S->getBeginLoc ();
235- notSingleDeclEnd = S->getEndLoc ();
332+ localVarDecls. varDeclsNum = 0 ;
333+ localVarDecls. starts . clear () ;
334+ localVarDecls. ends . clear ();
335+ localVarDecls. names .clear ();
336+ localVarDecls. isNotSingleFlag = true ;
337+ std::cout << " IS NOT SINGLE \n " ;
338+ localVarDecls. notSingleDeclStart = S-> getBeginLoc () ;
339+ localVarDecls. notSingleDeclEnd = S->getEndLoc ();
340+ varPositions[S-> getBeginLoc ()] = S->getEndLoc ();
236341 } else {
237- isNotSingleFlag = false ;
342+ std::cout << " IS SINGLE\n " ;
343+ localVarDecls.isNotSingleFlag = false ;
238344 }
239345 return true ;
240346 }
241347
242348 bool VisitParmVarDecl (ParmVarDecl *S) {
243349 std::cout << " is ParmVarDecl" << std::endl;
244- isNotSingleFlag = false ;
350+ localVarDecls. isNotSingleFlag = false ;
245351 return true ;
246352 }
247353
@@ -266,35 +372,21 @@ class ClangSplitter : public RecursiveASTVisitor<ClangSplitter> {
266372
267373 TransformationContext *mTfmCtx ;
268374 const ASTImportInfo &mImportInfo ;
375+ const GlobalInfoExtractor &mGlobalInfo ;
376+
269377 ClangGlobalInfoPass::RawInfo *mRawInfo ;
270378 Rewriter &mRewriter ;
271379 ASTContext &mContext ;
272380 SourceManager &mSrcMgr ;
273381 const LangOptions &mLangOpts ;
274382 SmallVector<Stmt *, 1 > mClauses ;
275383 bool mActiveSplit = false ;
276- DenseSet<DeclStmt*> mMultipleDecls ;
277- std::deque<SourceLocation> varDeclsStarts;
278- std::deque<SourceLocation> varDeclsEnds;
279- std::deque<SourceLocation> starts;
280- std::deque<SourceLocation> ends;
281- std::deque<SourceRange> Ranges;
282- std::deque<std::string> varDeclsNames;
283- std::deque<std::string> names;
284- int varDeclsNum = 0 ;
285- int varsNum = 0 ;
286- SourceLocation notSingleDeclStart;
287- SourceLocation notSingleDeclEnd;
288- SourceLocation DeclStart;
289- SourceLocation DeclEnd;
290- SourceRange TypeRange;
291- bool SplitDeclarationFlag = false ;
292- bool isNotSingleFlag = false ;
293- bool isAfterNotSingleFlag = false ;
294- bool isFirstVar = true ;
384+ bool splitPragmaFlag = false ;
385+
386+ std::map<SourceLocation, notSingleDecl> globalVarDeclsMap;
387+ std::map<SourceLocation, SourceLocation> varPositions;
388+ notSingleDecl localVarDecls;
295389 std::string txtStr;
296- std::string varDeclType;
297- std::string DeclType;
298390 SourceLocation start;
299391};
300392}
@@ -326,7 +418,9 @@ bool ClangSplitDeclsPass::runOnModule(llvm::Module &M) {
326418 if (auto *ImportPass = getAnalysisIfAvailable<ImmutableASTImportInfoPass>())
327419 ImportInfo = &ImportPass->getImportInfo ();
328420 auto &GIP = getAnalysis<ClangGlobalInfoPass>();
329- ClangSplitter Vis (*TfmCtx, *ImportInfo, GIP.getRawInfo ());
421+ // mGlobalInfo = &GIP.getGlobalInfo();
422+ const auto &GlobalInfo = GIP.getGlobalInfo ();
423+ ClangSplitter Vis (*TfmCtx, *ImportInfo, GlobalInfo, GIP.getRawInfo ());
330424 Vis.TraverseDecl (TfmCtx->getContext ().getTranslationUnitDecl ());
331425 return false ;
332426 }
0 commit comments