llvm-diff.cpp revision 221337
1254721Semaste//===-- llvm-diff.cpp - Module comparator command-line driver ---*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste//
10254721Semaste// This file defines the command-line driver for the difference engine.
11254721Semaste//
12254721Semaste//===----------------------------------------------------------------------===//
13254721Semaste
14254721Semaste#include "DiffLog.h"
15254721Semaste#include "DifferenceEngine.h"
16254721Semaste
17254721Semaste#include "llvm/LLVMContext.h"
18254721Semaste#include "llvm/Module.h"
19254721Semaste#include "llvm/Type.h"
20254721Semaste#include "llvm/ADT/DenseMap.h"
21254721Semaste#include "llvm/ADT/SmallVector.h"
22254721Semaste#include "llvm/ADT/StringRef.h"
23254721Semaste#include "llvm/Support/CommandLine.h"
24254721Semaste#include "llvm/Support/IRReader.h"
25254721Semaste#include "llvm/Support/MemoryBuffer.h"
26254721Semaste#include "llvm/Support/raw_ostream.h"
27254721Semaste#include "llvm/Support/SourceMgr.h"
28254721Semaste
29254721Semaste#include <string>
30254721Semaste#include <utility>
31254721Semaste
32254721Semaste
33254721Semasteusing namespace llvm;
34254721Semaste
35254721Semaste/// Reads a module from a file.  On error, messages are written to stderr
36254721Semaste/// and null is returned.
37254721Semastestatic Module *ReadModule(LLVMContext &Context, StringRef Name) {
38254721Semaste  SMDiagnostic Diag;
39254721Semaste  Module *M = ParseIRFile(Name, Diag, Context);
40254721Semaste  if (!M)
41254721Semaste    Diag.Print("llvmdiff", errs());
42254721Semaste  return M;
43254721Semaste}
44254721Semaste
45254721Semastestatic void diffGlobal(DifferenceEngine &Engine, Module *L, Module *R,
46254721Semaste                       StringRef Name) {
47254721Semaste  // Drop leading sigils from the global name.
48254721Semaste  if (Name.startswith("@")) Name = Name.substr(1);
49269024Semaste
50269024Semaste  Function *LFn = L->getFunction(Name);
51269024Semaste  Function *RFn = R->getFunction(Name);
52254721Semaste  if (LFn && RFn)
53254721Semaste    Engine.diff(LFn, RFn);
54254721Semaste  else if (!LFn && !RFn)
55254721Semaste    errs() << "No function named @" << Name << " in either module\n";
56254721Semaste  else if (!LFn)
57254721Semaste    errs() << "No function named @" << Name << " in left module\n";
58254721Semaste  else
59254721Semaste    errs() << "No function named @" << Name << " in right module\n";
60254721Semaste}
61254721Semaste
62254721Semastestatic cl::opt<std::string> LeftFilename(cl::Positional,
63254721Semaste                                         cl::desc("<first file>"),
64254721Semaste                                         cl::Required);
65254721Semastestatic cl::opt<std::string> RightFilename(cl::Positional,
66254721Semaste                                          cl::desc("<second file>"),
67254721Semaste                                          cl::Required);
68254721Semastestatic cl::list<std::string> GlobalsToCompare(cl::Positional,
69254721Semaste                                              cl::desc("<globals to compare>"));
70254721Semaste
71254721Semasteint main(int argc, char **argv) {
72254721Semaste  cl::ParseCommandLineOptions(argc, argv);
73254721Semaste
74254721Semaste  LLVMContext Context;
75254721Semaste
76254721Semaste  // Load both modules.  Die if that fails.
77254721Semaste  Module *LModule = ReadModule(Context, LeftFilename);
78254721Semaste  Module *RModule = ReadModule(Context, RightFilename);
79254721Semaste  if (!LModule || !RModule) return 1;
80254721Semaste
81254721Semaste  DiffConsumer Consumer(LModule, RModule);
82254721Semaste  DifferenceEngine Engine(Context, Consumer);
83254721Semaste
84254721Semaste  // If any global names were given, just diff those.
85254721Semaste  if (!GlobalsToCompare.empty()) {
86254721Semaste    for (unsigned I = 0, E = GlobalsToCompare.size(); I != E; ++I)
87254721Semaste      diffGlobal(Engine, LModule, RModule, GlobalsToCompare[I]);
88254721Semaste
89254721Semaste  // Otherwise, diff everything in the module.
90254721Semaste  } else {
91254721Semaste    Engine.diff(LModule, RModule);
92254721Semaste  }
93254721Semaste
94254721Semaste  delete LModule;
95254721Semaste  delete RModule;
96254721Semaste
97254721Semaste  return Consumer.hadDifferences();
98254721Semaste}
99254721Semaste