18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 28b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Redistribution and use in source and binary forms, with or without 38b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// modification, are permitted provided that the following conditions are 48b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// met: 58b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// 68b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// * Redistributions of source code must retain the above copyright 78b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// notice, this list of conditions and the following disclaimer. 88b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// * Redistributions in binary form must reproduce the above 98b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// copyright notice, this list of conditions and the following 108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// disclaimer in the documentation and/or other materials provided 118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// with the distribution. 128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// * Neither the name of Google Inc. nor the names of its 138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// contributors may be used to endorse or promote products derived 148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// from this software without specific prior written permission. 158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// 168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// This is clang plugin used by gcmole tool. See README for more details. 298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/AST/AST.h" 318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/AST/ASTConsumer.h" 328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/AST/Mangle.h" 338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/AST/RecursiveASTVisitor.h" 348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/AST/StmtVisitor.h" 358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/Frontend/FrontendPluginRegistry.h" 368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/Frontend/CompilerInstance.h" 378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "llvm/Support/raw_ostream.h" 388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <bitset> 408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <fstream> 418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <iostream> 428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <map> 438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <set> 448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <stack> 458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochnamespace { 478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochtypedef std::string MangledName; 498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochtypedef std::set<MangledName> CalleesSet; 508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic bool GetMangledName(clang::MangleContext* ctx, 528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const clang::NamedDecl* decl, 538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch MangledName* result) { 548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!isa<clang::CXXConstructorDecl>(decl) && 558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch !isa<clang::CXXDestructorDecl>(decl)) { 568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch llvm::SmallVector<char, 512> output; 578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch llvm::raw_svector_ostream out(output); 588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ctx->mangleName(decl, out); 598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch *result = out.str().str(); 608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return true; 618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return false; 648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic bool InV8Namespace(const clang::NamedDecl* decl) { 688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return decl->getQualifiedNameAsString().compare(0, 4, "v8::") == 0; 698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic std::string EXTERNAL("EXTERNAL"); 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic std::string STATE_TAG("enum v8::internal::StateTag"); 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool IsExternalVMState(const clang::ValueDecl* var) { 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const clang::EnumConstantDecl* enum_constant = 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch dyn_cast<clang::EnumConstantDecl>(var); 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (enum_constant != NULL && enum_constant->getNameAsString() == EXTERNAL) { 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch clang::QualType type = enum_constant->getType(); 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return (type.getAsString() == STATE_TAG); 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 87257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstruct Resolver { 88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch explicit Resolver(clang::ASTContext& ctx) 89257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : ctx_(ctx), decl_ctx_(ctx.getTranslationUnitDecl()) { 90257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Resolver(clang::ASTContext& ctx, clang::DeclContext* decl_ctx) 93257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : ctx_(ctx), decl_ctx_(decl_ctx) { 94257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::DeclarationName ResolveName(const char* n) { 97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::IdentifierInfo* ident = &ctx_.Idents.get(n); 98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ctx_.DeclarationNames.getIdentifier(ident); 99257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Resolver ResolveNamespace(const char* n) { 102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Resolver(ctx_, Resolve<clang::NamespaceDecl>(n)); 103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch template<typename T> 106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch T* Resolve(const char* n) { 107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (decl_ctx_ == NULL) return NULL; 108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::DeclContext::lookup_result result = 110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch decl_ctx_->lookup(ResolveName(n)); 111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::DeclContext::lookup_iterator end = result.second; 113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (clang::DeclContext::lookup_iterator i = result.first; 114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch i != end; 115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch i++) { 116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (isa<T>(*i)) return cast<T>(*i); 117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return NULL; 120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::ASTContext& ctx_; 124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::DeclContext* decl_ctx_; 125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}; 126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass CalleesPrinter : public clang::RecursiveASTVisitor<CalleesPrinter> { 1298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public: 1308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch explicit CalleesPrinter(clang::MangleContext* ctx) : ctx_(ctx) { 1318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch virtual bool VisitCallExpr(clang::CallExpr* expr) { 1348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const clang::FunctionDecl* callee = expr->getDirectCallee(); 1358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (callee != NULL) AnalyzeFunction(callee); 1368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return true; 1378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual bool VisitDeclRefExpr(clang::DeclRefExpr* expr) { 1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If function mentions EXTERNAL VMState add artificial garbage collection 1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // mark. 1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (IsExternalVMState(expr->getDecl())) AddCallee("CollectGarbage"); 1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void AnalyzeFunction(const clang::FunctionDecl* f) { 1478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch MangledName name; 1488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (InV8Namespace(f) && GetMangledName(ctx_, f, &name)) { 1498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddCallee(name); 1508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const clang::FunctionDecl* body = NULL; 1528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (f->hasBody(body) && !Analyzed(name)) { 1538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch EnterScope(name); 1548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch TraverseStmt(body->getBody()); 1558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LeaveScope(); 1568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch typedef std::map<MangledName, CalleesSet* > Callgraph; 1618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool Analyzed(const MangledName& name) { 1638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return callgraph_[name] != NULL; 1648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void EnterScope(const MangledName& name) { 1678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CalleesSet* callees = callgraph_[name]; 1688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (callees == NULL) { 1708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch callgraph_[name] = callees = new CalleesSet(); 1718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch scopes_.push(callees); 1748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void LeaveScope() { 1778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch scopes_.pop(); 1788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void AddCallee(const MangledName& name) { 1818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!scopes_.empty()) scopes_.top()->insert(name); 1828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void PrintCallGraph() { 1858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for (Callgraph::const_iterator i = callgraph_.begin(), e = callgraph_.end(); 1868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch i != e; 1878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ++i) { 1888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch std::cout << i->first << "\n"; 1898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CalleesSet* callees = i->second; 1918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for (CalleesSet::const_iterator j = callees->begin(), e = callees->end(); 1928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch j != e; 1938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ++j) { 1948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch std::cout << "\t" << *j << "\n"; 1958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private: 2008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clang::MangleContext* ctx_; 2018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch std::stack<CalleesSet* > scopes_; 2038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Callgraph callgraph_; 2048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}; 2058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass FunctionDeclarationFinder 2088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : public clang::ASTConsumer, 2098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public clang::RecursiveASTVisitor<FunctionDeclarationFinder> { 2108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public: 2118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch explicit FunctionDeclarationFinder(clang::Diagnostic& d, 212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::SourceManager& sm, 213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const std::vector<std::string>& args) 2148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : d_(d), sm_(sm) { } 2158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch virtual void HandleTranslationUnit(clang::ASTContext &ctx) { 2178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch mangle_context_ = clang::createItaniumMangleContext(ctx, d_); 2188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch callees_printer_ = new CalleesPrinter(mangle_context_); 2198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch TraverseDecl(ctx.getTranslationUnitDecl()); 2218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch callees_printer_->PrintCallGraph(); 2238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 2248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch virtual bool VisitFunctionDecl(clang::FunctionDecl* decl) { 2268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch callees_printer_->AnalyzeFunction(decl); 2278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return true; 2288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 2298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private: 2318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clang::Diagnostic& d_; 2328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clang::SourceManager& sm_; 2338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clang::MangleContext* mangle_context_; 2348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CalleesPrinter* callees_printer_; 2368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}; 2378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic bool loaded = false; 2408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic CalleesSet gc_suspects; 2418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic void LoadGCSuspects() { 2448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (loaded) return; 2458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch std::ifstream fin("gcsuspects"); 2478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch std::string s; 2488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch while (fin >> s) gc_suspects.insert(s); 2508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch loaded = true; 2528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 2538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic bool KnownToCauseGC(clang::MangleContext* ctx, 2568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const clang::FunctionDecl* decl) { 2578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LoadGCSuspects(); 2588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!InV8Namespace(decl)) return false; 2608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch MangledName name; 2628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (GetMangledName(ctx, decl, &name)) { 2638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return gc_suspects.find(name) != gc_suspects.end(); 2648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 2658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return false; 2678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 2688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kNoEffect = 0; 271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kCausesGC = 1; 272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kRawDef = 2; 273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kRawUse = 4; 274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kAllEffects = kCausesGC | kRawDef | kRawUse; 2758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass Environment; 277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass ExprEffect { 279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public: 280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool hasGC() { return (effect_ & kCausesGC) != 0; } 281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void setGC() { effect_ |= kCausesGC; } 282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool hasRawDef() { return (effect_ & kRawDef) != 0; } 284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void setRawDef() { effect_ |= kRawDef; } 285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool hasRawUse() { return (effect_ & kRawUse) != 0; } 287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void setRawUse() { effect_ |= kRawUse; } 288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static ExprEffect None() { return ExprEffect(kNoEffect, NULL); } 290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static ExprEffect NoneWithEnv(Environment* env) { 291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ExprEffect(kNoEffect, env); 292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static ExprEffect RawUse() { return ExprEffect(kRawUse, NULL); } 294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static ExprEffect Merge(ExprEffect a, ExprEffect b); 296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static ExprEffect MergeSeq(ExprEffect a, ExprEffect b); 297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect Define(const std::string& name); 298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment* env() { 300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return reinterpret_cast<Environment*>(effect_ & ~kAllEffects); 301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static ExprEffect GC() { 3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ExprEffect(kCausesGC, NULL); 3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect(int effect, Environment* env) 309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : effect_((effect & kAllEffects) | 310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch reinterpret_cast<intptr_t>(env)) { } 311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch intptr_t effect_; 313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}; 314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochconst std::string BAD_EXPR_MSG("Possible problem with evaluation order."); 317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochconst std::string DEAD_VAR_MSG("Possibly dead variable."); 318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass Environment { 321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public: 322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment() { } 323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static Environment Unreachable() { 325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment env; 326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch env.live_.set(); 327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return env; 328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static Environment Merge(const Environment& l, 331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Environment& r) { 332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Environment(l, r); 333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment ApplyEffect(ExprEffect effect) const { 336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment out = effect.hasGC() ? Environment() : Environment(*this); 337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (effect.env() != NULL) out.live_ |= effect.env()->live_; 338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return out; 339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch typedef std::map<std::string, int> SymbolTable; 342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool IsAlive(const std::string& name) const { 344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SymbolTable::iterator code = symbol_table_.find(name); 345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (code == symbol_table_.end()) return false; 346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return live_[code->second]; 347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool Equal(const Environment& env) { 350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return live_ == env.live_; 351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment Define(const std::string& name) const { 354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Environment(*this, SymbolToCode(name)); 355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void MDefine(const std::string& name) { 358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch live_.set(SymbolToCode(name)); 359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static int SymbolToCode(const std::string& name) { 362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SymbolTable::iterator code = symbol_table_.find(name); 363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (code == symbol_table_.end()) { 365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int new_code = symbol_table_.size(); 366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch symbol_table_.insert(std::make_pair(name, new_code)); 367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return new_code; 3688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return code->second; 371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static void ClearSymbolTable() { 374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std::vector<Environment*>::iterator end = envs_.end(); 375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (std::vector<Environment*>::iterator i = envs_.begin(); 376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch i != end; 377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ++i) { 378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch delete *i; 379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch envs_.clear(); 381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch symbol_table_.clear(); 382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Print() const { 385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool comma = false; 386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std::cout << "{"; 387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SymbolTable::iterator end = symbol_table_.end(); 388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (SymbolTable::iterator i = symbol_table_.begin(); 389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch i != end; 390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ++i) { 391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (live_[i->second]) { 392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (comma) std::cout << ", "; 393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std::cout << i->first; 394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch comma = true; 3958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 3968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std::cout << "}"; 3988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 3998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static Environment* Allocate(const Environment& env) { 401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment* allocated_env = new Environment(env); 402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch envs_.push_back(allocated_env); 403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return allocated_env; 404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment(const Environment& l, const Environment& r) 408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : live_(l.live_ & r.live_) { 409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment(const Environment& l, int code) 412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : live_(l.live_) { 413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch live_.set(code); 414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static SymbolTable symbol_table_; 417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static std::vector<Environment* > envs_; 418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kMaxNumberOfLocals = 256; 420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std::bitset<kMaxNumberOfLocals> live_; 421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch friend class ExprEffect; 423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch friend class CallProps; 424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}; 425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass CallProps { 428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public: 429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallProps() : env_(NULL) { } 430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void SetEffect(int arg, ExprEffect in) { 432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (in.hasGC()) gc_.set(arg); 433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (in.hasRawDef()) raw_def_.set(arg); 434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (in.hasRawUse()) raw_use_.set(arg); 435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (in.env() != NULL) { 436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (env_ == NULL) env_ = in.env(); 437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch env_->live_ |= in.env()->live_; 438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect ComputeCumulativeEffect(bool result_is_raw) { 442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect out = ExprEffect::NoneWithEnv(env_); 443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (gc_.any()) out.setGC(); 444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (raw_use_.any()) out.setRawUse(); 445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (result_is_raw) out.setRawDef(); 446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return out; 447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool IsSafe() { 450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!gc_.any()) return true; 451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std::bitset<kMaxNumberOfArguments> raw = (raw_def_ | raw_use_); 452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!raw.any()) return true; 453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return gc_.count() == 1 && !((raw ^ gc_).any()); 454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kMaxNumberOfArguments = 64; 458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std::bitset<kMaxNumberOfArguments> raw_def_; 459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std::bitset<kMaxNumberOfArguments> raw_use_; 460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std::bitset<kMaxNumberOfArguments> gc_; 461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment* env_; 462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}; 463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochEnvironment::SymbolTable Environment::symbol_table_; 466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstd::vector<Environment* > Environment::envs_; 467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochExprEffect ExprEffect::Merge(ExprEffect a, ExprEffect b) { 470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment* a_env = a.env(); 471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment* b_env = b.env(); 472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment* out = NULL; 473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (a_env != NULL && b_env != NULL) { 474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out = Environment::Allocate(*a_env); 475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out->live_ &= b_env->live_; 476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ExprEffect(a.effect_ | b.effect_, out); 478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochExprEffect ExprEffect::MergeSeq(ExprEffect a, ExprEffect b) { 482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment* a_env = b.hasGC() ? NULL : a.env(); 483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment* b_env = b.env(); 484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment* out = (b_env == NULL) ? a_env : b_env; 485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (a_env != NULL && b_env != NULL) { 486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out = Environment::Allocate(*b_env); 487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out->live_ |= a_env->live_; 488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ExprEffect(a.effect_ | b.effect_, out); 4908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 4918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 4928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochExprEffect ExprEffect::Define(const std::string& name) { 494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment* e = env(); 495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (e == NULL) { 496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch e = Environment::Allocate(Environment()); 497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch e->MDefine(name); 499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ExprEffect(effect_, e); 500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic std::string THIS ("this"); 504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass FunctionAnalyzer { 5078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public: 508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FunctionAnalyzer(clang::MangleContext* ctx, 509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::DeclarationName handle_decl_name, 510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::CXXRecordDecl* object_decl, 511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::CXXRecordDecl* smi_decl, 512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::Diagnostic& d, 513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::SourceManager& sm, 514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool dead_vars_analysis) 515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : ctx_(ctx), 516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch handle_decl_name_(handle_decl_name), 517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch object_decl_(object_decl), 518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch smi_decl_(smi_decl), 519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch d_(d), 520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch sm_(sm), 521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block_(NULL), 522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dead_vars_analysis_(dead_vars_analysis) { 5238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -------------------------------------------------------------------------- 527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Expressions 528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -------------------------------------------------------------------------- 529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect VisitExpr(clang::Expr* expr, const Environment& env) { 531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define VISIT(type) do { \ 532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::type* concrete_expr = dyn_cast_or_null<clang::type>(expr); \ 533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (concrete_expr != NULL) { \ 534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Visit##type (concrete_expr, env); \ 535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } \ 536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } while(0); 537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(AbstractConditionalOperator); 539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(AddrLabelExpr); 540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(ArraySubscriptExpr); 541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(BinaryOperator); 542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(BinaryTypeTraitExpr); 543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(BlockDeclRefExpr); 544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(BlockExpr); 545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CallExpr); 546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CastExpr); 547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CharacterLiteral); 548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(ChooseExpr); 549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CompoundLiteralExpr); 550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXBindTemporaryExpr); 551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXBoolLiteralExpr); 552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXConstructExpr); 553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXDefaultArgExpr); 554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXDeleteExpr); 555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXDependentScopeMemberExpr); 556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXNewExpr); 557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXNoexceptExpr); 558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXNullPtrLiteralExpr); 559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXPseudoDestructorExpr); 560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXScalarValueInitExpr); 561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXThisExpr); 562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXThrowExpr); 563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXTypeidExpr); 564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXUnresolvedConstructExpr); 565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXUuidofExpr); 566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(DeclRefExpr); 567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(DependentScopeDeclRefExpr); 568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(DesignatedInitExpr); 569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(ExprWithCleanups); 570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(ExtVectorElementExpr); 571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(FloatingLiteral); 572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(GNUNullExpr); 573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(ImaginaryLiteral); 574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(ImplicitValueInitExpr); 575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(InitListExpr); 576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(IntegerLiteral); 577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(MemberExpr); 578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(OffsetOfExpr); 579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(OpaqueValueExpr); 580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(OverloadExpr); 581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(PackExpansionExpr); 582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(ParenExpr); 583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(ParenListExpr); 584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(PredefinedExpr); 585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(ShuffleVectorExpr); 586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(SizeOfPackExpr); 587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(StmtExpr); 588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(StringLiteral); 589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(SubstNonTypeTemplateParmPackExpr); 590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(UnaryExprOrTypeTraitExpr); 591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(UnaryOperator); 592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(UnaryTypeTraitExpr); 593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(VAArgExpr); 594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#undef VISIT 595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ExprEffect::None(); 5978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define DECL_VISIT_EXPR(type) \ 600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect Visit##type (clang::type* expr, const Environment& env) 6018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define IGNORE_EXPR(type) \ 603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect Visit##type (clang::type* expr, const Environment& env) { \ 604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ExprEffect::None(); \ 605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(AddrLabelExpr); 608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(BinaryTypeTraitExpr); 609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(BlockExpr); 610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(CharacterLiteral); 611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(ChooseExpr); 612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(CompoundLiteralExpr); 613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(CXXBoolLiteralExpr); 614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(CXXDependentScopeMemberExpr); 615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(CXXNullPtrLiteralExpr); 616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(CXXPseudoDestructorExpr); 617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(CXXScalarValueInitExpr); 618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(CXXNoexceptExpr); 619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(CXXTypeidExpr); 620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(CXXUnresolvedConstructExpr); 621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(CXXUuidofExpr); 622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(DependentScopeDeclRefExpr); 623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(DesignatedInitExpr); 624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(ExtVectorElementExpr); 625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(FloatingLiteral); 626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(ImaginaryLiteral); 627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(IntegerLiteral); 628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(OffsetOfExpr); 629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(ImplicitValueInitExpr); 630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(PackExpansionExpr); 631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(PredefinedExpr); 632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(ShuffleVectorExpr); 633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(SizeOfPackExpr); 634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(StmtExpr); 635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(StringLiteral); 636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(SubstNonTypeTemplateParmPackExpr); 637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(UnaryExprOrTypeTraitExpr); 638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(UnaryTypeTraitExpr); 639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(VAArgExpr); 640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(GNUNullExpr); 641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_EXPR(OverloadExpr); 642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(CXXThisExpr) { 644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Use(expr, expr->getType(), THIS, env); 645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(AbstractConditionalOperator) { 648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment after_cond = env.ApplyEffect(VisitExpr(expr->getCond(), env)); 649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ExprEffect::Merge(VisitExpr(expr->getTrueExpr(), after_cond), 650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitExpr(expr->getFalseExpr(), after_cond)); 651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(ArraySubscriptExpr) { 654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::Expr* exprs[2] = {expr->getBase(), expr->getIdx()}; 655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Par(expr, 2, exprs, env); 656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool IsRawPointerVar(clang::Expr* expr, std::string* var_name) { 659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (isa<clang::BlockDeclRefExpr>(expr)) { 660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch *var_name = cast<clang::BlockDeclRefExpr>(expr)->getDecl()-> 661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch getNameAsString(); 662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return true; 663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (isa<clang::DeclRefExpr>(expr)) { 664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch *var_name = cast<clang::DeclRefExpr>(expr)->getDecl()->getNameAsString(); 665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return true; 6668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return false; 6688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(BinaryOperator) { 671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::Expr* lhs = expr->getLHS(); 672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::Expr* rhs = expr->getRHS(); 673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::Expr* exprs[2] = {lhs, rhs}; 674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (expr->getOpcode()) { 676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case clang::BO_Comma: 677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Seq(expr, 2, exprs, env); 678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case clang::BO_LAnd: 680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case clang::BO_LOr: 681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ExprEffect::Merge(VisitExpr(lhs, env), VisitExpr(rhs, env)); 682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case clang::BO_Assign: { 684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std::string var_name; 685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (IsRawPointerVar(lhs, &var_name)) { 686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitExpr(rhs, env).Define(var_name); 687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Par(expr, 2, exprs, env); 689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: 692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Par(expr, 2, exprs, env); 693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(CXXBindTemporaryExpr) { 697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitExpr(expr->getSubExpr(), env); 6988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(CXXConstructExpr) { 701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitArguments<>(expr, env); 702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(CXXDefaultArgExpr) { 705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitExpr(expr->getExpr(), env); 706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(CXXDeleteExpr) { 709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitExpr(expr->getArgument(), env); 710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(CXXNewExpr) { 713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Par(expr, 714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch expr->getNumConstructorArgs(), 715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch expr->getConstructorArgs(), 716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch env); 717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(ExprWithCleanups) { 720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitExpr(expr->getSubExpr(), env); 721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(CXXThrowExpr) { 724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitExpr(expr->getSubExpr(), env); 725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(InitListExpr) { 728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Seq(expr, expr->getNumInits(), expr->getInits(), env); 729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(MemberExpr) { 732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitExpr(expr->getBase(), env); 733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(OpaqueValueExpr) { 736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitExpr(expr->getSourceExpr(), env); 737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(ParenExpr) { 740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitExpr(expr->getSubExpr(), env); 741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(ParenListExpr) { 744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Par(expr, expr->getNumExprs(), expr->getExprs(), env); 745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(UnaryOperator) { 748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // TODO We are treating all expressions that look like &raw_pointer_var 749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // as definitions of raw_pointer_var. This should be changed to 750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // recognize less generic pattern: 751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // if (maybe_object->ToObject(&obj)) return maybe_object; 753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (expr->getOpcode() == clang::UO_AddrOf) { 755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std::string var_name; 756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (IsRawPointerVar(expr->getSubExpr(), &var_name)) { 757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ExprEffect::None().Define(var_name); 758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitExpr(expr->getSubExpr(), env); 761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(CastExpr) { 764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitExpr(expr->getSubExpr(), env); 765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(DeclRefExpr) { 768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Use(expr, expr->getDecl(), env); 769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_EXPR(BlockDeclRefExpr) { 772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Use(expr, expr->getDecl(), env); 773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect Par(clang::Expr* parent, 776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int n, 777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::Expr** exprs, 778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Environment& env) { 779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallProps props; 780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < n; ++i) { 782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch props.SetEffect(i, VisitExpr(exprs[i], env)); 783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!props.IsSafe()) ReportUnsafe(parent, BAD_EXPR_MSG); 786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return props.ComputeCumulativeEffect(IsRawPointerType(parent->getType())); 788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect Seq(clang::Stmt* parent, 791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int n, 792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::Expr** exprs, 793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Environment& env) { 794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect out = ExprEffect::None(); 795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment out_env = env; 796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < n; ++i) { 797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out = ExprEffect::MergeSeq(out, VisitExpr(exprs[i], out_env)); 798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out_env = out_env.ApplyEffect(out); 799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return out; 801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect Use(const clang::Expr* parent, 804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const clang::QualType& var_type, 805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const std::string& var_name, 806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Environment& env) { 807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (IsRawPointerType(var_type)) { 808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!env.IsAlive(var_name) && dead_vars_analysis_) { 809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ReportUnsafe(parent, DEAD_VAR_MSG); 8108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ExprEffect::RawUse(); 8128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return ExprEffect::None(); 814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect Use(const clang::Expr* parent, 817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const clang::ValueDecl* var, 818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Environment& env) { 8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (IsExternalVMState(var)) { 8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ExprEffect::GC(); 8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Use(parent, var->getType(), var->getNameAsString(), env); 823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 8258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch template<typename ExprType> 827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect VisitArguments(ExprType* call, const Environment& env) { 828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallProps props; 829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitArguments<>(call, &props, env); 830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!props.IsSafe()) ReportUnsafe(call, BAD_EXPR_MSG); 831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return props.ComputeCumulativeEffect(IsRawPointerType(call->getType())); 832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch template<typename ExprType> 835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void VisitArguments(ExprType* call, 836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallProps* props, 837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Environment& env) { 8388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for (unsigned arg = 0; arg < call->getNumArgs(); arg++) { 839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch props->SetEffect(arg + 1, VisitExpr(call->getArg(arg), env)); 8408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 8418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 8428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect VisitCallExpr(clang::CallExpr* call, 845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Environment& env) { 846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallProps props; 8478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 8488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clang::CXXMemberCallExpr* memcall = 8498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch dyn_cast_or_null<clang::CXXMemberCallExpr>(call); 850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (memcall != NULL) { 851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::Expr* receiver = memcall->getImplicitObjectArgument(); 852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch props.SetEffect(0, VisitExpr(receiver, env)); 8538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 8548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitArguments<>(call, &props, env); 856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!props.IsSafe()) ReportUnsafe(call, BAD_EXPR_MSG); 858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExprEffect out = 860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch props.ComputeCumulativeEffect(IsRawPointerType(call->getType())); 861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::FunctionDecl* callee = call->getDirectCallee(); 863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if ((callee != NULL) && KnownToCauseGC(ctx_, callee)) { 864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out.setGC(); 865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return out; 868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -------------------------------------------------------------------------- 871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Statements 872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -------------------------------------------------------------------------- 873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment VisitStmt(clang::Stmt* stmt, const Environment& env) { 875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define VISIT(type) do { \ 876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::type* concrete_stmt = dyn_cast_or_null<clang::type>(stmt); \ 877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (concrete_stmt != NULL) { \ 878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Visit##type (concrete_stmt, env); \ 879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } \ 880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } while(0); 881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (clang::Expr* expr = dyn_cast_or_null<clang::Expr>(stmt)) { 883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return env.ApplyEffect(VisitExpr(expr, env)); 884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(AsmStmt); 887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(BreakStmt); 888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CompoundStmt); 889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(ContinueStmt); 890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXCatchStmt); 891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CXXTryStmt); 892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(DeclStmt); 893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(DoStmt); 894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(ForStmt); 895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(GotoStmt); 896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(IfStmt); 897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(IndirectGotoStmt); 898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(LabelStmt); 899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(NullStmt); 900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(ReturnStmt); 901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(CaseStmt); 902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(DefaultStmt); 903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(SwitchStmt); 904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VISIT(WhileStmt); 905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#undef VISIT 906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return env; 908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define DECL_VISIT_STMT(type) \ 911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment Visit##type (clang::type* stmt, const Environment& env) 912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define IGNORE_STMT(type) \ 914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment Visit##type (clang::type* stmt, const Environment& env) { \ 915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return env; \ 916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_STMT(IndirectGotoStmt); 919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_STMT(NullStmt); 920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_STMT(AsmStmt); 921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We are ignoring control flow for simplicity. 923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_STMT(GotoStmt); 924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_STMT(LabelStmt); 925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We are ignoring try/catch because V8 does not use them. 927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_STMT(CXXCatchStmt); 928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IGNORE_STMT(CXXTryStmt); 929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch class Block { 931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public: 932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Block(const Environment& in, 933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FunctionAnalyzer* owner) 934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : in_(in), 935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out_(Environment::Unreachable()), 936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch changed_(false), 937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch owner_(owner) { 938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch parent_ = owner_->EnterBlock(this); 939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ~Block() { 942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch owner_->LeaveBlock(parent_); 943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void MergeIn(const Environment& env) { 946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment old_in = in_; 947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch in_ = Environment::Merge(in_, env); 948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch changed_ = !old_in.Equal(in_); 949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool changed() { 952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (changed_) { 953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch changed_ = false; 954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return true; 955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return false; 957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Environment& in() { 960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return in_; 961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const Environment& out() { 964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return out_; 965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void MergeOut(const Environment& env) { 968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out_ = Environment::Merge(out_, env); 969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Seq(clang::Stmt* a, clang::Stmt* b, clang::Stmt* c) { 972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment a_out = owner_->VisitStmt(a, in()); 973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment b_out = owner_->VisitStmt(b, a_out); 974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment c_out = owner_->VisitStmt(c, b_out); 975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MergeOut(c_out); 976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Seq(clang::Stmt* a, clang::Stmt* b) { 979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment a_out = owner_->VisitStmt(a, in()); 980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment b_out = owner_->VisitStmt(b, a_out); 981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MergeOut(b_out); 982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Loop(clang::Stmt* a, clang::Stmt* b, clang::Stmt* c) { 985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Seq(a, b, c); 986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MergeIn(out()); 987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Loop(clang::Stmt* a, clang::Stmt* b) { 990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Seq(a, b); 991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MergeIn(out()); 9928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment in_; 997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment out_; 998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool changed_; 999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FunctionAnalyzer* owner_; 1000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Block* parent_; 1001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch }; 1002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_STMT(BreakStmt) { 1005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block_->MergeOut(env); 1006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Environment::Unreachable(); 1007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_STMT(ContinueStmt) { 1010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block_->MergeIn(env); 1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Environment::Unreachable(); 1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_STMT(CompoundStmt) { 1015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment out = env; 1016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::CompoundStmt::body_iterator end = stmt->body_end(); 1017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (clang::CompoundStmt::body_iterator s = stmt->body_begin(); 1018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch s != end; 1019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ++s) { 1020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out = VisitStmt(*s, out); 1021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return out; 1023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_STMT(WhileStmt) { 1026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Block block (env, this); 1027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch do { 1028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block.Loop(stmt->getCond(), stmt->getBody()); 1029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } while (block.changed()); 1030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return block.out(); 1031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_STMT(DoStmt) { 1034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Block block (env, this); 1035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch do { 1036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block.Loop(stmt->getBody(), stmt->getCond()); 1037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } while (block.changed()); 1038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return block.out(); 1039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_STMT(ForStmt) { 1042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Block block (VisitStmt(stmt->getInit(), env), this); 1043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch do { 1044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block.Loop(stmt->getCond(), 1045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch stmt->getBody(), 1046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch stmt->getInc()); 1047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } while (block.changed()); 1048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return block.out(); 1049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_STMT(IfStmt) { 1052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment cond_out = VisitStmt(stmt->getCond(), env); 1053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment then_out = VisitStmt(stmt->getThen(), cond_out); 1054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment else_out = VisitStmt(stmt->getElse(), cond_out); 1055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Environment::Merge(then_out, else_out); 1056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_STMT(SwitchStmt) { 1059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Block block (env, this); 1060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block.Seq(stmt->getCond(), stmt->getBody()); 1061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return block.out(); 1062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_STMT(CaseStmt) { 1065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment in = Environment::Merge(env, block_->in()); 1066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment after_lhs = VisitStmt(stmt->getLHS(), in); 1067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitStmt(stmt->getSubStmt(), after_lhs); 1068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_STMT(DefaultStmt) { 1071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment in = Environment::Merge(env, block_->in()); 1072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return VisitStmt(stmt->getSubStmt(), in); 1073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_STMT(ReturnStmt) { 1076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitExpr(stmt->getRetValue(), env); 1077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Environment::Unreachable(); 10788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 10798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 10808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const clang::TagType* ToTagType(const clang::Type* t) { 10818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (t == NULL) { 10828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return NULL; 10838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else if (isa<clang::TagType>(t)) { 10848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return cast<clang::TagType>(t); 10858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else if (isa<clang::SubstTemplateTypeParmType>(t)) { 10868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return ToTagType(cast<clang::SubstTemplateTypeParmType>(t)-> 10878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch getReplacementType().getTypePtr()); 10888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 10898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return NULL; 10908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 10918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 10928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool IsDerivedFrom(clang::CXXRecordDecl* record, 1094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::CXXRecordDecl* base) { 1095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return (record == base) || record->isDerivedFrom(base); 1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 10978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool IsRawPointerType(clang::QualType qtype) { 10998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const clang::PointerType* type = 1100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dyn_cast_or_null<clang::PointerType>(qtype.getTypePtrOrNull()); 11018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (type == NULL) return false; 11028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 11038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const clang::TagType* pointee = 11048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ToTagType(type->getPointeeType().getTypePtr()); 11058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (pointee == NULL) return false; 11068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 11078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clang::CXXRecordDecl* record = 11088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch dyn_cast_or_null<clang::CXXRecordDecl>(pointee->getDecl()); 11098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (record == NULL) return false; 11108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!InV8Namespace(record)) return false; 11128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!record->hasDefinition()) return false; 11148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch record = record->getDefinition(); 11168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return IsDerivedFrom(record, object_decl_) && 1118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch !IsDerivedFrom(record, smi_decl_); 11198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 11208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment VisitDecl(clang::Decl* decl, const Environment& env) { 1122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (clang::VarDecl* var = dyn_cast<clang::VarDecl>(decl)) { 1123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment out = var->hasInit() ? VisitStmt(var->getInit(), env) : env; 1124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (IsRawPointerType(var->getType())) { 1126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out = out.Define(var->getNameAsString()); 1127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 11288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return out; 1130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // TODO: handle other declarations? 1132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return env; 11338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 11348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DECL_VISIT_STMT(DeclStmt) { 1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment out = env; 1137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::DeclStmt::decl_iterator end = stmt->decl_end(); 1138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (clang::DeclStmt::decl_iterator decl = stmt->decl_begin(); 1139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch decl != end; 1140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ++decl) { 1141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch out = VisitDecl(*decl, out); 1142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return out; 11448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 11458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 11468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void DefineParameters(const clang::FunctionDecl* f, 1148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment* env) { 1149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch env->MDefine(THIS); 1150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::FunctionDecl::param_const_iterator end = f->param_end(); 1151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (clang::FunctionDecl::param_const_iterator p = f->param_begin(); 1152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch p != end; 1153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ++p) { 1154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch env->MDefine((*p)->getNameAsString()); 1155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 11578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 11588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void AnalyzeFunction(const clang::FunctionDecl* f) { 1160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const clang::FunctionDecl* body = NULL; 1161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (f->hasBody(body)) { 1162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment env; 1163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DefineParameters(body, &env); 1164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitStmt(body->getBody(), env); 1165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Environment::ClearSymbolTable(); 1166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 11688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Block* EnterBlock(Block* block) { 1170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Block* parent = block_; 1171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block_ = block; 1172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return parent; 1173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 11748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void LeaveBlock(Block* block) { 1176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block_ = block; 1177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 11788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 1180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void ReportUnsafe(const clang::Expr* expr, const std::string& msg) { 1181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch d_.Report(clang::FullSourceLoc(expr->getExprLoc(), sm_), 1182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch d_.getCustomDiagID(clang::Diagnostic::Warning, msg)); 1183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 11848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 11858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::MangleContext* ctx_; 1187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::DeclarationName handle_decl_name_; 1188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::CXXRecordDecl* object_decl_; 1189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::CXXRecordDecl* smi_decl_; 11908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::Diagnostic& d_; 1192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::SourceManager& sm_; 11938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Block* block_; 1195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool dead_vars_analysis_; 1196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}; 11978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 11988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass ProblemsFinder : public clang::ASTConsumer, 1200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public clang::RecursiveASTVisitor<ProblemsFinder> { 1201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public: 1202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ProblemsFinder(clang::Diagnostic& d, 1203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::SourceManager& sm, 1204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const std::vector<std::string>& args) 1205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : d_(d), sm_(sm), dead_vars_analysis_(false) { 1206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (unsigned i = 0; i < args.size(); ++i) { 1207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (args[i] == "--dead-vars") { 1208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dead_vars_analysis_ = true; 1209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 12108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 12128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch virtual void HandleTranslationUnit(clang::ASTContext &ctx) { 12148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Resolver r(ctx); 12158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::CXXRecordDecl* object_decl = 12178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch r.ResolveNamespace("v8").ResolveNamespace("internal"). 12188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Resolve<clang::CXXRecordDecl>("Object"); 12198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch clang::CXXRecordDecl* smi_decl = 1221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch r.ResolveNamespace("v8").ResolveNamespace("internal"). 1222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Resolve<clang::CXXRecordDecl>("Smi"); 1223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (object_decl != NULL) object_decl = object_decl->getDefinition(); 1225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (smi_decl != NULL) smi_decl = smi_decl->getDefinition(); 1227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (object_decl != NULL && smi_decl != NULL) { 1229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch function_analyzer_ = 1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch new FunctionAnalyzer(clang::createItaniumMangleContext(ctx, d_), 1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch r.ResolveName("Handle"), 1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch object_decl, 1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch smi_decl, 1234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch d_, 1235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch sm_, 1236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dead_vars_analysis_); 12378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch TraverseDecl(ctx.getTranslationUnitDecl()); 12388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 1239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (object_decl == NULL) { 1240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch llvm::errs() << "Failed to resolve v8::internal::Object\n"; 1241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (smi_decl == NULL) { 1243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch llvm::errs() << "Failed to resolve v8::internal::Smi\n"; 1244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 12458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch virtual bool VisitFunctionDecl(clang::FunctionDecl* decl) { 1249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch function_analyzer_->AnalyzeFunction(decl); 12508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return true; 12518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private: 12548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clang::Diagnostic& d_; 12558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clang::SourceManager& sm_; 1256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool dead_vars_analysis_; 12578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FunctionAnalyzer* function_analyzer_; 12598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}; 12608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochtemplate<typename ConsumerType> 12638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass Action : public clang::PluginASTAction { 12648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch protected: 12658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &CI, 12668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch llvm::StringRef InFile) { 1267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return new ConsumerType(CI.getDiagnostics(), CI.getSourceManager(), args_); 12688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool ParseArgs(const clang::CompilerInstance &CI, 12718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const std::vector<std::string>& args) { 1272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch args_ = args; 12738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return true; 12748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void PrintHelp(llvm::raw_ostream& ros) { 1277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 1279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std::vector<std::string> args_; 12808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}; 12818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 12848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic clang::FrontendPluginRegistry::Add<Action<ProblemsFinder> > 1286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochFindProblems("find-problems", "Find GC-unsafe places."); 12878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic clang::FrontendPluginRegistry::Add< 1289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Action<FunctionDeclarationFinder> > 12908b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochDumpCallees("dump-callees", "Dump callees for each function."); 1291