diff options
author | Stephen Hines <srhines@google.com> | 2012-09-10 17:01:41 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2012-09-10 17:01:41 -0700 |
commit | 9f0b1324a5352713337c75ef4a5acffd96609c6c (patch) | |
tree | b2a3d75de08ebfc054b31a420400bca7d6aaec46 /utils | |
parent | 8eba6f194484c38ed724375aeab27de556113a84 (diff) | |
parent | 654f1d508cbc9553f4931b340dfa19b453f72ebd (diff) | |
download | clang-9f0b1324a5352713337c75ef4a5acffd96609c6c.tar.gz |
Merge branch 'upstream' into merge-2012_09_10
Diffstat (limited to 'utils')
-rw-r--r-- | utils/TableGen/CMakeLists.txt | 2 | ||||
-rw-r--r-- | utils/TableGen/ClangCommentCommandInfoEmitter.cpp | 70 | ||||
-rw-r--r-- | utils/TableGen/ClangCommentHTMLTagsEmitter.cpp | 69 | ||||
-rw-r--r-- | utils/TableGen/OptParserEmitter.cpp | 4 | ||||
-rw-r--r-- | utils/TableGen/TableGen.cpp | 24 | ||||
-rw-r--r-- | utils/TableGen/TableGenBackends.h | 5 | ||||
-rwxr-xr-x | utils/analyzer/CmpRuns.py | 4 | ||||
-rwxr-xr-x | utils/analyzer/SATestAdd.py | 18 | ||||
-rwxr-xr-x | utils/analyzer/SATestBuild.py | 163 | ||||
-rw-r--r-- | utils/analyzer/SumTimerInfo.py | 17 | ||||
-rwxr-xr-x | utils/analyzer/update_plist_test.pl | 51 |
11 files changed, 370 insertions, 57 deletions
diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt index 0d879214d4..d5748bc2ce 100644 --- a/utils/TableGen/CMakeLists.txt +++ b/utils/TableGen/CMakeLists.txt @@ -5,6 +5,8 @@ set(LLVM_LINK_COMPONENTS Support) add_tablegen(clang-tblgen CLANG ClangASTNodesEmitter.cpp ClangAttrEmitter.cpp + ClangCommentCommandInfoEmitter.cpp + ClangCommentHTMLTagsEmitter.cpp ClangDiagnosticsEmitter.cpp ClangSACheckersEmitter.cpp NeonEmitter.cpp diff --git a/utils/TableGen/ClangCommentCommandInfoEmitter.cpp b/utils/TableGen/ClangCommentCommandInfoEmitter.cpp new file mode 100644 index 0000000000..11b2f51f71 --- /dev/null +++ b/utils/TableGen/ClangCommentCommandInfoEmitter.cpp @@ -0,0 +1,70 @@ +//===--- ClangCommentCommandInfoEmitter.cpp - Generate command lists -----====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits command lists and efficient matchers command +// names that are used in documentation comments. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/StringMatcher.h" +#include <vector> + +using namespace llvm; + +namespace clang { +void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) { + OS << "// This file is generated by TableGen. Do not edit.\n\n"; + + OS << "namespace {\n" + "const CommandInfo Commands[] = {\n"; + std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command"); + for (size_t i = 0, e = Tags.size(); i != e; ++i) { + Record &Tag = *Tags[i]; + OS << " { " + << "\"" << Tag.getValueAsString("Name") << "\", " + << "\"" << Tag.getValueAsString("EndCommandName") << "\", " + << i << ", " + << Tag.getValueAsInt("NumArgs") << ", " + << Tag.getValueAsBit("IsInlineCommand") << ", " + << Tag.getValueAsBit("IsBlockCommand") << ", " + << Tag.getValueAsBit("IsBriefCommand") << ", " + << Tag.getValueAsBit("IsReturnsCommand") << ", " + << Tag.getValueAsBit("IsParamCommand") << ", " + << Tag.getValueAsBit("IsTParamCommand") << ", " + << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", " + << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", " + << Tag.getValueAsBit("IsVerbatimLineCommand") << ", " + << Tag.getValueAsBit("IsDeclarationCommand") << ", " + << /* IsUnknownCommand = */ "0" + << " }"; + if (i + 1 != e) + OS << ","; + OS << "\n"; + } + OS << "};\n" + "} // unnamed namespace\n\n"; + + std::vector<StringMatcher::StringPair> Matches; + for (size_t i = 0, e = Tags.size(); i != e; ++i) { + Record &Tag = *Tags[i]; + std::string Name = Tag.getValueAsString("Name"); + std::string Return; + raw_string_ostream(Return) << "return &Commands[" << i << "];"; + Matches.push_back(StringMatcher::StringPair(Name, Return)); + } + + OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n" + << " StringRef Name) {\n"; + StringMatcher("Name", Matches, OS).Emit(); + OS << " return NULL;\n" + << "}\n\n"; +} +} // end namespace clang + diff --git a/utils/TableGen/ClangCommentHTMLTagsEmitter.cpp b/utils/TableGen/ClangCommentHTMLTagsEmitter.cpp new file mode 100644 index 0000000000..0ae23b293e --- /dev/null +++ b/utils/TableGen/ClangCommentHTMLTagsEmitter.cpp @@ -0,0 +1,69 @@ +//===--- ClangCommentHTMLTagsEmitter.cpp - Generate HTML tag list for Clang -=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits efficient matchers for HTML tags that are used +// in documentation comments. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/StringMatcher.h" +#include <vector> + +using namespace llvm; + +namespace clang { +void EmitClangCommentHTMLTags(RecordKeeper &Records, raw_ostream &OS) { + std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Tag"); + std::vector<StringMatcher::StringPair> Matches; + for (std::vector<Record *>::iterator I = Tags.begin(), E = Tags.end(); + I != E; ++I) { + Record &Tag = **I; + std::string Spelling = Tag.getValueAsString("Spelling"); + Matches.push_back(StringMatcher::StringPair(Spelling, "return true;")); + } + + OS << "// This file is generated by TableGen. Do not edit.\n\n"; + + OS << "bool isHTMLTagName(StringRef Name) {\n"; + StringMatcher("Name", Matches, OS).Emit(); + OS << " return false;\n" + << "}\n\n"; +} + +void EmitClangCommentHTMLTagsProperties(RecordKeeper &Records, + raw_ostream &OS) { + std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Tag"); + std::vector<StringMatcher::StringPair> MatchesEndTagOptional; + std::vector<StringMatcher::StringPair> MatchesEndTagForbidden; + for (std::vector<Record *>::iterator I = Tags.begin(), E = Tags.end(); + I != E; ++I) { + Record &Tag = **I; + std::string Spelling = Tag.getValueAsString("Spelling"); + StringMatcher::StringPair Match(Spelling, "return true;"); + if (Tag.getValueAsBit("EndTagOptional")) + MatchesEndTagOptional.push_back(Match); + if (Tag.getValueAsBit("EndTagForbidden")) + MatchesEndTagForbidden.push_back(Match); + } + + OS << "// This file is generated by TableGen. Do not edit.\n\n"; + + OS << "bool isHTMLEndTagOptional(StringRef Name) {\n"; + StringMatcher("Name", MatchesEndTagOptional, OS).Emit(); + OS << " return false;\n" + << "}\n\n"; + + OS << "bool isHTMLEndTagForbidden(StringRef Name) {\n"; + StringMatcher("Name", MatchesEndTagForbidden, OS).Emit(); + OS << " return false;\n" + << "}\n\n"; +} +} // end namespace clang + diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index b0431a9be1..c9492ad719 100644 --- a/utils/TableGen/OptParserEmitter.cpp +++ b/utils/TableGen/OptParserEmitter.cpp @@ -32,8 +32,8 @@ static int StrCmpOptionName(const char *A, const char *B) { } static int CompareOptionRecords(const void *Av, const void *Bv) { - const Record *A = *(Record**) Av; - const Record *B = *(Record**) Bv; + const Record *A = *(const Record*const*) Av; + const Record *B = *(const Record*const*) Bv; // Sentinel options precede all others and are only ordered by precedence. bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel"); diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index d3408ed20f..4f7789dbef 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -42,6 +42,9 @@ enum ActionType { GenClangDeclNodes, GenClangStmtNodes, GenClangSACheckers, + GenClangCommentHTMLTags, + GenClangCommentHTMLTagsProperties, + GenClangCommentCommandInfo, GenOptParserDefs, GenOptParserImpl, GenArmNeon, GenArmNeonSema, @@ -95,6 +98,18 @@ namespace { "Generate Clang AST statement nodes"), clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers", "Generate Clang Static Analyzer checkers"), + clEnumValN(GenClangCommentHTMLTags, + "gen-clang-comment-html-tags", + "Generate efficient matchers for HTML tag " + "names that are used in documentation comments"), + clEnumValN(GenClangCommentHTMLTagsProperties, + "gen-clang-comment-html-tags-properties", + "Generate efficient matchers for HTML tag " + "properties"), + clEnumValN(GenClangCommentCommandInfo, + "gen-clang-comment-command-info", + "Generate list of commands that are used in " + "documentation comments"), clEnumValN(GenArmNeon, "gen-arm-neon", "Generate arm_neon.h for clang"), clEnumValN(GenArmNeonSema, "gen-arm-neon-sema", @@ -164,6 +179,15 @@ public: case GenClangSACheckers: EmitClangSACheckers(Records, OS); break; + case GenClangCommentHTMLTags: + EmitClangCommentHTMLTags(Records, OS); + break; + case GenClangCommentHTMLTagsProperties: + EmitClangCommentHTMLTagsProperties(Records, OS); + break; + case GenClangCommentCommandInfo: + EmitClangCommentCommandInfo(Records, OS); + break; case GenOptParserDefs: EmitOptParser(Records, OS, true); break; diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h index 779de7c734..838fc84dca 100644 --- a/utils/TableGen/TableGenBackends.h +++ b/utils/TableGen/TableGenBackends.h @@ -47,6 +47,11 @@ void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS); void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS); +void EmitClangCommentHTMLTags(RecordKeeper &Records, raw_ostream &OS); +void EmitClangCommentHTMLTagsProperties(RecordKeeper &Records, raw_ostream &OS); + +void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS); + void EmitNeon(RecordKeeper &Records, raw_ostream &OS); void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS); void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS); diff --git a/utils/analyzer/CmpRuns.py b/utils/analyzer/CmpRuns.py index c8f05cbcf4..f2961cf0ac 100755 --- a/utils/analyzer/CmpRuns.py +++ b/utils/analyzer/CmpRuns.py @@ -146,9 +146,7 @@ def loadResults(path, opts, root = "", deleteEmpty=True): for d in data['diagnostics']: # FIXME: Why is this named files, when does it have multiple # files? - # TODO: Add the assert back in after we fix the - # plist-html output. - # assert len(d['HTMLDiagnostics_files']) == 1 + assert len(d['HTMLDiagnostics_files']) == 1 htmlFiles.append(d.pop('HTMLDiagnostics_files')[0]) else: htmlFiles = [None] * len(data['diagnostics']) diff --git a/utils/analyzer/SATestAdd.py b/utils/analyzer/SATestAdd.py index 2d32533f6b..64ff4ff656 100755 --- a/utils/analyzer/SATestAdd.py +++ b/utils/analyzer/SATestAdd.py @@ -33,7 +33,7 @@ def isExistingProject(PMapFile, projectID) : # Params: # Dir is the directory where the sources are. # ID is a short string used to identify a project. -def addNewProject(ID, IsScanBuild) : +def addNewProject(ID, BuildMode) : CurDir = os.path.abspath(os.curdir) Dir = SATestBuild.getProjectDir(ID) if not os.path.exists(Dir): @@ -41,7 +41,7 @@ def addNewProject(ID, IsScanBuild) : sys.exit(-1) # Build the project. - SATestBuild.testProject(ID, IsScanBuild, IsReferenceBuild=True, Dir=Dir) + SATestBuild.testProject(ID, BuildMode, IsReferenceBuild=True, Dir=Dir) # Add the project ID to the project map. ProjectMapPath = os.path.join(CurDir, SATestBuild.ProjectMapFile) @@ -57,7 +57,7 @@ def addNewProject(ID, IsScanBuild) : print >> sys.stdout, "Reference output has been regenerated." else: PMapWriter = csv.writer(PMapFile) - PMapWriter.writerow( (ID, int(IsScanBuild)) ); + PMapWriter.writerow( (ID, int(BuildMode)) ); print "The project map is updated: ", ProjectMapPath finally: PMapFile.close() @@ -69,12 +69,14 @@ if __name__ == '__main__': if len(sys.argv) < 2: print >> sys.stderr, 'Usage: ', sys.argv[0],\ 'project_ID <mode>' \ - 'mode - 0 for single file project; 1 for scan_build' + 'mode - 0 for single file project; ' \ + '1 for scan_build; ' \ + '2 for single file c++11 project' sys.exit(-1) - IsScanBuild = 1 + BuildMode = 1 if (len(sys.argv) >= 3): - IsScanBuild = int(sys.argv[2]) - assert((IsScanBuild == 0) | (IsScanBuild == 1)) + BuildMode = int(sys.argv[2]) + assert((BuildMode == 0) | (BuildMode == 1) | (BuildMode == 2)) - addNewProject(sys.argv[1], IsScanBuild) + addNewProject(sys.argv[1], BuildMode) diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py index fd4bc8a8ee..baab11312e 100755 --- a/utils/analyzer/SATestBuild.py +++ b/utils/analyzer/SATestBuild.py @@ -42,39 +42,66 @@ import os import csv import sys import glob +import math import shutil import time import plistlib from subprocess import check_call, CalledProcessError -# Project map stores info about all the "registered" projects. -ProjectMapFile = "projectMap.csv" - -# Names of the project specific scripts. -# The script that needs to be executed before the build can start. -CleanupScript = "cleanup_run_static_analyzer.sh" -# This is a file containing commands for scan-build. -BuildScript = "run_static_analyzer.cmd" - -# The log file name. -LogFolderName = "Logs" -BuildLogName = "run_static_analyzer.log" -# Summary file - contains the summary of the failures. Ex: This info can be be -# displayed when buildbot detects a build failure. -NumOfFailuresInSummary = 10 -FailuresSummaryFileName = "failures.txt" -# Summary of the result diffs. -DiffsSummaryFileName = "diffs.txt" - -# The scan-build result directory. -SBOutputDirName = "ScanBuildResults" -SBOutputDirReferencePrefix = "Ref" - -# The list of checkers used during analyzes. -# Currently, consists of all the non experimental checkers. -Checkers="experimental.security.taint,core,deadcode,security,unix,osx" - -Verbose = 1 +#------------------------------------------------------------------------------ +# Helper functions. +#------------------------------------------------------------------------------ + +def detectCPUs(): + """ + Detects the number of CPUs on a system. Cribbed from pp. + """ + # Linux, Unix and MacOS: + if hasattr(os, "sysconf"): + if os.sysconf_names.has_key("SC_NPROCESSORS_ONLN"): + # Linux & Unix: + ncpus = os.sysconf("SC_NPROCESSORS_ONLN") + if isinstance(ncpus, int) and ncpus > 0: + return ncpus + else: # OSX: + return int(capture(['sysctl', '-n', 'hw.ncpu'])) + # Windows: + if os.environ.has_key("NUMBER_OF_PROCESSORS"): + ncpus = int(os.environ["NUMBER_OF_PROCESSORS"]) + if ncpus > 0: + return ncpus + return 1 # Default + +def which(command, paths = None): + """which(command, [paths]) - Look up the given command in the paths string + (or the PATH environment variable, if unspecified).""" + + if paths is None: + paths = os.environ.get('PATH','') + + # Check for absolute match first. + if os.path.exists(command): + return command + + # Would be nice if Python had a lib function for this. + if not paths: + paths = os.defpath + + # Get suffixes to search. + # On Cygwin, 'PATHEXT' may exist but it should not be used. + if os.pathsep == ';': + pathext = os.environ.get('PATHEXT', '').split(';') + else: + pathext = [''] + + # Search the paths... + for path in paths.split(os.pathsep): + for ext in pathext: + p = os.path.join(path, command + ext) + if os.path.exists(p): + return p + + return None # Make sure we flush the output after every print statement. class flushfile(object): @@ -104,6 +131,52 @@ def getSBOutputDirName(IsReferenceBuild) : else : return SBOutputDirName +#------------------------------------------------------------------------------ +# Configuration setup. +#------------------------------------------------------------------------------ + +# Find Clang for static analysis. +Clang = which("clang", os.environ['PATH']) +if not Clang: + print "Error: cannot find 'clang' in PATH" + sys.exit(-1) + +# Number of jobs. +Jobs = math.ceil(detectCPUs() * 0.75) + +# Project map stores info about all the "registered" projects. +ProjectMapFile = "projectMap.csv" + +# Names of the project specific scripts. +# The script that needs to be executed before the build can start. +CleanupScript = "cleanup_run_static_analyzer.sh" +# This is a file containing commands for scan-build. +BuildScript = "run_static_analyzer.cmd" + +# The log file name. +LogFolderName = "Logs" +BuildLogName = "run_static_analyzer.log" +# Summary file - contains the summary of the failures. Ex: This info can be be +# displayed when buildbot detects a build failure. +NumOfFailuresInSummary = 10 +FailuresSummaryFileName = "failures.txt" +# Summary of the result diffs. +DiffsSummaryFileName = "diffs.txt" + +# The scan-build result directory. +SBOutputDirName = "ScanBuildResults" +SBOutputDirReferencePrefix = "Ref" + +# The list of checkers used during analyzes. +# Currently, consists of all the non experimental checkers. +Checkers="alpha.security.taint,core,deadcode,security,unix,osx" + +Verbose = 1 + +#------------------------------------------------------------------------------ +# Test harness logic. +#------------------------------------------------------------------------------ + # Run pre-processing script if any. def runCleanupScript(Dir, PBuildLogFile): ScriptPath = os.path.join(Dir, CleanupScript) @@ -129,13 +202,19 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile): BuildScriptPath = os.path.join(Dir, BuildScript) if not os.path.exists(BuildScriptPath): print "Error: build script is not defined: %s" % BuildScriptPath - sys.exit(-1) - SBOptions = "-plist-html -o " + SBOutputDir + " " + sys.exit(-1) + SBOptions = "--use-analyzer " + Clang + " " + SBOptions += "-plist-html -o " + SBOutputDir + " " SBOptions += "-enable-checker " + Checkers + " " try: SBCommandFile = open(BuildScriptPath, "r") SBPrefix = "scan-build " + SBOptions + " " for Command in SBCommandFile: + # If using 'make', auto imply a -jX argument + # to speed up analysis. xcodebuild will + # automatically use the maximum number of cores. + if Command.startswith("make "): + Command += "-j" + Jobs SBCommand = SBPrefix + Command if Verbose == 1: print " Executing: %s" % (SBCommand,) @@ -160,17 +239,20 @@ def isValidSingleInputFile(FileName): (Ext == ".m") | (Ext == "")) : return True return False - + # Run analysis on a set of preprocessed files. -def runAnalyzePreprocessed(Dir, SBOutputDir): +def runAnalyzePreprocessed(Dir, SBOutputDir, Mode): if os.path.exists(os.path.join(Dir, BuildScript)): print "Error: The preprocessed files project should not contain %s" % \ BuildScript raise Exception() - CmdPrefix = "clang -cc1 -analyze -analyzer-output=plist -w " + CmdPrefix = Clang + " -cc1 -analyze -analyzer-output=plist -w " CmdPrefix += "-analyzer-checker=" + Checkers +" -fcxx-exceptions -fblocks " + if (Mode == 2) : + CmdPrefix += "-std=c++11 " + PlistPath = os.path.join(Dir, SBOutputDir, "date") FailPath = os.path.join(PlistPath, "failures"); os.makedirs(FailPath); @@ -208,7 +290,7 @@ def runAnalyzePreprocessed(Dir, SBOutputDir): if Failed == False: os.remove(LogFile.name); -def buildProject(Dir, SBOutputDir, IsScanBuild, IsReferenceBuild): +def buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild): TBegin = time.time() BuildLogPath = os.path.join(SBOutputDir, LogFolderName, BuildLogName) @@ -238,10 +320,10 @@ def buildProject(Dir, SBOutputDir, IsScanBuild, IsReferenceBuild): try: runCleanupScript(Dir, PBuildLogFile) - if IsScanBuild: + if (ProjectBuildMode == 1): runScanBuild(Dir, SBOutputDir, PBuildLogFile) else: - runAnalyzePreprocessed(Dir, SBOutputDir) + runAnalyzePreprocessed(Dir, SBOutputDir, ProjectBuildMode) if IsReferenceBuild : runCleanupScript(Dir, PBuildLogFile) @@ -395,7 +477,7 @@ def updateSVN(Mode, ProjectsMap): print "Error: SVN update failed." sys.exit(-1) -def testProject(ID, IsScanBuild, IsReferenceBuild=False, Dir=None): +def testProject(ID, ProjectBuildMode, IsReferenceBuild=False, Dir=None): print " \n\n--- Building project %s" % (ID,) TBegin = time.time() @@ -409,7 +491,7 @@ def testProject(ID, IsScanBuild, IsReferenceBuild=False, Dir=None): RelOutputDir = getSBOutputDirName(IsReferenceBuild) SBOutputDir = os.path.join(Dir, RelOutputDir) - buildProject(Dir, SBOutputDir, IsScanBuild, IsReferenceBuild) + buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild) checkBuild(SBOutputDir) @@ -427,8 +509,9 @@ def testAll(IsReferenceBuild = False, UpdateSVN = False): if (len(I) != 2) : print "Error: Rows in the ProjectMapFile should have 3 entries." raise Exception() - if (not ((I[1] == "1") | (I[1] == "0"))): - print "Error: Second entry in the ProjectMapFile should be 0 or 1." + if (not ((I[1] == "0") | (I[1] == "1") | (I[1] == "2"))): + print "Error: Second entry in the ProjectMapFile should be 0" \ + " (single file), 1 (project), or 2(single file c++11)." raise Exception() # When we are regenerating the reference results, we might need to diff --git a/utils/analyzer/SumTimerInfo.py b/utils/analyzer/SumTimerInfo.py index a6731bb8f2..4ef1ceb4ce 100644 --- a/utils/analyzer/SumTimerInfo.py +++ b/utils/analyzer/SumTimerInfo.py @@ -28,6 +28,8 @@ if __name__ == '__main__': ReachableBlocks = 0 ReachedMaxSteps = 0 NumSteps = 0 + NumInlinedCallSites = 0 + NumBifurcatedCallSites = 0 MaxCFGSize = 0 Mode = 1 for line in f: @@ -39,25 +41,31 @@ if __name__ == '__main__': Count = Count + 1 if (float(s[6]) > MaxTime) : MaxTime = float(s[6]) - if ((("warning generated." in line) or ("warnings generated." in line)) and Mode == 1) : + if ((("warning generated." in line) or ("warnings generated" in line)) and Mode == 1) : s = line.split() Warnings = Warnings + int(s[0]) - if (("The # of functions analysed (as top level)." in line) and (Mode == 1)) : + if (("The # of functions analysed (as top level)" in line) and (Mode == 1)) : s = line.split() FunctionsAnalyzed = FunctionsAnalyzed + int(s[0]) if (("The % of reachable basic blocks" in line) and (Mode == 1)) : s = line.split() ReachableBlocks = ReachableBlocks + int(s[0]) - if (("The # of times we reached the max number of steps." in line) and (Mode == 1)) : + if (("The # of times we reached the max number of steps" in line) and (Mode == 1)) : s = line.split() ReachedMaxSteps = ReachedMaxSteps + int(s[0]) if (("The maximum number of basic blocks in a function" in line) and (Mode == 1)) : s = line.split() if (MaxCFGSize < int(s[0])) : MaxCFGSize = int(s[0]) - if (("The # of steps executed." in line) and (Mode == 1)) : + if (("The # of steps executed" in line) and (Mode == 1)) : s = line.split() NumSteps = NumSteps + int(s[0]) + if (("The # of times we inlined a call" in line) and (Mode == 1)) : + s = line.split() + NumInlinedCallSites = NumInlinedCallSites + int(s[0]) + if (("The # of times we split the path due to imprecise dynamic dispatch info" in line) and (Mode == 1)) : + s = line.split() + NumBifurcatedCallSites = NumBifurcatedCallSites + int(s[0]) if ((") Total" in line) and (Mode == 1)) : s = line.split() TotalTime = TotalTime + float(s[6]) @@ -69,6 +77,7 @@ if __name__ == '__main__': print "Reachable Blocks %d" % (ReachableBlocks) print "Reached Max Steps %d" % (ReachedMaxSteps) print "Number of Steps %d" % (NumSteps) + print "Number of Inlined calls %d (bifurcated %d)" % (NumInlinedCallSites, NumBifurcatedCallSites) print "MaxTime %f" % (MaxTime) print "TotalTime %f" % (TotalTime) print "Max CFG Size %d" % (MaxCFGSize) diff --git a/utils/analyzer/update_plist_test.pl b/utils/analyzer/update_plist_test.pl new file mode 100755 index 0000000000..abb74a57c3 --- /dev/null +++ b/utils/analyzer/update_plist_test.pl @@ -0,0 +1,51 @@ +#!/usr/bin/perl -w +use strict; +require File::Temp; +use File::Temp (); + +die "update_plist_test <test file> <plist file>\n" if ($#ARGV < 1); +my $testFile = shift @ARGV; +die "error: cannot read file $testFile\n" if (! -r $testFile); +my $plistFile = shift @ARGV; +die "error: cannot read file $plistFile\n" if (! -r $plistFile); + +# Create a temp file for the new test. +my $fh = File::Temp->new(); +my $filename = $fh->filename; +$fh->unlink_on_destroy(1); + +# Copy the existing temp file, skipping the FileCheck comments. +open (IN, $testFile) or die "cannot open $testFile\n"; +while (<IN>) { + next if (/^\/\/ CHECK/); + print $fh $_; +} +close(IN); + +# Copy the plist data, and specially format it. +open (IN, $plistFile) or die "cannot open $plistFile\n"; +my $firstArray = 1; +my $first = 1; +while (<IN>) { + # Skip everything not indented. + next if (/^[^\s]/); + # Skip the first array entry, which is for files. + if ($firstArray) { + if (/<\/array>/) { $firstArray = 0; } + next; + } + # Format the CHECK lines. + if ($first) { + print $fh "// CHECK: "; + $first = 0; + } + else { + print $fh "// CHECK-NEXT: "; + } + print $fh $_; +} +close (IN); +close ($fh); + +`cp $filename $testFile`; +print "updated $testFile\n"; |