diff options
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/ASTConsumers.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/AnalysisConsumer.cpp | 588 | ||||
-rw-r--r-- | lib/Frontend/BackendUtil.cpp | 325 | ||||
-rw-r--r-- | lib/Frontend/CMakeLists.txt | 10 | ||||
-rw-r--r-- | lib/Frontend/CodeGenAction.cpp | 349 | ||||
-rw-r--r-- | lib/Frontend/FixItRewriter.cpp | 167 | ||||
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 83 | ||||
-rw-r--r-- | lib/Frontend/HTMLDiagnostics.cpp | 577 | ||||
-rw-r--r-- | lib/Frontend/HTMLPrint.cpp | 94 | ||||
-rw-r--r-- | lib/Frontend/PlistDiagnostics.cpp | 471 | ||||
-rw-r--r-- | lib/Frontend/RewriteMacros.cpp | 217 | ||||
-rw-r--r-- | lib/Frontend/RewriteObjC.cpp | 5778 | ||||
-rw-r--r-- | lib/Frontend/RewriteTest.cpp | 39 |
13 files changed, 0 insertions, 8700 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index 7b8ebf9203..bf2b3f2319 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -13,7 +13,6 @@ #include "clang/Frontend/ASTConsumers.h" #include "clang/Frontend/DocumentXML.h" -#include "clang/Frontend/PathDiagnosticClients.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/FileManager.h" @@ -22,7 +21,6 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/PrettyPrinter.h" -#include "clang/CodeGen/ModuleBuilder.h" #include "llvm/Module.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp deleted file mode 100644 index 0589008033..0000000000 --- a/lib/Frontend/AnalysisConsumer.cpp +++ /dev/null @@ -1,588 +0,0 @@ -//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// "Meta" ASTConsumer for running different source analyses. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/AnalysisConsumer.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/ParentMap.h" -#include "clang/Analysis/Analyses/LiveVariables.h" -#include "clang/Analysis/Analyses/UninitializedValues.h" -#include "clang/Analysis/CFG.h" -#include "clang/Checker/Checkers/LocalCheckers.h" -#include "clang/Checker/ManagerRegistry.h" -#include "clang/Checker/BugReporter/PathDiagnostic.h" -#include "clang/Checker/PathSensitive/AnalysisManager.h" -#include "clang/Checker/BugReporter/BugReporter.h" -#include "clang/Checker/PathSensitive/GRExprEngine.h" -#include "clang/Checker/PathSensitive/GRTransferFuncs.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Frontend/PathDiagnosticClients.h" -#include "clang/Lex/Preprocessor.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Path.h" -#include "llvm/System/Program.h" -#include "llvm/ADT/OwningPtr.h" - -using namespace clang; - -static ExplodedNode::Auditor* CreateUbiViz(); - -//===----------------------------------------------------------------------===// -// Special PathDiagnosticClients. -//===----------------------------------------------------------------------===// - -static PathDiagnosticClient* -CreatePlistHTMLDiagnosticClient(const std::string& prefix, - const Preprocessor &PP) { - llvm::sys::Path F(prefix); - PathDiagnosticClient *PD = CreateHTMLDiagnosticClient(F.getDirname(), PP); - return CreatePlistDiagnosticClient(prefix, PP, PD); -} - -//===----------------------------------------------------------------------===// -// AnalysisConsumer declaration. -//===----------------------------------------------------------------------===// - -namespace { - -class AnalysisConsumer : public ASTConsumer { -public: - typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D); - typedef void (*TUAction)(AnalysisConsumer &C, AnalysisManager &M, - TranslationUnitDecl &TU); - -private: - typedef std::vector<CodeAction> Actions; - typedef std::vector<TUAction> TUActions; - - Actions FunctionActions; - Actions ObjCMethodActions; - Actions ObjCImplementationActions; - Actions CXXMethodActions; - TUActions TranslationUnitActions; // Remove this. - -public: - ASTContext* Ctx; - const Preprocessor &PP; - const std::string OutDir; - AnalyzerOptions Opts; - bool declDisplayed; - - - // PD is owned by AnalysisManager. - PathDiagnosticClient *PD; - - StoreManagerCreator CreateStoreMgr; - ConstraintManagerCreator CreateConstraintMgr; - - llvm::OwningPtr<AnalysisManager> Mgr; - - AnalysisConsumer(const Preprocessor& pp, - const std::string& outdir, - const AnalyzerOptions& opts) - : Ctx(0), PP(pp), OutDir(outdir), - Opts(opts), declDisplayed(false), PD(0) { - DigestAnalyzerOptions(); - } - - void DigestAnalyzerOptions() { - // Create the PathDiagnosticClient. - if (!OutDir.empty()) { - switch (Opts.AnalysisDiagOpt) { - default: -#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \ - case PD_##NAME: PD = CREATEFN(OutDir, PP); break; -#include "clang/Frontend/Analyses.def" - } - } - - // Create the analyzer component creators. - if (ManagerRegistry::StoreMgrCreator != 0) { - CreateStoreMgr = ManagerRegistry::StoreMgrCreator; - } - else { - switch (Opts.AnalysisStoreOpt) { - default: - assert(0 && "Unknown store manager."); -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \ - case NAME##Model: CreateStoreMgr = CREATEFN; break; -#include "clang/Frontend/Analyses.def" - } - } - - if (ManagerRegistry::ConstraintMgrCreator != 0) - CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator; - else { - switch (Opts.AnalysisConstraintsOpt) { - default: - assert(0 && "Unknown store manager."); -#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \ - case NAME##Model: CreateConstraintMgr = CREATEFN; break; -#include "clang/Frontend/Analyses.def" - } - } - } - - void DisplayFunction(const Decl *D) { - if (!Opts.AnalyzerDisplayProgress || declDisplayed) - return; - - declDisplayed = true; - SourceManager &SM = Mgr->getASTContext().getSourceManager(); - PresumedLoc Loc = SM.getPresumedLoc(D->getLocation()); - llvm::errs() << "ANALYZE: " << Loc.getFilename(); - - if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { - const NamedDecl *ND = cast<NamedDecl>(D); - llvm::errs() << ' ' << ND << '\n'; - } - else if (isa<BlockDecl>(D)) { - llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:" - << Loc.getColumn() << '\n'; - } - } - - void addCodeAction(CodeAction action) { - FunctionActions.push_back(action); - ObjCMethodActions.push_back(action); - CXXMethodActions.push_back(action); - } - - void addTranslationUnitAction(TUAction action) { - TranslationUnitActions.push_back(action); - } - - void addObjCImplementationAction(CodeAction action) { - ObjCImplementationActions.push_back(action); - } - - virtual void Initialize(ASTContext &Context) { - Ctx = &Context; - Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(), - PP.getLangOptions(), PD, - CreateStoreMgr, CreateConstraintMgr, - Opts.MaxNodes, Opts.MaxLoop, - Opts.VisualizeEGDot, Opts.VisualizeEGUbi, - Opts.PurgeDead, Opts.EagerlyAssume, - Opts.TrimGraph, Opts.InlineCall)); - } - - virtual void HandleTranslationUnit(ASTContext &C); - void HandleCode(Decl *D, Stmt* Body, Actions& actions); -}; -} // end anonymous namespace - -//===----------------------------------------------------------------------===// -// AnalysisConsumer implementation. -//===----------------------------------------------------------------------===// - -void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { - - TranslationUnitDecl *TU = C.getTranslationUnitDecl(); - - for (DeclContext::decl_iterator I = TU->decls_begin(), E = TU->decls_end(); - I != E; ++I) { - Decl *D = *I; - - switch (D->getKind()) { - case Decl::CXXConstructor: - case Decl::CXXDestructor: - case Decl::CXXConversion: - case Decl::CXXMethod: - case Decl::Function: { - FunctionDecl* FD = cast<FunctionDecl>(D); - - if (FD->isThisDeclarationADefinition()) { - if (!Opts.AnalyzeSpecificFunction.empty() && - FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction) - break; - HandleCode(FD, FD->getBody(), FunctionActions); - } - break; - } - - case Decl::ObjCMethod: { - ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D); - - if (MD->isThisDeclarationADefinition()) { - if (!Opts.AnalyzeSpecificFunction.empty() && - Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString()) - break; - HandleCode(MD, MD->getBody(), ObjCMethodActions); - } - break; - } - - case Decl::ObjCImplementation: { - ObjCImplementationDecl* ID = cast<ObjCImplementationDecl>(*I); - HandleCode(ID, 0, ObjCImplementationActions); - - for (ObjCImplementationDecl::method_iterator MI = ID->meth_begin(), - ME = ID->meth_end(); MI != ME; ++MI) { - if ((*MI)->isThisDeclarationADefinition()) { - if (!Opts.AnalyzeSpecificFunction.empty() && - Opts.AnalyzeSpecificFunction != (*MI)->getSelector().getAsString()) - break; - HandleCode(*MI, (*MI)->getBody(), ObjCMethodActions); - } - } - break; - } - - default: - break; - } - } - - for (TUActions::iterator I = TranslationUnitActions.begin(), - E = TranslationUnitActions.end(); I != E; ++I) { - (*I)(*this, *Mgr, *TU); - } - - // Explicitly destroy the PathDiagnosticClient. This will flush its output. - // FIXME: This should be replaced with something that doesn't rely on - // side-effects in PathDiagnosticClient's destructor. This is required when - // used with option -disable-free. - Mgr.reset(NULL); -} - -static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl<Decl*> &WL) { - if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) - WL.push_back(BD); - - for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end(); - I!=E; ++I) - if (DeclContext *DC = dyn_cast<DeclContext>(*I)) - FindBlocks(DC, WL); -} - -void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) { - - // Don't run the actions if an error has occured with parsing the file. - Diagnostic &Diags = PP.getDiagnostics(); - if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) - return; - - // Don't run the actions on declarations in header files unless - // otherwise specified. - SourceManager &SM = Ctx->getSourceManager(); - SourceLocation SL = SM.getInstantiationLoc(D->getLocation()); - if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL)) - return; - - // Clear the AnalysisManager of old AnalysisContexts. - Mgr->ClearContexts(); - - // Dispatch on the actions. - llvm::SmallVector<Decl*, 10> WL; - WL.push_back(D); - - if (Body && Opts.AnalyzeNestedBlocks) - FindBlocks(cast<DeclContext>(D), WL); - - for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I) - for (llvm::SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end(); - WI != WE; ++WI) - (*I)(*this, *Mgr, *WI); -} - -//===----------------------------------------------------------------------===// -// Analyses -//===----------------------------------------------------------------------===// - -static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D) { - if (LiveVariables *L = mgr.getLiveVariables(D)) { - BugReporter BR(mgr); - CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR); - } -} - -static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D) { - if (CFG* c = mgr.getCFG(D)) { - CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic()); - } -} - - -static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D, - GRTransferFuncs* tf) { - - llvm::OwningPtr<GRTransferFuncs> TF(tf); - - // Construct the analysis engine. We first query for the LiveVariables - // information to see if the CFG is valid. - // FIXME: Inter-procedural analysis will need to handle invalid CFGs. - if (!mgr.getLiveVariables(D)) - return; - GRExprEngine Eng(mgr, TF.take()); - - if (C.Opts.EnableExperimentalInternalChecks) - RegisterExperimentalInternalChecks(Eng); - - RegisterAppleChecks(Eng, *D); - - if (C.Opts.EnableExperimentalChecks) - RegisterExperimentalChecks(Eng); - - // Set the graph auditor. - llvm::OwningPtr<ExplodedNode::Auditor> Auditor; - if (mgr.shouldVisualizeUbigraph()) { - Auditor.reset(CreateUbiViz()); - ExplodedNode::SetAuditor(Auditor.get()); - } - - // Execute the worklist algorithm. - Eng.ExecuteWorkList(mgr.getStackFrame(D), mgr.getMaxNodes()); - - // Release the auditor (if any) so that it doesn't monitor the graph - // created BugReporter. - ExplodedNode::SetAuditor(0); - - // Visualize the exploded graph. - if (mgr.shouldVisualizeGraphviz()) - Eng.ViewGraph(mgr.shouldTrimGraph()); - - // Display warnings. - Eng.getBugReporter().FlushReports(); -} - -static void ActionObjCMemCheckerAux(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D, bool GCEnabled) { - - GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(), - GCEnabled, - mgr.getLangOptions()); - - ActionGRExprEngine(C, mgr, D, TF); -} - -static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D) { - - switch (mgr.getLangOptions().getGCMode()) { - default: - assert (false && "Invalid GC mode."); - case LangOptions::NonGC: - ActionObjCMemCheckerAux(C, mgr, D, false); - break; - - case LangOptions::GCOnly: - ActionObjCMemCheckerAux(C, mgr, D, true); - break; - - case LangOptions::HybridGC: - ActionObjCMemCheckerAux(C, mgr, D, false); - ActionObjCMemCheckerAux(C, mgr, D, true); - break; - } -} - -static void ActionDisplayLiveVariables(AnalysisConsumer &C, - AnalysisManager& mgr, Decl *D) { - if (LiveVariables* L = mgr.getLiveVariables(D)) { - L->dumpBlockLiveness(mgr.getSourceManager()); - } -} - -static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { - if (CFG *cfg = mgr.getCFG(D)) { - cfg->dump(mgr.getLangOptions()); - } -} - -static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { - if (CFG *cfg = mgr.getCFG(D)) { - cfg->viewCFG(mgr.getLangOptions()); - } -} - -static void ActionSecuritySyntacticChecks(AnalysisConsumer &C, - AnalysisManager &mgr, Decl *D) { - BugReporter BR(mgr); - CheckSecuritySyntaxOnly(D, BR); -} - -static void ActionLLVMConventionChecker(AnalysisConsumer &C, - AnalysisManager &mgr, - TranslationUnitDecl &TU) { - BugReporter BR(mgr); - CheckLLVMConventions(TU, BR); -} - -static void ActionWarnObjCDealloc(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D) { - if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly) - return; - BugReporter BR(mgr); - CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR); -} - -static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D) { - BugReporter BR(mgr); - CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR); -} - -static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D) { - BugReporter BR(mgr); - CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR); -} - -static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr, - Decl *D) { - BugReporter BR(mgr); - CheckSizeofPointer(D, BR); -} - -//===----------------------------------------------------------------------===// -// AnalysisConsumer creation. -//===----------------------------------------------------------------------===// - -ASTConsumer* clang::CreateAnalysisConsumer(const Preprocessor& pp, - const std::string& OutDir, - const AnalyzerOptions& Opts) { - llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(pp, OutDir, Opts)); - - for (unsigned i = 0; i < Opts.AnalysisList.size(); ++i) - switch (Opts.AnalysisList[i]) { -#define ANALYSIS(NAME, CMD, DESC, SCOPE)\ - case NAME:\ - C->add ## SCOPE ## Action(&Action ## NAME);\ - break; -#include "clang/Frontend/Analyses.def" - default: break; - } - - // Last, disable the effects of '-Werror' when using the AnalysisConsumer. - pp.getDiagnostics().setWarningsAsErrors(false); - - return C.take(); -} - -//===----------------------------------------------------------------------===// -// Ubigraph Visualization. FIXME: Move to separate file. -//===----------------------------------------------------------------------===// - -namespace { - -class UbigraphViz : public ExplodedNode::Auditor { - llvm::OwningPtr<llvm::raw_ostream> Out; - llvm::sys::Path Dir, Filename; - unsigned Cntr; - - typedef llvm::DenseMap<void*,unsigned> VMap; - VMap M; - -public: - UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir, - llvm::sys::Path& filename); - - ~UbigraphViz(); - - virtual void AddEdge(ExplodedNode* Src, ExplodedNode* Dst); -}; - -} // end anonymous namespace - -static ExplodedNode::Auditor* CreateUbiViz() { - std::string ErrMsg; - - llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg); - if (!ErrMsg.empty()) - return 0; - - llvm::sys::Path Filename = Dir; - Filename.appendComponent("llvm_ubi"); - Filename.makeUnique(true,&ErrMsg); - - if (!ErrMsg.empty()) - return 0; - - llvm::errs() << "Writing '" << Filename.str() << "'.\n"; - - llvm::OwningPtr<llvm::raw_fd_ostream> Stream; - Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg)); - - if (!ErrMsg.empty()) - return 0; - - return new UbigraphViz(Stream.take(), Dir, Filename); -} - -void UbigraphViz::AddEdge(ExplodedNode* Src, ExplodedNode* Dst) { - - assert (Src != Dst && "Self-edges are not allowed."); - - // Lookup the Src. If it is a new node, it's a root. - VMap::iterator SrcI= M.find(Src); - unsigned SrcID; - - if (SrcI == M.end()) { - M[Src] = SrcID = Cntr++; - *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n"; - } - else - SrcID = SrcI->second; - - // Lookup the Dst. - VMap::iterator DstI= M.find(Dst); - unsigned DstID; - - if (DstI == M.end()) { - M[Dst] = DstID = Cntr++; - *Out << "('vertex', " << DstID << ")\n"; - } - else { - // We have hit DstID before. Change its style to reflect a cache hit. - DstID = DstI->second; - *Out << "('change_vertex_style', " << DstID << ", 1)\n"; - } - - // Add the edge. - *Out << "('edge', " << SrcID << ", " << DstID - << ", ('arrow','true'), ('oriented', 'true'))\n"; -} - -UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir, - llvm::sys::Path& filename) - : Out(out), Dir(dir), Filename(filename), Cntr(0) { - - *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n"; - *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66')," - " ('size', '1.5'))\n"; -} - -UbigraphViz::~UbigraphViz() { - Out.reset(0); - llvm::errs() << "Running 'ubiviz' program... "; - std::string ErrMsg; - llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz"); - std::vector<const char*> args; - args.push_back(Ubiviz.c_str()); - args.push_back(Filename.c_str()); - args.push_back(0); - - if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) { - llvm::errs() << "Error viewing graph: " << ErrMsg << "\n"; - } - - // Delete the directory. - Dir.eraseFromDisk(true); -} diff --git a/lib/Frontend/BackendUtil.cpp b/lib/Frontend/BackendUtil.cpp deleted file mode 100644 index 2ceb831a5e..0000000000 --- a/lib/Frontend/BackendUtil.cpp +++ /dev/null @@ -1,325 +0,0 @@ -//===--- BackendUtil.cpp - LLVM Backend Utilities -------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/BackendUtil.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/TargetOptions.h" -#include "clang/CodeGen/CodeGenOptions.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/Assembly/PrintModulePass.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/CodeGen/RegAllocRegistry.h" -#include "llvm/CodeGen/SchedulerRegistry.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/StandardPasses.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/SubtargetFeature.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetRegistry.h" -using namespace clang; -using namespace llvm; - -namespace { - -class EmitAssemblyHelper { - Diagnostic &Diags; - const CodeGenOptions &CodeGenOpts; - const TargetOptions &TargetOpts; - Module *TheModule; - - Timer CodeGenerationTime; - - mutable FunctionPassManager *CodeGenPasses; - mutable PassManager *PerModulePasses; - mutable FunctionPassManager *PerFunctionPasses; - -private: - FunctionPassManager *getCodeGenPasses() const { - if (!CodeGenPasses) { - CodeGenPasses = new FunctionPassManager(TheModule); - CodeGenPasses->add(new TargetData(TheModule)); - } - return CodeGenPasses; - } - - PassManager *getPerModulePasses() const { - if (!PerModulePasses) { - PerModulePasses = new PassManager(); - PerModulePasses->add(new TargetData(TheModule)); - } - return PerModulePasses; - } - - FunctionPassManager *getPerFunctionPasses() const { - if (!PerFunctionPasses) { - PerFunctionPasses = new FunctionPassManager(TheModule); - PerFunctionPasses->add(new TargetData(TheModule)); - } - return PerFunctionPasses; - } - - void CreatePasses(); - - /// AddEmitPasses - Add passes necessary to emit assembly or LLVM IR. - /// - /// \return True on success. - bool AddEmitPasses(BackendAction Action, formatted_raw_ostream &OS); - -public: - EmitAssemblyHelper(Diagnostic &_Diags, - const CodeGenOptions &CGOpts, const TargetOptions &TOpts, - Module *M) - : Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), - TheModule(M), CodeGenerationTime("Code Generation Time"), - CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {} - - ~EmitAssemblyHelper() { - delete CodeGenPasses; - delete PerModulePasses; - delete PerFunctionPasses; - } - - void EmitAssembly(BackendAction Action, raw_ostream *OS); -}; - -} - -void EmitAssemblyHelper::CreatePasses() { - unsigned OptLevel = CodeGenOpts.OptimizationLevel; - CodeGenOptions::InliningMethod Inlining = CodeGenOpts.Inlining; - - // Handle disabling of LLVM optimization, where we want to preserve the - // internal module before any optimization. - if (CodeGenOpts.DisableLLVMOpts) { - OptLevel = 0; - Inlining = CodeGenOpts.NoInlining; - } - - // In -O0 if checking is disabled, we don't even have per-function passes. - if (CodeGenOpts.VerifyModule) - getPerFunctionPasses()->add(createVerifierPass()); - - // Assume that standard function passes aren't run for -O0. - if (OptLevel > 0) - llvm::createStandardFunctionPasses(getPerFunctionPasses(), OptLevel); - - llvm::Pass *InliningPass = 0; - switch (Inlining) { - case CodeGenOptions::NoInlining: break; - case CodeGenOptions::NormalInlining: { - // Set the inline threshold following llvm-gcc. - // - // FIXME: Derive these constants in a principled fashion. - unsigned Threshold = 225; - if (CodeGenOpts.OptimizeSize) - Threshold = 75; - else if (OptLevel > 2) - Threshold = 275; - InliningPass = createFunctionInliningPass(Threshold); - break; - } - case CodeGenOptions::OnlyAlwaysInlining: - InliningPass = createAlwaysInlinerPass(); // Respect always_inline - break; - } - - // For now we always create per module passes. - llvm::createStandardModulePasses(getPerModulePasses(), OptLevel, - CodeGenOpts.OptimizeSize, - CodeGenOpts.UnitAtATime, - CodeGenOpts.UnrollLoops, - CodeGenOpts.SimplifyLibCalls, - /*HaveExceptions=*/true, - InliningPass); -} - -bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action, - formatted_raw_ostream &OS) { - // Create the TargetMachine for generating code. - std::string Error; - std::string Triple = TheModule->getTargetTriple(); - const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); - if (!TheTarget) { - Diags.Report(diag::err_fe_unable_to_create_target) << Error; - return false; - } - - // FIXME: Expose these capabilities via actual APIs!!!! Aside from just - // being gross, this is also totally broken if we ever care about - // concurrency. - llvm::NoFramePointerElim = CodeGenOpts.DisableFPElim; - if (CodeGenOpts.FloatABI == "soft") - llvm::FloatABIType = llvm::FloatABI::Soft; - else if (CodeGenOpts.FloatABI == "hard") - llvm::FloatABIType = llvm::FloatABI::Hard; - else { - assert(CodeGenOpts.FloatABI.empty() && "Invalid float abi!"); - llvm::FloatABIType = llvm::FloatABI::Default; - } - NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; - llvm::UseSoftFloat = CodeGenOpts.SoftFloat; - UnwindTablesMandatory = CodeGenOpts.UnwindTables; - - TargetMachine::setAsmVerbosityDefault(CodeGenOpts.AsmVerbose); - - TargetMachine::setFunctionSections(CodeGenOpts.FunctionSections); - TargetMachine::setDataSections (CodeGenOpts.DataSections); - - // FIXME: Parse this earlier. - if (CodeGenOpts.RelocationModel == "static") { - TargetMachine::setRelocationModel(llvm::Reloc::Static); - } else if (CodeGenOpts.RelocationModel == "pic") { - TargetMachine::setRelocationModel(llvm::Reloc::PIC_); - } else { - assert(CodeGenOpts.RelocationModel == "dynamic-no-pic" && - "Invalid PIC model!"); - TargetMachine::setRelocationModel(llvm::Reloc::DynamicNoPIC); - } - // FIXME: Parse this earlier. - if (CodeGenOpts.CodeModel == "small") { - TargetMachine::setCodeModel(llvm::CodeModel::Small); - } else if (CodeGenOpts.CodeModel == "kernel") { - TargetMachine::setCodeModel(llvm::CodeModel::Kernel); - } else if (CodeGenOpts.CodeModel == "medium") { - TargetMachine::setCodeModel(llvm::CodeModel::Medium); - } else if (CodeGenOpts.CodeModel == "large") { - TargetMachine::setCodeModel(llvm::CodeModel::Large); - } else { - assert(CodeGenOpts.CodeModel.empty() && "Invalid code model!"); - TargetMachine::setCodeModel(llvm::CodeModel::Default); - } - - std::vector<const char *> BackendArgs; - BackendArgs.push_back("clang"); // Fake program name. - if (!CodeGenOpts.DebugPass.empty()) { - BackendArgs.push_back("-debug-pass"); - BackendArgs.push_back(CodeGenOpts.DebugPass.c_str()); - } - if (!CodeGenOpts.LimitFloatPrecision.empty()) { - BackendArgs.push_back("-limit-float-precision"); - BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str()); - } - if (llvm::TimePassesIsEnabled) - BackendArgs.push_back("-time-passes"); - BackendArgs.push_back(0); - llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, - const_cast<char **>(&BackendArgs[0])); - - std::string FeaturesStr; - if (TargetOpts.CPU.size() || TargetOpts.Features.size()) { - SubtargetFeatures Features; - Features.setCPU(TargetOpts.CPU); - for (std::vector<std::string>::const_iterator - it = TargetOpts.Features.begin(), - ie = TargetOpts.Features.end(); it != ie; ++it) - Features.AddFeature(*it); - FeaturesStr = Features.getString(); - } - TargetMachine *TM = TheTarget->createTargetMachine(Triple, FeaturesStr); - - if (CodeGenOpts.RelaxAll) - TM->setMCRelaxAll(true); - - // Create the code generator passes. - FunctionPassManager *PM = getCodeGenPasses(); - CodeGenOpt::Level OptLevel = CodeGenOpt::Default; - - switch (CodeGenOpts.OptimizationLevel) { - default: break; - case 0: OptLevel = CodeGenOpt::None; break; - case 3: OptLevel = CodeGenOpt::Aggressive; break; - } - - // Normal mode, emit a .s or .o file by running the code generator. Note, - // this also adds codegenerator level optimization passes. - TargetMachine::CodeGenFileType CGFT = TargetMachine::CGFT_AssemblyFile; - if (Action == Backend_EmitObj) - CGFT = TargetMachine::CGFT_ObjectFile; - else if (Action == Backend_EmitMCNull) - CGFT = TargetMachine::CGFT_Null; - else - assert(Action == Backend_EmitAssembly && "Invalid action!"); - if (TM->addPassesToEmitFile(*PM, OS, CGFT, OptLevel, - /*DisableVerify=*/!CodeGenOpts.VerifyModule)) { - Diags.Report(diag::err_fe_unable_to_interface_with_target); - return false; - } - - return true; -} - -void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) { - TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : 0); - llvm::formatted_raw_ostream FormattedOS; - - CreatePasses(); - switch (Action) { - case Backend_EmitNothing: - break; - - case Backend_EmitBC: - getPerModulePasses()->add(createBitcodeWriterPass(*OS)); - break; - - case Backend_EmitLL: - FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM); - getPerModulePasses()->add(createPrintModulePass(&FormattedOS)); - break; - - default: - FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM); - if (!AddEmitPasses(Action, FormattedOS)) - return; - } - - // Run passes. For now we do all passes at once, but eventually we - // would like to have the option of streaming code generation. - - if (PerFunctionPasses) { - PrettyStackTraceString CrashInfo("Per-function optimization"); - - PerFunctionPasses->doInitialization(); - for (Module::iterator I = TheModule->begin(), - E = TheModule->end(); I != E; ++I) - if (!I->isDeclaration()) - PerFunctionPasses->run(*I); - PerFunctionPasses->doFinalization(); - } - - if (PerModulePasses) { - PrettyStackTraceString CrashInfo("Per-module optimization passes"); - PerModulePasses->run(*TheModule); - } - - if (CodeGenPasses) { - PrettyStackTraceString CrashInfo("Code generation"); - - CodeGenPasses->doInitialization(); - for (Module::iterator I = TheModule->begin(), - E = TheModule->end(); I != E; ++I) - if (!I->isDeclaration()) - CodeGenPasses->run(*I); - CodeGenPasses->doFinalization(); - } -} - -void clang::EmitBackendOutput(Diagnostic &Diags, const CodeGenOptions &CGOpts, - |