Computer Laboratory

instrument.cpp
Go to the documentation of this file.
1 //===- instrument.cpp - Driver for TESLA instrumentation passes -----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is derived from LLVM's 'tools/opt/opt.cpp'. It has been cut down
11 // to only invokes TESLA instrumentation passes, but many useful arguments to
12 // 'opt' still work, e.g. -p, -S and -verify-each.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "Assertion.h"
17 #include "Callee.h"
18 #include "Caller.h"
19 #include "Debug.h"
20 #include "FieldReference.h"
21 #include "Manifest.h"
22 
23 #include "llvm/IR/DataLayout.h"
24 #include "llvm/IR/LLVMContext.h"
25 #include "llvm/IR/Module.h"
26 #include "llvm/IRReader/IRReader.h"
27 #include "llvm/CodeGen/CommandFlags.h"
28 #include "llvm/Bitcode/ReaderWriter.h"
29 #include "llvm/Assembly/PrintModulePass.h"
30 #include "llvm/Analysis/Verifier.h"
31 #include "llvm/Analysis/CallGraph.h"
32 #include "llvm/Target/TargetLibraryInfo.h"
33 #include "llvm/Target/TargetMachine.h"
34 #include "llvm/ADT/Triple.h"
35 #include "llvm/Support/SourceMgr.h"
36 #include "llvm/Support/ManagedStatic.h"
37 #include "llvm/Support/PrettyStackTrace.h"
38 #include "llvm/Support/SystemUtils.h"
39 #include "llvm/Support/TargetRegistry.h"
40 #include "llvm/Support/ToolOutputFile.h"
41 #include "llvm/PassManager.h"
42 
43 using namespace llvm;
44 
45 // Command line options.
46 //
47 static cl::opt<std::string>
48 InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
49  cl::init("-"), cl::value_desc("filename"));
50 
51 static cl::opt<std::string>
52 OutputFilename("o", cl::desc("Override output filename"),
53  cl::value_desc("filename"));
54 
55 static cl::opt<bool>
56 Force("f", cl::desc("Enable binary output on terminals"));
57 
58 static cl::opt<bool>
59 PrintEachXForm("p", cl::desc("Print module after each transformation"));
60 
61 static cl::opt<bool>
62 OutputAssembly("S", cl::desc("Write output as LLVM assembly"));
63 
64 static cl::opt<bool>
65 SuppressDI("suppress-debug-instrumentation",
66  cl::desc("Suppress the generation of debug output in instrumentation"));
67 
68 static cl::opt<bool>
69 VerifyEach("verify-each", cl::desc("Verify after each transform"));
70 
71 
72 static inline void addPass(PassManagerBase &PM, Pass *P) {
73  // Add the pass to the pass manager...
74  PM.add(P);
75 
76  // If we are verifying all of the intermediate steps, add the verifier...
77  if (VerifyEach) PM.add(createVerifierPass());
78 
79  // Optionally print the result of each pass...
80  if (PrintEachXForm) PM.add(createPrintModulePass(&errs()));
81 }
82 
83 //===----------------------------------------------------------------------===//
84 //
85 int main(int argc, char **argv) {
86  llvm::PrettyStackTraceProgram X(argc, argv);
87 
88  llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
89  LLVMContext &Context = getGlobalContext();
90 
91  cl::ParseCommandLineOptions(argc, argv, "TESLA bitcode instrumenter\n");
92 
93  SMDiagnostic Err;
94 
95  // Load TESLA manifest file.
96  OwningPtr<tesla::Manifest> Manifest(tesla::Manifest::load(llvm::errs()));
97  if (!Manifest)
98  tesla::panic("unable to load TESLA manifest");
99 
100  // Load the input module...
101  std::auto_ptr<Module> M;
102  M.reset(ParseIRFile(InputFilename, Err, Context));
103 
104  if (M.get() == 0) {
105  Err.print(argv[0], errs());
106  return 1;
107  }
108 
109  // Output stream...
110  OwningPtr<tool_output_file> Out;
111  if (OutputFilename.empty())
112  OutputFilename = "-";
113 
114  std::string ErrorInfo;
115  Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo,
116  raw_fd_ostream::F_Binary));
117  if (!ErrorInfo.empty()) {
118  errs() << ErrorInfo << '\n';
119  return 1;
120  }
121 
122  // If the output is set to be emitted to standard out, and standard out is a
123  // console, print out a warning message and refuse to do it. We don't
124  // impress anyone by spewing tons of binary goo to a terminal.
125  bool NoOutput = false;
126  if (!Force && !OutputAssembly)
127  if (CheckBitcodeOutputToConsole(Out->os(), true))
128  NoOutput = true;
129 
130  // Create a PassManager to hold and optimize the collection of passes we are
131  // about to build.
132  //
133  PassManager Passes;
134 
135  // Add an appropriate TargetLibraryInfo pass for the module's triple.
136  TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(M->getTargetTriple()));
137  Passes.add(TLI);
138 
139  // Add an appropriate DataLayout instance for this module.
140  DataLayout *TD = 0;
141  const std::string &ModuleDataLayout = M.get()->getDataLayout();
142  if (!ModuleDataLayout.empty())
143  TD = new DataLayout(ModuleDataLayout);
144 
145  if (TD)
146  Passes.add(TD);
147 
148  // Just add TESLA instrumentation passes.
149  addPass(Passes, new tesla::AssertionSiteInstrumenter(*Manifest, SuppressDI));
150  addPass(Passes, new tesla::FnCalleeInstrumenter(*Manifest, SuppressDI));
151  addPass(Passes, new tesla::FnCallerInstrumenter(*Manifest, SuppressDI));
152  addPass(Passes, new tesla::FieldReferenceInstrumenter(*Manifest, SuppressDI));
153 
154  // Write bitcode or assembly to the output as the last step...
155  if (!NoOutput) {
156  if (OutputAssembly)
157  Passes.add(createPrintModulePass(&Out->os()));
158  else
159  Passes.add(createBitcodeWriterPass(Out->os()));
160  }
161 
162  // Before executing passes, print the final values of the LLVM options.
163  cl::PrintOptionValues();
164 
165  // Now that we have all of the passes ready, run them.
166  Passes.run(*M.get());
167 
168  // Declare success.
169  if (!NoOutput)
170  Out->keep();
171 
172  return 0;
173 }
174