int main(int argc, char **argv) {
  LLVMContext &Context = getGlobalContext();
  SMDiagnostic Err;
  cl::ParseCommandLineOptions(argc, argv, "PNaCl Bitcode ABI checker\n");

  OwningPtr<Module> Mod(
      NaClParseIRFile(InputFilename, InputFileFormat, Err, Context));
  if (Mod.get() == 0) {
    Err.print(argv[0], errs());
    return 1;
  }
  PNaClABIErrorReporter ABIErrorReporter;
  ABIErrorReporter.setNonFatal();
  bool ErrorsFound = false;

  OwningPtr<ModulePass> ModuleChecker(
      createPNaClABIVerifyModulePass(&ABIErrorReporter));
  ModuleChecker->doInitialization(*Mod);
  ModuleChecker->runOnModule(*Mod);
  ErrorsFound |= CheckABIVerifyErrors(ABIErrorReporter, "Module");

  OwningPtr<FunctionPassManager> PM(new FunctionPassManager(&*Mod));
  PM->add(new DataLayout(&*Mod));
  PM->add(createPNaClABIVerifyFunctionsPass(&ABIErrorReporter));

  PM->doInitialization();
  for (Module::iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) {
    PM->run(*I);
    ErrorsFound |=
        CheckABIVerifyErrors(ABIErrorReporter, "Function " + I->getName());
  }
  PM->doFinalization();

  return ErrorsFound ? 1 : 0;
}
// Print any errors collected by the error reporter. Return true if
// there were any.
static bool CheckABIVerifyErrors(PNaClABIErrorReporter &Reporter,
                                 const Twine &Name) {
  bool HasErrors = Reporter.getErrorCount() > 0;
  if (HasErrors) {
    if (!Quiet) {
      outs() << "ERROR: " << Name << " is not valid PNaCl bitcode:\n";
      Reporter.printErrors(outs());
    }
  }
  Reporter.reset();
  return HasErrors;
}
static void CheckABIVerifyErrors(PNaClABIErrorReporter &Reporter,
                                 const Twine &Name) {
  if (PNaClABIVerify && Reporter.getErrorCount() > 0) {
    std::string errors;
    raw_string_ostream os(errors);
    os << (PNaClABIVerifyFatalErrors ? "ERROR: " : "WARNING: ");
    os << Name << " is not valid PNaCl bitcode:\n";
    Reporter.printErrors(os);
    if (PNaClABIVerifyFatalErrors) {
      report_fatal_error(os.str());
    }
    errs() << os.str();
  }
  Reporter.reset();
}