r332885 - CodeGen, Driver: Start using direct split dwarf emission in clang.

Peter Collingbourne via cfe-commits cfe-commits at lists.llvm.org
Tue May 22 11:57:11 PDT 2018


Sorry about that, I was keeping an eye on the bots but I must have missed
that one. I've relanded with a fix in r333013.

Peter

On Tue, May 22, 2018 at 4:25 AM, Amara Emerson <aemerson at apple.com> wrote:

> On 21 May 2018, at 21:31, Peter Collingbourne via cfe-commits <
> cfe-commits at lists.llvm.org> wrote:
>
> Author: pcc
> Date: Mon May 21 13:31:59 2018
> New Revision: 332885
>
> URL: http://llvm.org/viewvc/llvm-project?rev=332885&view=rev
> Log:
> CodeGen, Driver: Start using direct split dwarf emission in clang.
>
> Fixes PR37466.
>
> Differential Revision: https://reviews.llvm.org/D47093
>
> Added:
>    cfe/trunk/test/Misc/cc1as-split-dwarf.s
> Modified:
>    cfe/trunk/include/clang/Driver/CC1Options.td
>    cfe/trunk/lib/CodeGen/BackendUtil.cpp
>    cfe/trunk/lib/Driver/ToolChains/Clang.cpp
>    cfe/trunk/test/CodeGen/split-debug-filename.c
>    cfe/trunk/test/Driver/split-debug.c
>    cfe/trunk/test/Driver/split-debug.s
>    cfe/trunk/tools/driver/cc1as_main.cpp
>
> Modified: cfe/trunk/include/clang/Driver/CC1Options.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Driver/CC1Options.td?rev=332885&r1=332884&r2=332885&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Driver/CC1Options.td (original)
> +++ cfe/trunk/include/clang/Driver/CC1Options.td Mon May 21 13:31:59 2018
> @@ -619,6 +619,8 @@ def version : Flag<["-"], "version">,
>   HelpText<"Print the compiler version">;
> def main_file_name : Separate<["-"], "main-file-name">,
>   HelpText<"Main file name to use for debug info">;
> +def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
> +  HelpText<"File name to use for split dwarf debug info output">;
>
> }
>
> @@ -628,8 +630,6 @@ def fexternc_nounwind : Flag<["-"], "fex
>   HelpText<"Assume all functions with C linkage do not unwind">;
> def enable_split_dwarf : Flag<["-"], "enable-split-dwarf">,
>   HelpText<"Use split dwarf/Fission">;
> -def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
> -  HelpText<"File name to use for split dwarf debug info output">;
> def fno_wchar : Flag<["-"], "fno-wchar">,
>   HelpText<"Disable C++ builtin type wchar_t">;
> def fconstant_string_class : Separate<["-"], "fconstant-string-class">,
>
> Modified: cfe/trunk/lib/CodeGen/BackendUtil.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
> BackendUtil.cpp?rev=332885&r1=332884&r2=332885&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/CodeGen/BackendUtil.cpp (original)
> +++ cfe/trunk/lib/CodeGen/BackendUtil.cpp Mon May 21 13:31:59 2018
> @@ -104,7 +104,17 @@ class EmitAssemblyHelper {
>   ///
>   /// \return True on success.
>   bool AddEmitPasses(legacy::PassManager &CodeGenPasses, BackendAction
> Action,
> -                     raw_pwrite_stream &OS);
> +                     raw_pwrite_stream &OS, raw_pwrite_stream *DwoOS);
> +
> +  std::unique_ptr<llvm::ToolOutputFile> openOutputFile(StringRef Path) {
> +    std::error_code EC;
> +    auto F = make_unique<llvm::ToolOutputFile>(Path, EC,
> llvm::sys::fs::F_None);
> +    if (EC) {
> +      Diags.Report(diag::err_fe_unable_to_open_output) << Path <<
> EC.message();
> +      F.reset();
> +    }
> +    return F;
> +  }
>
> public:
>   EmitAssemblyHelper(DiagnosticsEngine &_Diags,
> @@ -701,7 +711,8 @@ void EmitAssemblyHelper::CreateTargetMac
>
> bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses,
>                                        BackendAction Action,
> -                                       raw_pwrite_stream &OS) {
> +                                       raw_pwrite_stream &OS,
> +                                       raw_pwrite_stream *DwoOS) {
>   // Add LibraryInfo.
>   llvm::Triple TargetTriple(TheModule->getTargetTriple());
>   std::unique_ptr<TargetLibraryInfoImpl> TLII(
> @@ -718,7 +729,7 @@ bool EmitAssemblyHelper::AddEmitPasses(l
>   if (CodeGenOpts.OptimizationLevel > 0)
>     CodeGenPasses.add(createObjCARCContractPass());
>
> -  if (TM->addPassesToEmitFile(CodeGenPasses, OS, nullptr, CGFT,
> +  if (TM->addPassesToEmitFile(CodeGenPasses, OS, DwoOS, CGFT,
>                               /*DisableVerify=*/!CodeGenOpts.VerifyModule))
> {
>     Diags.Report(diag::err_fe_unable_to_interface_with_target);
>     return false;
> @@ -757,7 +768,7 @@ void EmitAssemblyHelper::EmitAssembly(Ba
>   CodeGenPasses.add(
>       createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
>
> -  std::unique_ptr<raw_fd_ostream> ThinLinkOS;
> +  std::unique_ptr<llvm::ToolOutputFile> ThinLinkOS, DwoOS;
>
>   switch (Action) {
>   case Backend_EmitNothing:
> @@ -766,18 +777,12 @@ void EmitAssemblyHelper::EmitAssembly(Ba
>   case Backend_EmitBC:
>     if (CodeGenOpts.EmitSummaryIndex) {
>       if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) {
> -        std::error_code EC;
> -        ThinLinkOS.reset(new llvm::raw_fd_ostream(
> -            CodeGenOpts.ThinLinkBitcodeFile, EC,
> -            llvm::sys::fs::F_None));
> -        if (EC) {
> -          Diags.Report(diag::err_fe_unable_to_open_output) <<
> CodeGenOpts.ThinLinkBitcodeFile
> -                                                           <<
> EC.message();
> +        ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile);
> +        if (!ThinLinkOS)
>           return;
> -        }
>       }
> -      PerModulePasses.add(
> -          createWriteThinLTOBitcodePass(*OS, ThinLinkOS.get()));
> +      PerModulePasses.add(createWriteThinLTOBitcodePass(
> +          *OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr));
>     }
>     else
>       PerModulePasses.add(
> @@ -790,7 +795,13 @@ void EmitAssemblyHelper::EmitAssembly(Ba
>     break;
>
>   default:
> -    if (!AddEmitPasses(CodeGenPasses, Action, *OS))
> +    if (!CodeGenOpts.SplitDwarfFile.empty()) {
> +      DwoOS = openOutputFile(CodeGenOpts.SplitDwarfFile);
> +      if (!DwoOS)
> +        return;
> +    }
> +    if (!AddEmitPasses(CodeGenPasses, Action, *OS,
> +                       DwoOS ? &DwoOS->os() : nullptr))
>       return;
>   }
>
> @@ -819,6 +830,11 @@ void EmitAssemblyHelper::EmitAssembly(Ba
>     PrettyStackTraceString CrashInfo("Code generation");
>     CodeGenPasses.run(*TheModule);
>   }
> +
> +  if (ThinLinkOS)
> +    ThinLinkOS->keep();
> +  if (DwoOS)
> +    DwoOS->keep();
> }
>
> static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions
> &Opts) {
> @@ -971,7 +987,7 @@ void EmitAssemblyHelper::EmitAssemblyWit
>   // create that pass manager here and use it as needed below.
>   legacy::PassManager CodeGenPasses;
>   bool NeedCodeGen = false;
> -  Optional<raw_fd_ostream> ThinLinkOS;
> +  std::unique_ptr<llvm::ToolOutputFile> ThinLinkOS, DwoOS;
>
>   // Append any output we need to the pass manager.
>   switch (Action) {
> @@ -981,17 +997,12 @@ void EmitAssemblyHelper::EmitAssemblyWit
>   case Backend_EmitBC:
>     if (CodeGenOpts.EmitSummaryIndex) {
>       if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) {
> -        std::error_code EC;
> -        ThinLinkOS.emplace(CodeGenOpts.ThinLinkBitcodeFile, EC,
> -                           llvm::sys::fs::F_None);
> -        if (EC) {
> -          Diags.Report(diag::err_fe_unable_to_open_output)
> -              << CodeGenOpts.ThinLinkBitcodeFile << EC.message();
> +        ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile);
> +        if (!ThinLinkOS)
>           return;
> -        }
>       }
> -      MPM.addPass(
> -          ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &*ThinLinkOS :
> nullptr));
> +      MPM.addPass(ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ?
> &ThinLinkOS->os()
> +                                                           : nullptr));
>     } else {
>       MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,
>                                     CodeGenOpts.EmitSummaryIndex,
> @@ -1009,7 +1020,13 @@ void EmitAssemblyHelper::EmitAssemblyWit
>     NeedCodeGen = true;
>     CodeGenPasses.add(
>         createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
> -    if (!AddEmitPasses(CodeGenPasses, Action, *OS))
> +    if (!CodeGenOpts.SplitDwarfFile.empty()) {
> +      DwoOS = openOutputFile(CodeGenOpts.SplitDwarfFile);
> +      if (!DwoOS)
> +        return;
> +    }
> +    if (!AddEmitPasses(CodeGenPasses, Action, *OS,
> +                       DwoOS ? &DwoOS->os() : nullptr))
>       // FIXME: Should we handle this error differently?
>       return;
>     break;
> @@ -1029,6 +1046,11 @@ void EmitAssemblyHelper::EmitAssemblyWit
>     PrettyStackTraceString CrashInfo("Code generation");
>     CodeGenPasses.run(*TheModule);
>   }
> +
> +  if (ThinLinkOS)
> +    ThinLinkOS->keep();
> +  if (DwoOS)
> +    DwoOS->keep();
> }
>
> Expected<BitcodeModule> clang::FindThinLTOModule(MemoryBufferRef MBRef) {
>
> Modified: cfe/trunk/lib/Driver/ToolChains/Clang.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/
> ToolChains/Clang.cpp?rev=332885&r1=332884&r2=332885&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Driver/ToolChains/Clang.cpp (original)
> +++ cfe/trunk/lib/Driver/ToolChains/Clang.cpp Mon May 21 13:31:59 2018
> @@ -4802,12 +4802,6 @@ void Clang::ConstructJob(Compilation &C,
>     C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs,
> Inputs));
>   }
>
> -  // Handle the debug info splitting at object creation time if we're
> -  // creating an object.
> -  // TODO: Currently only works on linux with newer objcopy.
> -  if (SplitDWARF && Output.getType() == types::TY_Object)
> -    SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
> SplitDWARFOut);
> -
>   if (Arg *A = Args.getLastArg(options::OPT_pg))
>     if (Args.hasArg(options::OPT_fomit_frame_pointer))
>       D.Diag(diag::err_drv_argument_not_allowed_with) <<
> "-fomit-frame-pointer"
> @@ -5464,19 +5458,17 @@ void ClangAs::ConstructJob(Compilation &
>   CmdArgs.push_back("-o");
>   CmdArgs.push_back(Output.getFilename());
>
> +  if (Args.hasArg(options::OPT_gsplit_dwarf) &&
> +      getToolChain().getTriple().isOSLinux()) {
> +    CmdArgs.push_back("-split-dwarf-file");
> +    CmdArgs.push_back(SplitDebugName(Args, Input));
> +  }
> +
>   assert(Input.isFilename() && "Invalid input.");
>   CmdArgs.push_back(Input.getFilename());
>
>   const char *Exec = getToolChain().getDriver().getClangProgramPath();
>   C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs,
> Inputs));
> -
> -  // Handle the debug info splitting at object creation time if we're
> -  // creating an object.
> -  // TODO: Currently only works on linux with newer objcopy.
> -  if (Args.hasArg(options::OPT_gsplit_dwarf) &&
> -      getToolChain().getTriple().isOSLinux())
> -    SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
> -                   SplitDebugName(Args, Input));
> }
>
> // Begin OffloadBundler
>
> Modified: cfe/trunk/test/CodeGen/split-debug-filename.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> CodeGen/split-debug-filename.c?rev=332885&r1=332884&r2=332885&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/CodeGen/split-debug-filename.c (original)
> +++ cfe/trunk/test/CodeGen/split-debug-filename.c Mon May 21 13:31:59 2018
> @@ -1,5 +1,8 @@
> // RUN: %clang_cc1 -debug-info-kind=limited -split-dwarf-file foo.dwo -S
> -emit-llvm -o - %s | FileCheck %s
> // RUN: %clang_cc1 -debug-info-kind=limited -enable-split-dwarf
> -split-dwarf-file foo.dwo -S -emit-llvm -o - %s | FileCheck
> --check-prefix=VANILLA %s
> +// RUN: %clang_cc1 -debug-info-kind=limited -enable-split-dwarf
> -split-dwarf-file %t.dwo -emit-obj -o - %s | llvm-objdump -section-headers
> - | FileCheck --check-prefix=O %s
> +// RUN: llvm-objdump -section-headers %t.dwo | FileCheck
> --check-prefix=DWO %s
> +
> int main (void) {
>   return 0;
> }
> @@ -10,3 +13,6 @@ int main (void) {
> // Testing to ensure that the dwo name is not output into the compile unit
> if
> // it's for vanilla split-dwarf rather than split-dwarf for implicit
> modules.
> // VANILLA-NOT: splitDebugFilename
> +
> +// O-NOT: .dwo
> +// DWO: .dwo
>
> Modified: cfe/trunk/test/Driver/split-debug.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/
> split-debug.c?rev=332885&r1=332884&r2=332885&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/Driver/split-debug.c (original)
> +++ cfe/trunk/test/Driver/split-debug.c Mon May 21 13:31:59 2018
> @@ -3,8 +3,7 @@
> // RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -c -### %s
> 2> %t
> // RUN: FileCheck -check-prefix=CHECK-ACTIONS < %t %s
> //
> -// CHECK-ACTIONS: objcopy{{.*}}--extract-dwo{{.*}}"split-debug.dwo"
> -// CHECK-ACTIONS: objcopy{{.*}}--strip-dwo{{.*}}"split-debug.o"
> +// CHECK-ACTIONS: "-split-dwarf-file" "split-debug.dwo"
>
>
> // RUN: %clang -target x86_64-macosx -gsplit-dwarf -c -### %s 2> %t
>
> Modified: cfe/trunk/test/Driver/split-debug.s
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/
> split-debug.s?rev=332885&r1=332884&r2=332885&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/Driver/split-debug.s (original)
> +++ cfe/trunk/test/Driver/split-debug.s Mon May 21 13:31:59 2018
> @@ -3,8 +3,7 @@
> // RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -c -### %s
> 2> %t
> // RUN: FileCheck -check-prefix=CHECK-ACTIONS < %t %s
> //
> -// CHECK-ACTIONS: objcopy{{.*}}--extract-dwo{{.*}}"split-debug.dwo"
> -// CHECK-ACTIONS: objcopy{{.*}}--strip-dwo{{.*}}"split-debug.o"
> +// CHECK-ACTIONS: "-split-dwarf-file" "split-debug.dwo"
>
>
> // RUN: %clang -target x86_64-macosx -gsplit-dwarf -c -### %s 2> %t
>
> Added: cfe/trunk/test/Misc/cc1as-split-dwarf.s
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/
> cc1as-split-dwarf.s?rev=332885&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/Misc/cc1as-split-dwarf.s (added)
> +++ cfe/trunk/test/Misc/cc1as-split-dwarf.s Mon May 21 13:31:59 2018
> @@ -0,0 +1,25 @@
> +// RUN: %clang -cc1as -triple x86_64-pc-linux-gnu %s -filetype obj -o %t1
> -split-dwarf-file %t2
> +// RUN: llvm-objdump -s %t1 | FileCheck --check-prefix=O %s
> +// RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=DWO %s
> +
> +// O-NOT: Contents of section
> +// O: Contents of section .strtab:
> +// O-NOT: Contents of section
> +// O: Contents of section .text:
> +// O-NEXT: 0000 c3
> +// O-NEXT: Contents of section .symtab:
> +// O-NOT: Contents of section
> +.globl main
> +main:
> +.Ltmp1:
> +ret
> +.Ltmp2:
> +
> +// DWO-NOT: Contents of section
> +// DWO: Contents of section .strtab:
> +// DWO-NOT: Contents of section
> +// DWO: Contents of section .foo.dwo:
> +// DWO-NEXT: 0000 01000000
> +// DWO-NOT: Contents of section
> +.section .foo.dwo
> +.long .Ltmp2-.Ltmp1
>
> Modified: cfe/trunk/tools/driver/cc1as_main.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/
> driver/cc1as_main.cpp?rev=332885&r1=332884&r2=332885&view=diff
> ============================================================
> ==================
> --- cfe/trunk/tools/driver/cc1as_main.cpp (original)
> +++ cfe/trunk/tools/driver/cc1as_main.cpp Mon May 21 13:31:59 2018
> @@ -97,6 +97,7 @@ struct AssemblerInvocation {
>   llvm::DebugCompressionType CompressDebugSections =
>       llvm::DebugCompressionType::None;
>   std::string MainFileName;
> +  std::string SplitDwarfFile;
>
>   /// @}
>   /// @name Frontend Options
> @@ -247,6 +248,7 @@ bool AssemblerInvocation::CreateFromArgs
>   }
>   Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
>   Opts.OutputPath = Args.getLastArgValue(OPT_o);
> +  Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
>   if (Arg *A = Args.getLastArg(OPT_filetype)) {
>     StringRef Name = A->getValue();
>     unsigned OutputType = StringSwitch<unsigned>(Name)
> @@ -282,22 +284,17 @@ bool AssemblerInvocation::CreateFromArgs
> }
>
> static std::unique_ptr<raw_fd_ostream>
> -getOutputStream(AssemblerInvocation &Opts, DiagnosticsEngine &Diags,
> -                bool Binary) {
> -  if (Opts.OutputPath.empty())
> -    Opts.OutputPath = "-";
> -
> +getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
>   // Make sure that the Out file gets unlinked from the disk if we get a
>   // SIGINT.
> -  if (Opts.OutputPath != "-")
> -    sys::RemoveFileOnSignal(Opts.OutputPath);
> +  if (Path != "-")
> +    sys::RemoveFileOnSignal(Path);
>
>   std::error_code EC;
>   auto Out = llvm::make_unique<raw_fd_ostream>(
> -      Opts.OutputPath, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
> +      Path, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
>   if (EC) {
> -    Diags.Report(diag::err_fe_unable_to_open_output) << Opts.OutputPath
> -                                                     << EC.message();
> +    Diags.Report(diag::err_fe_unable_to_open_output) << Path <<
> EC.message();
>     return nullptr;
>   }
>
> @@ -342,9 +339,15 @@ static bool ExecuteAssembler(AssemblerIn
>   MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations);
>
>   bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
> -  std::unique_ptr<raw_fd_ostream> FDOS = getOutputStream(Opts, Diags,
> IsBinary);
> +  if (Opts.OutputPath.empty())
> +    Opts.OutputPath = "-";
> +  std::unique_ptr<raw_fd_ostream> FDOS =
> +      getOutputStream(Opts.OutputPath, Diags, IsBinary);
>   if (!FDOS)
>     return true;
> +  std::unique_ptr<raw_fd_ostream> DwoOS;
> +  if (!Opts.SplitDwarfFile.empty())
> +    DwoOS = getOutputStream(Opts.SplitDwarfFile, Diags, IsBinary);
>
>   // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
>   // MCObjectFileInfo needs a MCContext reference in order to initialize
> itself.
> @@ -427,7 +430,9 @@ static bool ExecuteAssembler(AssemblerIn
>     MCTargetOptions MCOptions;
>     std::unique_ptr<MCAsmBackend> MAB(
>         TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
> -    std::unique_ptr<MCObjectWriter> OW = MAB->createObjectWriter(*Out);
> +    std::unique_ptr<MCObjectWriter> OW =
> +        DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS)
> +              : MAB->createObjectWriter(*Out);
>
>     Triple T(Opts.Triple);
>     Str.reset(TheTarget->createMCObjectStreamer(
> @@ -476,8 +481,12 @@ static bool ExecuteAssembler(AssemblerIn
>   FDOS.reset();
>
>   // Delete output file if there were errors.
> -  if (Failed && Opts.OutputPath != "-")
> -    sys::fs::remove(Opts.OutputPath);
> +  if (Failed) {
> +    if (Opts.OutputPath != "-")
> +      sys::fs::remove(Opts.OutputPath);
> +    if (!Opts.SplitDwarfFile.empty() && Opts.SplitDwarfFile != "-")
> +      sys::fs::remove(Opts.SplitDwarfFile);
> +  }
>
>   return Failed;
> }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
>
> Hi Peter,
>
> Sorry but I had to revert this and the two follow on commits in r332971,
> r332972, r332973 as it broke several green dragon buildbots. For example:
> http://green.lab.llvm.org/green/job/clang-stage1-configure-RA/45399/
>
> Cheers,
> Amara
>



-- 
-- 
Peter
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180522/f5204262/attachment-0001.html>


More information about the cfe-commits mailing list