|
1 | | -//=== RemoveFirstPrivate.cpp - (Clang) --*- C++ -*===// |
| 1 | +//=== DeadDeclsElimination.cpp - Dead Decls Elimination (Clang) --*- C++ -*===// |
2 | 2 | // |
3 | 3 | // Traits Static Analyzer (SAPFOR) |
4 | 4 | // |
|
18 | 18 | // |
19 | 19 | //===----------------------------------------------------------------------===// |
20 | 20 | // |
21 | | -// |
| 21 | +// This file implements a pass to initialize firstprivate variables. |
22 | 22 | // |
23 | 23 | //===----------------------------------------------------------------------===// |
24 | 24 |
|
|
31 | 31 | #include <clang/AST/Decl.h> |
32 | 32 | #include <clang/AST/RecursiveASTVisitor.h> |
33 | 33 | #include <clang/AST/Stmt.h> |
| 34 | +#include <clang/Basic/SourceLocation.h> |
34 | 35 | #include <llvm/ADT/DenseMap.h> |
35 | 36 | #include <llvm/ADT/DenseSet.h> |
36 | 37 | #include <llvm/ADT/SmallVector.h> |
|
39 | 40 | #include <llvm/Support/Debug.h> |
40 | 41 | #include <llvm/Support/raw_ostream.h> |
41 | 42 | #include <vector> |
| 43 | +#include <stack> |
42 | 44 |
|
43 | 45 | using namespace clang; |
44 | 46 | using namespace llvm; |
45 | 47 | using namespace tsar; |
46 | 48 |
|
47 | 49 | #undef DEBUG_TYPE |
48 | | -#define DEBUG_TYPE "remove-firstprivate" |
| 50 | +#define DEBUG_TYPE "clang-rfp" |
49 | 51 |
|
50 | 52 | char ClangRemoveFirstPrivate::ID = 0; |
51 | 53 |
|
52 | 54 | INITIALIZE_PASS_IN_GROUP_BEGIN(ClangRemoveFirstPrivate, "remove-firstprivate", |
53 | | - "Does something important", false, false, |
| 55 | + "Initialize variables in for", false, false, |
54 | 56 | TransformationQueryManager::getPassRegistry()) |
55 | 57 | INITIALIZE_PASS_DEPENDENCY(TransformationEnginePass) |
56 | 58 | INITIALIZE_PASS_DEPENDENCY(ClangGlobalInfoPass) |
57 | 59 | INITIALIZE_PASS_IN_GROUP_END(ClangRemoveFirstPrivate, "remove-firstprivate", |
58 | | - "Does something important", false, false, |
| 60 | + "Initialize variables in for", false, false, |
59 | 61 | TransformationQueryManager::getPassRegistry()) |
60 | 62 |
|
| 63 | +namespace { |
| 64 | + |
| 65 | +class DeclVisitor : public RecursiveASTVisitor<DeclVisitor> { |
| 66 | + struct DeclarationInfo { |
| 67 | + DeclarationInfo(Stmt *S) : Scope(S) {} |
| 68 | + |
| 69 | + Stmt *Scope; |
| 70 | + SmallVector<Stmt *, 16> DeadAccesses; |
| 71 | + }; |
| 72 | +public: |
| 73 | + explicit DeclVisitor(TransformationContext &TfmCtx, const ASTImportInfo &ImportInfo, |
| 74 | + ClangGlobalInfoPass::RawInfo &RawInfo) : |
| 75 | + mTfmCtx(&TfmCtx), mImportInfo(ImportInfo), |
| 76 | + mRawInfo(&RawInfo), mRewriter(TfmCtx.getRewriter()), |
| 77 | + mContext(TfmCtx.getContext()), mSrcMgr(mRewriter.getSourceMgr()), |
| 78 | + mLangOpts(mRewriter.getLangOpts()) {} |
| 79 | + |
| 80 | + bool TraverseStmt(Stmt *S) { |
| 81 | + if (!S) |
| 82 | + return true; |
| 83 | + |
| 84 | + bool ast = false; |
| 85 | + Pragma P(*S); |
| 86 | + |
| 87 | + if (findClause(P, ClauseId::RemoveFirstPrivate, mClauses)) { |
| 88 | + |
| 89 | + auto locationForInits = S -> getEndLoc(); |
| 90 | + |
| 91 | + isInPragma = true; |
| 92 | + ast = RecursiveASTVisitor::TraverseStmt(S); |
| 93 | + isInPragma = false; |
| 94 | + |
| 95 | + |
| 96 | + std::string txtStr; |
| 97 | + std::vector<std::string> inits; |
| 98 | + while (starts.size()) { |
| 99 | + SourceRange toInsert(starts.top(), ends.top()); |
| 100 | + CharSourceRange txtToInsert(toInsert, true); |
| 101 | + starts.pop(); |
| 102 | + ends.pop(); |
| 103 | + |
| 104 | + txtStr = mRewriter.getRewrittenText(txtToInsert); |
| 105 | + txtStr += ";\n"; |
| 106 | + inits.push_back(txtStr); |
| 107 | + } |
| 108 | + |
| 109 | + llvm::SmallVector<clang::CharSourceRange, 8> ToRemove; |
| 110 | + auto IsPossible = pragmaRangeToRemove(P, mClauses, mSrcMgr, mLangOpts, |
| 111 | + mImportInfo, ToRemove); |
| 112 | + if (!IsPossible.first) |
| 113 | + if (IsPossible.second & PragmaFlags::IsInMacro) |
| 114 | + toDiag(mSrcMgr.getDiagnostics(), mClauses.front()->getBeginLoc(), |
| 115 | + tsar::diag::warn_remove_directive_in_macro); |
| 116 | + else if (IsPossible.second & PragmaFlags::IsInHeader) |
| 117 | + toDiag(mSrcMgr.getDiagnostics(), mClauses.front()->getBeginLoc(), |
| 118 | + tsar::diag::warn_remove_directive_in_include); |
| 119 | + else |
| 120 | + toDiag(mSrcMgr.getDiagnostics(), mClauses.front()->getBeginLoc(), |
| 121 | + tsar::diag::warn_remove_directive); |
| 122 | + Rewriter::RewriteOptions RemoveEmptyLine; |
| 123 | + /// TODO ([email protected]): it seems that RemoveLineIfEmpty is |
| 124 | + /// set to true then removing (in RewriterBuffer) works incorrect. |
| 125 | + RemoveEmptyLine.RemoveLineIfEmpty = false; |
| 126 | + for (auto SR : ToRemove) |
| 127 | + mRewriter.RemoveText(SR, RemoveEmptyLine); // delete each range |
| 128 | + |
| 129 | + for (std::vector<std::string>::iterator it = inits.begin(); it != inits.end(); ++it) { |
| 130 | + mRewriter.InsertTextAfterToken(locationForInits, *it); |
| 131 | + } |
| 132 | + return ast; |
| 133 | + } |
| 134 | + return RecursiveASTVisitor::TraverseStmt(S); |
| 135 | + } |
| 136 | + |
| 137 | + bool TraverseDeclRefExpr(clang::DeclRefExpr *Ex) { |
| 138 | + NamedDecl *named = nullptr; |
| 139 | + if (isInPragma) { |
| 140 | + |
| 141 | + if (waitingForVar) { |
| 142 | + starts.push(Ex -> getLocation()); |
| 143 | + } else { |
| 144 | + ends.push(Ex -> getLocation()); |
| 145 | + } |
| 146 | + waitingForVar = !waitingForVar; |
| 147 | + } |
| 148 | + return RecursiveASTVisitor::TraverseDeclRefExpr(Ex); |
| 149 | + } |
61 | 150 |
|
| 151 | +#ifdef LLVM_DEBUG |
| 152 | +// debug info |
| 153 | +#endif |
| 154 | + |
| 155 | +private: |
| 156 | + /// Return current scope. |
| 157 | + Stmt *getScope() { |
| 158 | + for (auto I = mScopes.rbegin(), EI = mScopes.rend(); I != EI; ++I) |
| 159 | + if (isa<ForStmt>(*I) || isa<CompoundStmt>(*I)) |
| 160 | + return *I; |
| 161 | + return nullptr; |
| 162 | + } |
| 163 | + |
| 164 | + /// Return true if there is a side effect inside a specified statement. |
| 165 | + const Stmt * findSideEffect(const Stmt &S) { |
| 166 | + if (!isa<CallExpr>(S) && |
| 167 | + !(isa<BinaryOperator>(S) && cast<BinaryOperator>(S).isAssignmentOp()) && |
| 168 | + !(isa<UnaryOperator>(S) && |
| 169 | + cast<UnaryOperator>(S).isIncrementDecrementOp())) { |
| 170 | + for (auto Child : make_range(S.child_begin(), S.child_end())) |
| 171 | + if (Child) |
| 172 | + if (auto SideEffect = findSideEffect(*Child)) |
| 173 | + return SideEffect; |
| 174 | + return nullptr; |
| 175 | + } |
| 176 | + return &S; |
| 177 | + } |
| 178 | + |
| 179 | + bool isInPragma = false; |
| 180 | + bool waitingForVar = true; |
| 181 | + std::map<NamedDecl *, DeclarationInfo> mDeadDecls; |
| 182 | + std::vector<Stmt*> mScopes; |
| 183 | + // clang::Rewriter *mRewriter; |
| 184 | + DenseSet<DeclStmt*> mMultipleDecls; |
| 185 | + DenseMap<const clang::Type *, decltype(mDeadDecls)::const_iterator> mTypeDecls; |
| 186 | + DeclRefExpr *mSimpleAssignLHS = nullptr; |
| 187 | + |
| 188 | + TransformationContext *mTfmCtx; |
| 189 | + const ASTImportInfo &mImportInfo; |
| 190 | + ClangGlobalInfoPass::RawInfo *mRawInfo; |
| 191 | + Rewriter &mRewriter; |
| 192 | + ASTContext &mContext; |
| 193 | + SourceManager &mSrcMgr; |
| 194 | + const LangOptions &mLangOpts; |
| 195 | + SmallVector<Stmt *, 1> mClauses; |
| 196 | + |
| 197 | + std::stack<SourceLocation> starts; |
| 198 | + std::stack<SourceLocation> ends; |
| 199 | + |
| 200 | +}; |
| 201 | +} |
| 202 | + |
| 203 | +bool ClangRemoveFirstPrivate::runOnFunction(Function &F) { |
| 204 | + auto *M = F.getParent(); |
| 205 | + auto &TfmInfo = getAnalysis<TransformationEnginePass>(); |
| 206 | + auto *TfmCtx{TfmInfo ? TfmInfo->getContext(*M) : nullptr}; |
| 207 | + if (!TfmCtx || !TfmCtx->hasInstance()) { |
| 208 | + M->getContext().emitError("can not transform sources" |
| 209 | + ": transformation context is not available"); |
| 210 | + return false; |
| 211 | + } |
| 212 | + auto FuncDecl = TfmCtx->getDeclForMangledName(F.getName()); |
| 213 | + if (!FuncDecl) |
| 214 | + return false; |
| 215 | + |
| 216 | + ASTImportInfo ImportStub; |
| 217 | + const auto *ImportInfo = &ImportStub; |
| 218 | + if (auto *ImportPass = getAnalysisIfAvailable<ImmutableASTImportInfoPass>()) |
| 219 | + ImportInfo = &ImportPass->getImportInfo(); |
| 220 | + auto &GIP = getAnalysis<ClangGlobalInfoPass>(); |
| 221 | + |
| 222 | + DeclVisitor Visitor(*TfmCtx, *ImportInfo, GIP.getRawInfo()); |
| 223 | + Visitor.TraverseDecl(FuncDecl); |
| 224 | + return false; |
| 225 | +} |
62 | 226 |
|
63 | 227 | void ClangRemoveFirstPrivate::getAnalysisUsage(AnalysisUsage &AU) const { |
64 | 228 | AU.addRequired<TransformationEnginePass>(); |
65 | 229 | AU.addRequired<ClangGlobalInfoPass>(); |
66 | 230 | AU.setPreservesAll(); |
67 | 231 | } |
68 | 232 |
|
69 | | -bool ClangRemoveFirstPrivate::runOnModule(Module &M) { |
70 | | - return false; |
71 | | -} |
72 | | - |
73 | | -ModulePass *llvm::createClangRemoveFirstPrivate() { |
| 233 | +FunctionPass *llvm::createClangRemoveFirstPrivate() { |
74 | 234 | return new ClangRemoveFirstPrivate(); |
75 | 235 | } |
0 commit comments