diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 78dc0d5..ef808ad 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -49,914 +49,7 @@
     PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {}
 
 //===----------------------------------------------------------------------===//
-// Utility functions.
-//===----------------------------------------------------------------------===//
-
-static const char *getAnalysisStoreName(AnalysisStores Kind) {
-  switch (Kind) {
-  default:
-    llvm_unreachable("Unknown analysis store!");
-#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
-  case NAME##Model: return CMDFLAG;
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-  }
-}
-
-static const char *getAnalysisConstraintName(AnalysisConstraints Kind) {
-  switch (Kind) {
-  default:
-    llvm_unreachable("Unknown analysis constraints!");
-#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
-  case NAME##Model: return CMDFLAG;
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-  }
-}
-
-static const char *getAnalysisDiagClientName(AnalysisDiagClients Kind) {
-  switch (Kind) {
-  default:
-    llvm_unreachable("Unknown analysis client!");
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE) \
-  case PD_##NAME: return CMDFLAG;
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-  }
-}
-
-static const char *getAnalysisPurgeModeName(AnalysisPurgeMode Kind) {
-  switch (Kind) {
-  default:
-    llvm_unreachable("Unknown analysis purge mode!");
-#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \
-  case NAME: return CMDFLAG;
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-  }
-}
-
-static const char *getAnalysisIPAModeName(AnalysisIPAMode Kind) {
-  switch (Kind) {
-  default:
-    llvm_unreachable("Unknown analysis ipa mode!");
-#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) \
-  case NAME: return CMDFLAG;
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-  }
-}
-
-static const char *
-  getAnalysisInliningModeName(AnalysisInliningMode Kind) {
-  switch (Kind) {
-  default:
-    llvm_unreachable("Unknown analysis inlining mode!");
-#define ANALYSIS_INLINE_SELECTION(NAME, CMDFLAG, DESC) \
-  case NAME: return CMDFLAG;
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// Serialization (to args)
-//===----------------------------------------------------------------------===//
-
-namespace {
-  /// ToArgsList - Helper class to create a list of std::strings.
-  class ToArgsList {
-    std::vector<std::string> &Res;
-  public:
-    explicit ToArgsList(std::vector<std::string> &Res) : Res(Res) {}
-
-    void push_back(StringRef Str) {
-      // Avoid creating a temporary string.
-      Res.push_back(std::string());
-      Res.back().assign(Str.data(), Str.size());
-    }
-
-    void push_back(StringRef Str1, StringRef Str2) {
-      push_back(Str1);
-      push_back(Str2);
-    }
-  };
-}
-
-static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, ToArgsList &Res) {
-  if (Opts.ShowCheckerHelp)
-    Res.push_back("-analyzer-checker-help");
-  if (Opts.AnalysisStoreOpt != RegionStoreModel)
-    Res.push_back("-analyzer-store",
-                  getAnalysisStoreName(Opts.AnalysisStoreOpt));
-  if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel)
-    Res.push_back("-analyzer-constraints",
-                  getAnalysisConstraintName(Opts.AnalysisConstraintsOpt));
-  if (Opts.AnalysisDiagOpt != PD_HTML)
-    Res.push_back("-analyzer-output",
-                  getAnalysisDiagClientName(Opts.AnalysisDiagOpt));
-  if (Opts.AnalysisPurgeOpt != PurgeStmt)
-    Res.push_back("-analyzer-purge",
-                  getAnalysisPurgeModeName(Opts.AnalysisPurgeOpt));
-  if (!Opts.AnalyzeSpecificFunction.empty())
-    Res.push_back("-analyze-function", Opts.AnalyzeSpecificFunction);
-  if (Opts.IPAMode != DynamicDispatchBifurcate)
-    Res.push_back("-analyzer-ipa", getAnalysisIPAModeName(Opts.IPAMode));
-  if (Opts.InliningMode != NoRedundancy)
-    Res.push_back("-analyzer-inlining-mode",
-                  getAnalysisInliningModeName(Opts.InliningMode));
-
-  if (Opts.AnalyzeAll)
-    Res.push_back("-analyzer-opt-analyze-headers");
-  if (Opts.AnalyzerDisplayProgress)
-    Res.push_back("-analyzer-display-progress");
-  if (Opts.AnalyzeNestedBlocks)
-    Res.push_back("-analyzer-opt-analyze-nested-blocks");
-  if (Opts.eagerlyAssumeBinOpBifurcation)
-    Res.push_back("-analyzer-eagerly-assume");
-  if (Opts.TrimGraph)
-    Res.push_back("-trim-egraph");
-  if (Opts.visualizeExplodedGraphWithGraphViz)
-    Res.push_back("-analyzer-viz-egraph-graphviz");
-  if (Opts.visualizeExplodedGraphWithUbiGraph)
-    Res.push_back("-analyzer-viz-egraph-ubigraph");
-  if (Opts.NoRetryExhausted)
-    Res.push_back("-analyzer-disable-retry-exhausted");
-
-  for (unsigned i = 0, e = Opts.CheckersControlList.size(); i != e; ++i) {
-    const std::pair<std::string, bool> &opt = Opts.CheckersControlList[i];
-    if (opt.second)
-      Res.push_back("-analyzer-disable-checker");
-    else
-      Res.push_back("-analyzer-checker");
-    Res.push_back(opt.first);
-  }
-}
-
-static void CodeGenOptsToArgs(const CodeGenOptions &Opts, ToArgsList &Res) {
-  switch (Opts.getDebugInfo()) {
-    case CodeGenOptions::NoDebugInfo:
-      break;
-    case CodeGenOptions::DebugLineTablesOnly:
-      Res.push_back("-gline-tables-only");
-      break;
-    case CodeGenOptions::LimitedDebugInfo:
-      Res.push_back("-g");
-      Res.push_back("-flimit-debug-info");
-      break;
-    case CodeGenOptions::FullDebugInfo:
-      Res.push_back("-g");
-      Res.push_back("-fno-limit-debug-info");
-      break;
-  }
-  if (Opts.DebugColumnInfo)
-    Res.push_back("-gcolumn-info");
-  if (Opts.DisableLLVMOpts)
-    Res.push_back("-disable-llvm-optzns");
-  if (Opts.DisableRedZone)
-    Res.push_back("-disable-red-zone");
-  if (Opts.DisableTailCalls)
-    Res.push_back("-mdisable-tail-calls");
-  if (!Opts.DebugCompilationDir.empty())
-    Res.push_back("-fdebug-compilation-dir", Opts.DebugCompilationDir);
-  if (!Opts.DwarfDebugFlags.empty())
-    Res.push_back("-dwarf-debug-flags", Opts.DwarfDebugFlags);
-  if (Opts.EmitGcovArcs)
-    Res.push_back("-femit-coverage-data");
-  if (Opts.EmitGcovNotes)
-    Res.push_back("-femit-coverage-notes");
-  if (Opts.EmitOpenCLArgMetadata)
-    Res.push_back("-cl-kernel-arg-info");
-  if (!Opts.MergeAllConstants)
-    Res.push_back("-fno-merge-all-constants");
-  if (Opts.NoCommon)
-    Res.push_back("-fno-common");
-  if (Opts.ForbidGuardVariables)
-    Res.push_back("-fforbid-guard-variables");
-  if (Opts.UseRegisterSizedBitfieldAccess)
-    Res.push_back("-fuse-register-sized-bitfield-access");
-  if (Opts.NoImplicitFloat)
-    Res.push_back("-no-implicit-float");
-  if (Opts.OmitLeafFramePointer)
-    Res.push_back("-momit-leaf-frame-pointer");
-  if (Opts.OptimizeSize) {
-    assert(Opts.OptimizationLevel == 2 && "Invalid options!");
-    Opts.OptimizeSize == 1 ? Res.push_back("-Os") : Res.push_back("-Oz");
-  } else if (Opts.OptimizationLevel != 0)
-    Res.push_back("-O" + llvm::utostr(Opts.OptimizationLevel));
-  if (!Opts.MainFileName.empty())
-    Res.push_back("-main-file-name", Opts.MainFileName);
-  if (Opts.NoInfsFPMath)
-    Res.push_back("-menable-no-infinities");
-  if (Opts.NoNaNsFPMath)
-    Res.push_back("-menable-no-nans");
-  // SimplifyLibCalls is only derived.
-  // TimePasses is only derived.
-  // UnitAtATime is unused.
-  // Inlining is only derived.
-
-  // UnrollLoops is derived, but also accepts an option, no
-  // harm in pushing it back here.
-  if (Opts.UnrollLoops)
-    Res.push_back("-funroll-loops");
-  if (Opts.DataSections)
-    Res.push_back("-fdata-sections");
-  if (Opts.FunctionSections)
-    Res.push_back("-ffunction-sections");
-  if (Opts.AsmVerbose)
-    Res.push_back("-masm-verbose");
-  if (!Opts.CodeModel.empty())
-    Res.push_back("-mcode-model", Opts.CodeModel);
-  if (Opts.CUDAIsDevice)
-    Res.push_back("-fcuda-is-device");
-  if (!Opts.CXAAtExit)
-    Res.push_back("-fno-use-cxa-atexit");
-  if (Opts.CXXCtorDtorAliases)
-    Res.push_back("-mconstructor-aliases");
-  if (Opts.ObjCAutoRefCountExceptions)
-    Res.push_back("-fobjc-arc-eh");
-  if (!Opts.DebugPass.empty()) {
-    Res.push_back("-mdebug-pass", Opts.DebugPass);
-  }
-  if (Opts.DisableFPElim)
-    Res.push_back("-mdisable-fp-elim");
-  if (!Opts.FloatABI.empty())
-    Res.push_back("-mfloat-abi", Opts.FloatABI);
-  if (!Opts.LimitFloatPrecision.empty())
-    Res.push_back("-mlimit-float-precision", Opts.LimitFloatPrecision);
-  if (Opts.NoZeroInitializedInBSS)
-    Res.push_back("-mno-zero-initialized-bss");
-  switch (Opts.getObjCDispatchMethod()) {
-  case CodeGenOptions::Legacy:
-    break;
-  case CodeGenOptions::Mixed:
-    Res.push_back("-fobjc-dispatch-method=mixed");
-    break;
-  case CodeGenOptions::NonLegacy:
-    Res.push_back("-fobjc-dispatch-method=non-legacy");
-    break;
-  }
-  if (Opts.BoundsChecking > 0)
-    Res.push_back("-fbounds-checking=" + llvm::utostr(Opts.BoundsChecking));
-  if (Opts.NumRegisterParameters)
-    Res.push_back("-mregparm", llvm::utostr(Opts.NumRegisterParameters));
-  if (Opts.NoGlobalMerge)
-    Res.push_back("-mno-global-merge");
-  if (Opts.NoExecStack)
-    Res.push_back("-mnoexecstack");
-  if (Opts.RelaxAll)
-    Res.push_back("-mrelax-all");
-  if (Opts.SaveTempLabels)
-    Res.push_back("-msave-temp-labels");
-  if (Opts.NoDwarf2CFIAsm)
-    Res.push_back("-fno-dwarf2-cfi-asm");
-  if (Opts.NoDwarfDirectoryAsm)
-    Res.push_back("-fno-dwarf-directory-asm");
-  if (Opts.SoftFloat)
-    Res.push_back("-msoft-float");
-  if (Opts.StrictEnums)
-    Res.push_back("-fstrict-enums");
-  if (Opts.UnwindTables)
-    Res.push_back("-munwind-tables");
-  if (Opts.RelocationModel != "pic")
-    Res.push_back("-mrelocation-model", Opts.RelocationModel);
-  if (!Opts.VerifyModule)
-    Res.push_back("-disable-llvm-verifier");
-  for (unsigned i = 0, e = Opts.BackendOptions.size(); i != e; ++i)
-    Res.push_back("-backend-option", Opts.BackendOptions[i]);
-
-  switch (Opts.getDefaultTLSModel()) {
-  case CodeGenOptions::GeneralDynamicTLSModel:
-    break;
-  case CodeGenOptions::LocalDynamicTLSModel:
-    Res.push_back("-ftls-model=local-dynamic");
-    break;
-  case CodeGenOptions::InitialExecTLSModel:
-    Res.push_back("-ftls-model=initial-exec");
-    break;
-  case CodeGenOptions::LocalExecTLSModel:
-    Res.push_back("-ftls-model=local-exec");
-    break;
-  }
-}
-
-static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts,
-                                       ToArgsList &Res) {
-  if (Opts.IncludeSystemHeaders)
-    Res.push_back("-sys-header-deps");
-  if (Opts.ShowHeaderIncludes)
-    Res.push_back("-H");
-  if (!Opts.HeaderIncludeOutputFile.empty())
-    Res.push_back("-header-include-file", Opts.HeaderIncludeOutputFile);
-  if (Opts.UsePhonyTargets)
-    Res.push_back("-MP");
-  if (!Opts.OutputFile.empty())
-    Res.push_back("-dependency-file", Opts.OutputFile);
-  for (unsigned i = 0, e = Opts.Targets.size(); i != e; ++i)
-    Res.push_back("-MT", Opts.Targets[i]);
-}
-
-static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts,
-                                 ToArgsList &Res) {
-  if (Opts.IgnoreWarnings)
-    Res.push_back("-w");
-  if (Opts.NoRewriteMacros)
-    Res.push_back("-Wno-rewrite-macros");
-  if (Opts.Pedantic)
-    Res.push_back("-pedantic");
-  if (Opts.PedanticErrors)
-    Res.push_back("-pedantic-errors");
-  if (!Opts.ShowColumn)
-    Res.push_back("-fno-show-column");
-  if (!Opts.ShowLocation)
-    Res.push_back("-fno-show-source-location");
-  if (!Opts.ShowCarets)
-    Res.push_back("-fno-caret-diagnostics");
-  if (!Opts.ShowFixits)
-    Res.push_back("-fno-diagnostics-fixit-info");
-  if (Opts.ShowSourceRanges)
-    Res.push_back("-fdiagnostics-print-source-range-info");
-  if (Opts.ShowParseableFixits)
-    Res.push_back("-fdiagnostics-parseable-fixits");
-  if (Opts.ShowColors)
-    Res.push_back("-fcolor-diagnostics");
-  if (Opts.VerifyDiagnostics)
-    Res.push_back("-verify");
-  if (Opts.ShowOptionNames)
-    Res.push_back("-fdiagnostics-show-option");
-  if (Opts.ShowCategories == 1)
-    Res.push_back("-fdiagnostics-show-category=id");
-  else if (Opts.ShowCategories == 2)
-    Res.push_back("-fdiagnostics-show-category=name");
-  switch (Opts.getFormat()) {
-  case DiagnosticOptions::Clang: 
-    Res.push_back("-fdiagnostics-format=clang"); break;
-  case DiagnosticOptions::Msvc:  
-    Res.push_back("-fdiagnostics-format=msvc");  break;
-  case DiagnosticOptions::Vi:    
-    Res.push_back("-fdiagnostics-format=vi");    break;
-  }
-  if (Opts.ErrorLimit)
-    Res.push_back("-ferror-limit", llvm::utostr(Opts.ErrorLimit));
-  if (!Opts.DiagnosticLogFile.empty())
-    Res.push_back("-diagnostic-log-file", Opts.DiagnosticLogFile);
-  if (Opts.MacroBacktraceLimit
-                        != DiagnosticOptions::DefaultMacroBacktraceLimit)
-    Res.push_back("-fmacro-backtrace-limit",
-                  llvm::utostr(Opts.MacroBacktraceLimit));
-  if (Opts.TemplateBacktraceLimit
-                        != DiagnosticOptions::DefaultTemplateBacktraceLimit)
-    Res.push_back("-ftemplate-backtrace-limit",
-                  llvm::utostr(Opts.TemplateBacktraceLimit));
-  if (Opts.ConstexprBacktraceLimit
-                        != DiagnosticOptions::DefaultConstexprBacktraceLimit)
-    Res.push_back("-fconstexpr-backtrace-limit",
-                  llvm::utostr(Opts.ConstexprBacktraceLimit));
-
-  if (Opts.TabStop != DiagnosticOptions::DefaultTabStop)
-    Res.push_back("-ftabstop", llvm::utostr(Opts.TabStop));
-  if (Opts.MessageLength)
-    Res.push_back("-fmessage-length", llvm::utostr(Opts.MessageLength));
-  if (!Opts.DumpBuildInformation.empty())
-    Res.push_back("-dump-build-information", Opts.DumpBuildInformation);
-  for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i)
-    Res.push_back("-W" + Opts.Warnings[i]);
-}
-
-static const char *getInputKindName(InputKind Kind) {
-  switch (Kind) {
-  case IK_None:              break;
-  case IK_AST:               return "ast";
-  case IK_Asm:               return "assembler-with-cpp";
-  case IK_C:                 return "c";
-  case IK_CXX:               return "c++";
-  case IK_LLVM_IR:           return "ir";
-  case IK_ObjC:              return "objective-c";
-  case IK_ObjCXX:            return "objective-c++";
-  case IK_OpenCL:            return "cl";
-  case IK_CUDA:              return "cuda";
-  case IK_PreprocessedC:     return "cpp-output";
-  case IK_PreprocessedCXX:   return "c++-cpp-output";
-  case IK_PreprocessedObjC:  return "objective-c-cpp-output";
-  case IK_PreprocessedObjCXX:return "objective-c++-cpp-output";
-  }
-
-  llvm_unreachable("Unexpected language kind!");
-}
-
-static const char *getActionName(frontend::ActionKind Kind) {
-  switch (Kind) {
-  case frontend::PluginAction:
-    llvm_unreachable("Invalid kind!");
-
-  case frontend::ASTDeclList:            return "-ast-list";
-  case frontend::ASTDump:                return "-ast-dump";
-  case frontend::ASTDumpXML:             return "-ast-dump-xml";
-  case frontend::ASTPrint:               return "-ast-print";
-  case frontend::ASTView:                return "-ast-view";
-  case frontend::DumpRawTokens:          return "-dump-raw-tokens";
-  case frontend::DumpTokens:             return "-dump-tokens";
-  case frontend::EmitAssembly:           return "-S";
-  case frontend::EmitBC:                 return "-emit-llvm-bc";
-  case frontend::EmitHTML:               return "-emit-html";
-  case frontend::EmitLLVM:               return "-emit-llvm";
-  case frontend::EmitLLVMOnly:           return "-emit-llvm-only";
-  case frontend::EmitCodeGenOnly:        return "-emit-codegen-only";
-  case frontend::EmitObj:                return "-emit-obj";
-  case frontend::FixIt:                  return "-fixit";
-  case frontend::GenerateModule:         return "-emit-module";
-  case frontend::GeneratePCH:            return "-emit-pch";
-  case frontend::GeneratePTH:            return "-emit-pth";
-  case frontend::InitOnly:               return "-init-only";
-  case frontend::ParseSyntaxOnly:        return "-fsyntax-only";
-  case frontend::PrintDeclContext:       return "-print-decl-contexts";
-  case frontend::PrintPreamble:          return "-print-preamble";
-  case frontend::PrintPreprocessedInput: return "-E";
-  case frontend::RewriteMacros:          return "-rewrite-macros";
-  case frontend::RewriteObjC:            return "-rewrite-objc";
-  case frontend::RewriteTest:            return "-rewrite-test";
-  case frontend::RunAnalysis:            return "-analyze";
-  case frontend::MigrateSource:          return "-migrate";
-  case frontend::RunPreprocessorOnly:    return "-Eonly";
-  }
-
-  llvm_unreachable("Unexpected language kind!");
-}
-
-static void FileSystemOptsToArgs(const FileSystemOptions &Opts, ToArgsList &Res){
-  if (!Opts.WorkingDir.empty())
-    Res.push_back("-working-directory", Opts.WorkingDir);
-}
-
-static void CodeCompleteOptionsToArgs(const CodeCompleteOptions &Opts,
-                                      ToArgsList &Res) {
-  if (Opts.IncludeMacros)
-    Res.push_back("-code-completion-macros");
-  if (Opts.IncludeCodePatterns)
-    Res.push_back("-code-completion-patterns");
-  if (!Opts.IncludeGlobals)
-    Res.push_back("-no-code-completion-globals");
-  if (Opts.IncludeBriefComments)
-    Res.push_back("-code-completion-brief-comments");
-}
-
-static void FrontendOptsToArgs(const FrontendOptions &Opts, ToArgsList &Res) {
-  if (Opts.DisableFree)
-    Res.push_back("-disable-free");
-  if (Opts.RelocatablePCH)
-    Res.push_back("-relocatable-pch");
-  if (Opts.ShowHelp)
-    Res.push_back("-help");
-  if (Opts.ShowStats)
-    Res.push_back("-print-stats");
-  if (Opts.ShowTimers)
-    Res.push_back("-ftime-report");
-  if (Opts.ShowVersion)
-    Res.push_back("-version");
-  if (Opts.FixWhatYouCan)
-    Res.push_back("-fix-what-you-can");
-  if (Opts.FixOnlyWarnings)
-    Res.push_back("-fix-only-warnings");
-  if (Opts.FixAndRecompile)
-    Res.push_back("-fixit-recompile");
-  if (Opts.FixToTemporaries)
-    Res.push_back("-fixit-to-temporary");
-  switch (Opts.ARCMTAction) {
-  case FrontendOptions::ARCMT_None:
-    break;
-  case FrontendOptions::ARCMT_Check:
-    Res.push_back("-arcmt-check");
-    break;
-  case FrontendOptions::ARCMT_Modify:
-    Res.push_back("-arcmt-modify");
-    break;
-  case FrontendOptions::ARCMT_Migrate:
-    Res.push_back("-arcmt-migrate");
-    break;
-  }
-  CodeCompleteOptionsToArgs(Opts.CodeCompleteOpts, Res);
-  if (!Opts.MTMigrateDir.empty())
-    Res.push_back("-mt-migrate-directory", Opts.MTMigrateDir);
-  if (!Opts.ARCMTMigrateReportOut.empty())
-    Res.push_back("-arcmt-migrate-report-output", Opts.ARCMTMigrateReportOut);
-  if (Opts.ARCMTMigrateEmitARCErrors)
-    Res.push_back("-arcmt-migrate-emit-errors");
-
-  if (Opts.ObjCMTAction & ~FrontendOptions::ObjCMT_Literals)
-    Res.push_back("-objcmt-migrate-literals");
-  if (Opts.ObjCMTAction & ~FrontendOptions::ObjCMT_Subscripting)
-    Res.push_back("-objcmt-migrate-subscripting");
-
-  bool NeedLang = false;
-  for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i)
-    if (FrontendOptions::getInputKindForExtension(Opts.Inputs[i].File) !=
-        Opts.Inputs[i].Kind)
-      NeedLang = true;
-  if (NeedLang)
-    Res.push_back("-x", getInputKindName(Opts.Inputs[0].Kind));
-  for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i) {
-    assert((!NeedLang || Opts.Inputs[i].Kind == Opts.Inputs[0].Kind) &&
-           "Unable to represent this input vector!");
-    Res.push_back(Opts.Inputs[i].File);
-  }
-
-  if (!Opts.OutputFile.empty())
-    Res.push_back("-o", Opts.OutputFile);
-  if (!Opts.CodeCompletionAt.FileName.empty())
-    Res.push_back("-code-completion-at",
-                  Opts.CodeCompletionAt.FileName + ":" +
-                  llvm::utostr(Opts.CodeCompletionAt.Line) + ":" +
-                  llvm::utostr(Opts.CodeCompletionAt.Column));
-  if (Opts.ProgramAction != frontend::PluginAction)
-    Res.push_back(getActionName(Opts.ProgramAction));
-  if (!Opts.ActionName.empty()) {
-    Res.push_back("-plugin", Opts.ActionName);
-    for(unsigned i = 0, e = Opts.PluginArgs.size(); i != e; ++i)
-      Res.push_back("-plugin-arg-" + Opts.ActionName, Opts.PluginArgs[i]);
-  }
-  if (!Opts.ASTDumpFilter.empty())
-    Res.push_back("-ast-dump-filter", Opts.ASTDumpFilter);
-  for (unsigned i = 0, e = Opts.Plugins.size(); i != e; ++i)
-    Res.push_back("-load", Opts.Plugins[i]);
-  for (unsigned i = 0, e = Opts.AddPluginActions.size(); i != e; ++i) {
-    Res.push_back("-add-plugin", Opts.AddPluginActions[i]);
-    for(unsigned ai = 0, ae = Opts.AddPluginArgs.size(); ai != ae; ++ai)
-      Res.push_back("-plugin-arg-" + Opts.AddPluginActions[i],
-                    Opts.AddPluginArgs[i][ai]);
-  }
-  for (unsigned i = 0, e = Opts.ASTMergeFiles.size(); i != e; ++i)
-    Res.push_back("-ast-merge", Opts.ASTMergeFiles[i]);
-  for (unsigned i = 0, e = Opts.LLVMArgs.size(); i != e; ++i)
-    Res.push_back("-mllvm", Opts.LLVMArgs[i]);
-  if (!Opts.OverrideRecordLayoutsFile.empty())
-    Res.push_back("-foverride-record-layout=" + Opts.OverrideRecordLayoutsFile);
-}
-
-static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
-                                   ToArgsList &Res) {
-  if (Opts.Sysroot != "/") {
-    Res.push_back("-isysroot");
-    Res.push_back(Opts.Sysroot);
-  }
-
-  /// User specified include entries.
-  for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) {
-    const HeaderSearchOptions::Entry &E = Opts.UserEntries[i];
-    if (E.IsFramework && (E.Group != frontend::Angled || !E.IsUserSupplied))
-      llvm::report_fatal_error("Invalid option set!");
-    if (E.IsUserSupplied) {
-      switch (E.Group) {
-      case frontend::After:
-        Res.push_back("-idirafter");
-        break;
-        
-      case frontend::Quoted:
-        Res.push_back("-iquote");
-        break;
-        
-      case frontend::System:
-        Res.push_back("-isystem");
-        break;
-        
-      case frontend::IndexHeaderMap:
-        Res.push_back("-index-header-map");
-        Res.push_back(E.IsFramework? "-F" : "-I");
-        break;
-        
-      case frontend::CSystem:
-        Res.push_back("-c-isystem");
-        break;
-
-      case frontend::CXXSystem:
-        Res.push_back("-cxx-isystem");
-        break;
-
-      case frontend::ObjCSystem:
-        Res.push_back("-objc-isystem");
-        break;
-
-      case frontend::ObjCXXSystem:
-        Res.push_back("-objcxx-isystem");
-        break;
-        
-      case frontend::Angled:
-        Res.push_back(E.IsFramework ? "-F" : "-I");
-        break;
-      }
-    } else {
-      if (E.IsInternal) {
-        assert(E.Group == frontend::System && "Unexpected header search group");
-        if (E.ImplicitExternC)
-          Res.push_back("-internal-externc-isystem");
-        else
-          Res.push_back("-internal-isystem");
-      } else {
-        if (E.Group != frontend::Angled && E.Group != frontend::System)
-          llvm::report_fatal_error("Invalid option set!");
-        Res.push_back(E.Group == frontend::Angled ? "-iwithprefixbefore" :
-                      "-iwithprefix");
-      }
-    }
-    Res.push_back(E.Path);
-  }
-
-  /// User-specified system header prefixes.
-  for (unsigned i = 0, e = Opts.SystemHeaderPrefixes.size(); i != e; ++i) {
-    if (Opts.SystemHeaderPrefixes[i].IsSystemHeader)
-      Res.push_back("-isystem-prefix");
-    else
-      Res.push_back("-ino-system-prefix");
-
-    Res.push_back(Opts.SystemHeaderPrefixes[i].Prefix);
-  }
-
-  if (!Opts.ResourceDir.empty())
-    Res.push_back("-resource-dir", Opts.ResourceDir);
-  if (!Opts.ModuleCachePath.empty())
-    Res.push_back("-fmodule-cache-path", Opts.ModuleCachePath);
-  if (!Opts.UseStandardSystemIncludes)
-    Res.push_back("-nostdsysteminc");
-  if (!Opts.UseStandardCXXIncludes)
-    Res.push_back("-nostdinc++");
-  if (Opts.UseLibcxx)
-    Res.push_back("-stdlib=libc++");
-  if (Opts.Verbose)
-    Res.push_back("-v");
-}
-
-static void LangOptsToArgs(const LangOptions &Opts, ToArgsList &Res) {
-  LangOptions DefaultLangOpts;
-
-  // FIXME: Need to set -std to get all the implicit options.
-
-  // FIXME: We want to only pass options relative to the defaults, which
-  // requires constructing a target. :(
-  //
-  // It would be better to push the all target specific choices into the driver,
-  // so that everything below that was more uniform.
-
-  if (Opts.Trigraphs)
-    Res.push_back("-trigraphs");
-  // Implicit based on the input kind:
-  //   AsmPreprocessor, CPlusPlus, ObjC1, ObjC2, OpenCL
-  // Implicit based on the input language standard:
-  //   BCPLComment, C99, CPlusPlus0x, Digraphs, GNUInline, ImplicitInt, GNUMode
-  if (Opts.DollarIdents)
-    Res.push_back("-fdollars-in-identifiers");
-  if (Opts.GNUMode && !Opts.GNUKeywords)
-    Res.push_back("-fno-gnu-keywords");
-  if (!Opts.GNUMode && Opts.GNUKeywords)
-    Res.push_back("-fgnu-keywords");
-  if (Opts.MicrosoftExt)
-    Res.push_back("-fms-extensions");
-  if (Opts.MicrosoftMode)
-    Res.push_back("-fms-compatibility");
-  if (Opts.MSCVersion != 0)
-    Res.push_back("-fmsc-version=" + llvm::utostr(Opts.MSCVersion));
-  if (Opts.Borland)
-    Res.push_back("-fborland-extensions");
-  if (Opts.ObjCDefaultSynthProperties)
-    Res.push_back("-fobjc-default-synthesize-properties");
-  // NoInline is implicit.
-  if (!Opts.CXXOperatorNames)
-    Res.push_back("-fno-operator-names");
-  if (Opts.PascalStrings)
-    Res.push_back("-fpascal-strings");
-  if (Opts.CatchUndefined)
-    Res.push_back("-fcatch-undefined-behavior");
-  if (Opts.AddressSanitizer)
-    Res.push_back("-faddress-sanitizer");
-  if (Opts.ThreadSanitizer)
-    Res.push_back("-fthread-sanitizer");
-  if (Opts.WritableStrings)
-    Res.push_back("-fwritable-strings");
-  if (Opts.ConstStrings)
-    Res.push_back("-fconst-strings");
-  if (!Opts.LaxVectorConversions)
-    Res.push_back("-fno-lax-vector-conversions");
-  if (Opts.AltiVec)
-    Res.push_back("-faltivec");
-  if (Opts.Exceptions)
-    Res.push_back("-fexceptions");
-  if (Opts.ObjCExceptions)
-    Res.push_back("-fobjc-exceptions");
-  if (Opts.CXXExceptions)
-    Res.push_back("-fcxx-exceptions");
-  if (Opts.SjLjExceptions)
-    Res.push_back("-fsjlj-exceptions");
-  if (Opts.TraditionalCPP)
-    Res.push_back("-traditional-cpp");
-  if (!Opts.RTTI)
-    Res.push_back("-fno-rtti");
-  if (Opts.MSBitfields)
-    Res.push_back("-mms-bitfields");
-  if (Opts.Freestanding)
-    Res.push_back("-ffreestanding");
-  if (Opts.NoBuiltin)
-    Res.push_back("-fno-builtin");
-  if (!Opts.AssumeSaneOperatorNew)
-    Res.push_back("-fno-assume-sane-operator-new");
-  if (!Opts.ThreadsafeStatics)
-    Res.push_back("-fno-threadsafe-statics");
-  if (Opts.POSIXThreads)
-    Res.push_back("-pthread");
-  if (Opts.Blocks)
-    Res.push_back("-fblocks");
-  if (Opts.BlocksRuntimeOptional)
-    Res.push_back("-fblocks-runtime-optional");
-  if (Opts.Modules)
-    Res.push_back("-fmodules");
-  if (Opts.EmitAllDecls)
-    Res.push_back("-femit-all-decls");
-  if (Opts.MathErrno)
-    Res.push_back("-fmath-errno");
-  switch (Opts.getSignedOverflowBehavior()) {
-  case LangOptions::SOB_Undefined: break;
-  case LangOptions::SOB_Defined:   Res.push_back("-fwrapv"); break;
-  case LangOptions::SOB_Trapping:
-    Res.push_back("-ftrapv");
-    if (!Opts.OverflowHandler.empty())
-      Res.push_back("-ftrapv-handler", Opts.OverflowHandler);
-    break;
-  }
-  switch (Opts.getFPContractMode()) {
-  case LangOptions::FPC_Off:  Res.push_back("-ffp-contract=off"); break;
-  case LangOptions::FPC_On:   Res.push_back("-ffp-contract=on"); break;
-  case LangOptions::FPC_Fast: Res.push_back("-ffp-contract=fast"); break;
-  }
-  if (Opts.HeinousExtensions)
-    Res.push_back("-fheinous-gnu-extensions");
-  // Optimize is implicit.
-  // OptimizeSize is implicit.
-  if (Opts.FastMath)
-    Res.push_back("-ffast-math");
-  if (Opts.Static)
-    Res.push_back("-static-define");
-  if (Opts.DumpRecordLayoutsSimple)
-    Res.push_back("-fdump-record-layouts-simple");
-  else if (Opts.DumpRecordLayouts)
-    Res.push_back("-fdump-record-layouts");
-  if (Opts.DumpVTableLayouts)
-    Res.push_back("-fdump-vtable-layouts");
-  if (Opts.NoBitFieldTypeAlign)
-    Res.push_back("-fno-bitfield-type-alignment");
-  if (Opts.PICLevel)
-    Res.push_back("-pic-level", llvm::utostr(Opts.PICLevel));
-  if (Opts.PIELevel)
-    Res.push_back("-pie-level", llvm::utostr(Opts.PIELevel));
-  if (Opts.ObjCGCBitmapPrint)
-    Res.push_back("-print-ivar-layout");
-  if (Opts.NoConstantCFStrings)
-    Res.push_back("-fno-constant-cfstrings");
-  if (!Opts.AccessControl)
-    Res.push_back("-fno-access-control");
-  if (!Opts.CharIsSigned)
-    Res.push_back("-fno-signed-char");
-  if (Opts.CPlusPlus && !Opts.WChar)
-    Res.push_back("-fno-wchar");
-  if (Opts.ShortWChar)
-    Res.push_back("-fshort-wchar");
-  if (!Opts.ElideConstructors)
-    Res.push_back("-fno-elide-constructors");
-  if (Opts.getGC() != LangOptions::NonGC) {
-    if (Opts.getGC() == LangOptions::HybridGC) {
-      Res.push_back("-fobjc-gc");
-    } else {
-      assert(Opts.getGC() == LangOptions::GCOnly && "Invalid GC mode!");
-      Res.push_back("-fobjc-gc-only");
-    }
-  }
-  Res.push_back("-fobjc-runtime=" + Opts.ObjCRuntime.getAsString());
-  if (Opts.ObjCAutoRefCount)
-    Res.push_back("-fobjc-arc");
-  if (Opts.ObjCARCWeak)
-    Res.push_back("-fobjc-runtime-has-weak");
-  if (!Opts.ObjCInferRelatedResultType)
-    Res.push_back("-fno-objc-infer-related-result-type");
-  
-  if (Opts.AppleKext)
-    Res.push_back("-fapple-kext");
-
-  if (Opts.getVisibilityMode() != DefaultVisibility) {
-    Res.push_back("-fvisibility");
-    if (Opts.getVisibilityMode() == HiddenVisibility) {
-      Res.push_back("hidden");
-    } else {
-      assert(Opts.getVisibilityMode() == ProtectedVisibility &&
-             "Invalid visibility!");
-      Res.push_back("protected");
-    }
-  }
-  if (Opts.InlineVisibilityHidden)
-    Res.push_back("-fvisibility-inlines-hidden");
-
-  if (Opts.getStackProtector() != 0)
-    Res.push_back("-stack-protector", llvm::utostr(Opts.getStackProtector()));
-  if (Opts.InstantiationDepth != DefaultLangOpts.InstantiationDepth)
-    Res.push_back("-ftemplate-depth", llvm::utostr(Opts.InstantiationDepth));
-  if (Opts.ConstexprCallDepth != DefaultLangOpts.ConstexprCallDepth)
-    Res.push_back("-fconstexpr-depth", llvm::utostr(Opts.ConstexprCallDepth));
-  if (!Opts.ObjCConstantStringClass.empty())
-    Res.push_back("-fconstant-string-class", Opts.ObjCConstantStringClass);
-  if (Opts.FakeAddressSpaceMap)
-    Res.push_back("-ffake-address-space-map");
-  if (Opts.ParseUnknownAnytype)
-    Res.push_back("-funknown-anytype");
-  if (Opts.DebuggerSupport)
-    Res.push_back("-fdebugger-support");
-  if (Opts.DebuggerCastResultToId)
-    Res.push_back("-fdebugger-cast-result-to-id");
-  if (Opts.DebuggerObjCLiteral)
-    Res.push_back("-fdebugger-objc-literal");
-  if (Opts.DelayedTemplateParsing)
-    Res.push_back("-fdelayed-template-parsing");
-  if (Opts.Deprecated)
-    Res.push_back("-fdeprecated-macro");
-  if (Opts.ApplePragmaPack)
-    Res.push_back("-fapple-pragma-pack");
-  if (!Opts.CurrentModule.empty())
-    Res.push_back("-fmodule-name=" + Opts.CurrentModule);
-}
-
-static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts,
-                                   ToArgsList &Res) {
-  for (unsigned i = 0, e = Opts.Macros.size(); i != e; ++i)
-    Res.push_back(std::string(Opts.Macros[i].second ? "-U" : "-D") +
-                  Opts.Macros[i].first);
-  for (unsigned i = 0, e = Opts.Includes.size(); i != e; ++i) {
-    // FIXME: We need to avoid reincluding the implicit PCH and PTH includes.
-    Res.push_back("-include", Opts.Includes[i]);
-  }
-  for (unsigned i = 0, e = Opts.MacroIncludes.size(); i != e; ++i)
-    Res.push_back("-imacros", Opts.MacroIncludes[i]);
-  if (!Opts.UsePredefines)
-    Res.push_back("-undef");
-  if (Opts.DetailedRecord)
-    Res.push_back("-detailed-preprocessing-record");
-  if (!Opts.ImplicitPCHInclude.empty())
-    Res.push_back("-include-pch", Opts.ImplicitPCHInclude);
-  if (!Opts.ImplicitPTHInclude.empty())
-    Res.push_back("-include-pth", Opts.ImplicitPTHInclude);
-  if (!Opts.TokenCache.empty()) {
-    if (Opts.ImplicitPTHInclude.empty())
-      Res.push_back("-token-cache", Opts.TokenCache);
-    else
-      assert(Opts.ImplicitPTHInclude == Opts.TokenCache &&
-             "Unsupported option combination!");
-  }
-  for (unsigned i = 0, e = Opts.ChainedIncludes.size(); i != e; ++i)
-    Res.push_back("-chain-include", Opts.ChainedIncludes[i]);
-  for (unsigned i = 0, e = Opts.RemappedFiles.size(); i != e; ++i) {
-    Res.push_back("-remap-file", Opts.RemappedFiles[i].first + ";" +
-                                 Opts.RemappedFiles[i].second);
-  }
-}
-
-static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts,
-                                         ToArgsList &Res) {
-  if (!Opts.ShowCPP && !Opts.ShowMacros)
-    llvm::report_fatal_error("Invalid option combination!");
-
-  if (Opts.ShowCPP && Opts.ShowMacros)
-    Res.push_back("-dD");
-  else if (!Opts.ShowCPP && Opts.ShowMacros)
-    Res.push_back("-dM");
-
-  if (!Opts.ShowLineMarkers)
-    Res.push_back("-P");
-  if (Opts.ShowComments)
-    Res.push_back("-C");
-  if (Opts.ShowMacroComments)
-    Res.push_back("-CC");
-}
-
-static void TargetOptsToArgs(const TargetOptions &Opts,
-                             ToArgsList &Res) {
-  Res.push_back("-triple");
-  Res.push_back(Opts.Triple);
-  if (!Opts.CPU.empty())
-    Res.push_back("-target-cpu", Opts.CPU);
-  if (!Opts.ABI.empty())
-    Res.push_back("-target-abi", Opts.ABI);
-  if (!Opts.LinkerVersion.empty())
-    Res.push_back("-target-linker-version", Opts.LinkerVersion);
-  if (!Opts.CXXABI.empty())
-    Res.push_back("-cxx-abi", Opts.CXXABI);
-  for (unsigned i = 0, e = Opts.FeaturesAsWritten.size(); i != e; ++i)
-    Res.push_back("-target-feature", Opts.FeaturesAsWritten[i]);
-}
-
-void CompilerInvocation::toArgs(std::vector<std::string> &Res) const {
-  ToArgsList List(Res);
-  AnalyzerOptsToArgs(*getAnalyzerOpts(), List);
-  CodeGenOptsToArgs(getCodeGenOpts(), List);
-  DependencyOutputOptsToArgs(getDependencyOutputOpts(), List);
-  DiagnosticOptsToArgs(getDiagnosticOpts(), List);
-  FileSystemOptsToArgs(getFileSystemOpts(), List);
-  FrontendOptsToArgs(getFrontendOpts(), List);
-  HeaderSearchOptsToArgs(getHeaderSearchOpts(), List);
-  LangOptsToArgs(*getLangOpts(), List);
-  PreprocessorOptsToArgs(getPreprocessorOpts(), List);
-  PreprocessorOutputOptsToArgs(getPreprocessorOutputOpts(), List);
-  TargetOptsToArgs(getTargetOpts(), List);
-}
-
-//===----------------------------------------------------------------------===//
-// Deserialization (to args)
+// Deserialization (from args)
 //===----------------------------------------------------------------------===//
 
 using namespace clang::driver;
