SBallantyne updated this revision to Diff 508949. SBallantyne marked an inline comment as done. SBallantyne added a comment.
Add common function addDebugKindInfo, update warning message Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D146814/new/ https://reviews.llvm.org/D146814 Files: clang/include/clang/Driver/Options.td clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Driver/ToolChains/CommonArgs.cpp clang/lib/Driver/ToolChains/CommonArgs.h clang/lib/Driver/ToolChains/Flang.cpp flang/include/flang/Frontend/CodeGenOptions.def flang/include/flang/Frontend/CodeGenOptions.h flang/include/flang/Tools/CLOptions.inc flang/lib/Frontend/CompilerInvocation.cpp flang/lib/Frontend/FrontendActions.cpp flang/test/Driver/driver-help-hidden.f90 flang/test/Driver/driver-help.f90 flang/test/Driver/mlir-debug-pass-pipeline.f90
Index: flang/test/Driver/mlir-debug-pass-pipeline.f90 =================================================================== --- /dev/null +++ flang/test/Driver/mlir-debug-pass-pipeline.f90 @@ -0,0 +1,83 @@ +! Test the debug pass pipeline + +! RUN: %flang -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline -o /dev/null %s 2>&1 | FileCheck --check-prefixes=ALL,NO-DEBUG %s + +! RUN: %flang -g0 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL,NO-DEBUG %s +! RUN: %flang -g -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL,DEBUG %s +! RUN: %flang -g1 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL,DEBUG %s +! RUN: %flang -gline-tables-only -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL,DEBUG %s +! RUN: %flang -gline-directives-only -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL,DEBUG,DEBUG-DIRECTIVES %s +! RUN: %flang -g2 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL,DEBUG,DEBUG-CONSTRUCT %s +! RUN: %flang -g3 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL,DEBUG,DEBUG-CONSTRUCT %s + +! RUN: not %flang_fc1 -debug-info-kind=invalid -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -o /dev/null 2>&1 | FileCheck --check-prefixes=DEBUG-ERR %s + +! REQUIRES: asserts + +end program + +! DEBUG-CONSTRUCT: warning: Unsupported debug option: constructor +! DEBUG-DIRECTIVES: warning: Unsupported debug option: line-directives-only +! +! DEBUG-ERR: error: invalid value 'invalid' in '-debug-info-kind=invalid' +! DEBUG-ERR-NOT: Pass statistics report + +! ALL: Pass statistics report + +! ALL: Fortran::lower::VerifierPass +! ALL-NEXT: LowerHLFIRIntrinsics +! ALL-NEXT: BufferizeHLFIR +! ALL-NEXT: ConvertHLFIRtoFIR +! ALL-NEXT: CSE +! Ideally, we need an output with only the pass names, but +! there is currently no way to get that, so in order to +! guarantee that the passes are in the expected order +! (i.e. use -NEXT) we have to check the statistics output as well. +! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd +! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd + +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: ArrayValueCopy +! ALL-NEXT: CharacterConversion + +! ALL-NEXT: Canonicalizer +! ALL-NEXT: SimplifyRegionLite +! ALL-NEXT: CSE +! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd +! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd + +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: MemoryAllocationOpt + +! ALL-NEXT: Inliner +! ALL-NEXT: SimplifyRegionLite +! ALL-NEXT: CSE +! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd +! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd + +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: PolymorphicOpConversion +! ALL-NEXT: CFGConversion + +! ALL-NEXT: SCFToControlFlow +! ALL-NEXT: Canonicalizer +! ALL-NEXT: SimplifyRegionLite +! ALL-NEXT: CSE +! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd +! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd +! ALL-NEXT: BoxedProcedurePass + +! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func'] +! ALL-NEXT: 'fir.global' Pipeline +! ALL-NEXT: AbstractResultOnGlobalOpt +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: AbstractResultOnFuncOpt + +! ALL-NEXT: CodeGenRewrite +! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated +! ALL-NEXT: TargetRewrite +! ALL-NEXT: ExternalNameConversion +! DEBUG-NEXT: AddDebugFoundation +! NO-DEBUG-NOT: AddDebugFoundation +! ALL-NEXT: FIRToLLVMLowering +! ALL-NOT: LLVMIRLoweringPass Index: flang/test/Driver/driver-help.f90 =================================================================== --- flang/test/Driver/driver-help.f90 +++ flang/test/Driver/driver-help.f90 @@ -56,6 +56,8 @@ ! HELP-NEXT: -fsyntax-only Run the preprocessor, parser and semantic analysis stages ! HELP-NEXT: -funderscoring Appends one trailing underscore to external names ! HELP-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV. +! HELP-NEXT: -gline-tables-only Emit debug line number tables only +! HELP-NEXT: -g Generate source-level debug information ! HELP-NEXT: -help Display available options ! HELP-NEXT: -I <dir> Add directory to the end of the list of include search paths ! HELP-NEXT: -mllvm=<arg> Alias for -mllvm Index: flang/test/Driver/driver-help-hidden.f90 =================================================================== --- flang/test/Driver/driver-help-hidden.f90 +++ flang/test/Driver/driver-help-hidden.f90 @@ -60,6 +60,8 @@ ! CHECK-NEXT: -fsyntax-only Run the preprocessor, parser and semantic analysis stages ! CHECK-NEXT: -funderscoring Appends one trailing underscore to external names ! CHECK-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV. +! CHECK-NEXT: -gline-tables-only Emit debug line number tables only +! CHECK-NEXT: -g Generate source-level debug information ! CHECK-NEXT: -help Display available options ! CHECK-NEXT: -I <dir> Add directory to the end of the list of include search paths ! CHECK-NEXT: -mllvm=<arg> Alias for -mllvm Index: flang/lib/Frontend/FrontendActions.cpp =================================================================== --- flang/lib/Frontend/FrontendActions.cpp +++ flang/lib/Frontend/FrontendActions.cpp @@ -606,7 +606,7 @@ // Create the pass pipeline fir::createMLIRToLLVMPassPipeline(pm, level, opts.StackArrays, - opts.Underscoring); + opts.Underscoring, opts.getDebugInfo()); mlir::applyPassManagerCLOptions(pm); // run the pass manager Index: flang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- flang/lib/Frontend/CompilerInvocation.cpp +++ flang/lib/Frontend/CompilerInvocation.cpp @@ -25,6 +25,7 @@ #include "clang/Driver/Options.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Frontend/Debug/Options.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" @@ -117,6 +118,38 @@ return true; } +static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts, + llvm::opt::ArgList &args, + clang::DiagnosticsEngine &diags) { + using DebugInfoKind = llvm::codegenoptions::DebugInfoKind; + if (llvm::opt::Arg *arg = + args.getLastArg(clang::driver::options::OPT_debug_info_kind_EQ)) { + std::optional<DebugInfoKind> val = + llvm::StringSwitch<std::optional<DebugInfoKind>>(arg->getValue()) + .Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly) + .Case("line-directives-only", + llvm::codegenoptions::DebugDirectivesOnly) + .Case("constructor", llvm::codegenoptions::DebugInfoConstructor) + .Case("limited", llvm::codegenoptions::LimitedDebugInfo) + .Case("standalone", llvm::codegenoptions::FullDebugInfo) + .Case("unused-types", llvm::codegenoptions::UnusedTypeInfo) + .Default(std::nullopt); + if (!val.has_value()) { + diags.Report(clang::diag::err_drv_invalid_value) + << arg->getAsString(args) << arg->getValue(); + return false; + } + opts.setDebugInfo(val.value()); + if (val != llvm::codegenoptions::DebugLineTablesOnly && + val != llvm::codegenoptions::NoDebugInfo) { + const auto debugWarning = diags.getCustomDiagID( + clang::DiagnosticsEngine::Warning, "Unsupported debug option: %0"); + diags.Report(debugWarning) << arg->getValue(); + } + } + return true; +} + static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, llvm::opt::ArgList &args, clang::DiagnosticsEngine &diags) { @@ -830,6 +863,7 @@ parseTargetArgs(res.getTargetOpts(), args); parsePreprocessorArgs(res.getPreprocessorOpts(), args); parseCodeGenArgs(res.getCodeGenOpts(), args, diags); + success &= parseDebugArgs(res.getCodeGenOpts(), args, diags); success &= parseSemaArgs(res, args, diags); success &= parseDialectArgs(res, args, diags); success &= parseDiagArgs(res, args, diags); Index: flang/include/flang/Tools/CLOptions.inc =================================================================== --- flang/include/flang/Tools/CLOptions.inc +++ flang/include/flang/Tools/CLOptions.inc @@ -18,6 +18,7 @@ #include "flang/Optimizer/Transforms/Passes.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Frontend/Debug/Options.h" #define DisableOption(DOName, DOOption, DODescription) \ static llvm::cl::opt<bool> disable##DOName("disable-" DOOption, \ @@ -56,6 +57,9 @@ const static llvm::OptimizationLevel &defaultOptLevel{ llvm::OptimizationLevel::O0}; +const static llvm::codegenoptions::DebugInfoKind &NoDebugInfo{ + llvm::codegenoptions::NoDebugInfo}; + /// Optimizer Passes DisableOption(CfgConversion, "cfg-conversion", "disable FIR to CFG pass"); DisableOption(FirAvc, "avc", "array value copy analysis and transformation"); @@ -228,9 +232,28 @@ } #if !defined(FLANG_EXCLUDE_CODEGEN) +inline void createDebugPasses( + mlir::PassManager &pm, llvm::codegenoptions::DebugInfoKind debugLevel) { + // Currently only -g1, -g, -gline-tables-only supported + switch(debugLevel) { + case llvm::codegenoptions::DebugLineTablesOnly: + addDebugFoundationPass(pm); + return; + case llvm::codegenoptions::NoDebugInfo: + return; + default: + // TODO: Add cases and passes for other debug options. + // All other debug options not implemented yet, currently emits warning + // and generates as much debug information as possible. + addDebugFoundationPass(pm); + return; + } +} + inline void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, llvm::OptimizationLevel optLevel = defaultOptLevel, - bool underscoring = true) { + bool underscoring = true, + llvm::codegenoptions::DebugInfoKind debugInfo = NoDebugInfo) { fir::addBoxedProcedurePass(pm); pm.addNestedPass<mlir::func::FuncOp>( fir::createAbstractResultOnFuncOptPass()); @@ -238,6 +261,7 @@ fir::addCodeGenRewritePass(pm); fir::addTargetRewritePass(pm); fir::addExternalNameConversionPass(pm, underscoring); + fir::createDebugPasses(pm, debugInfo); fir::addFIRToLLVMPass(pm, optLevel); } @@ -248,14 +272,15 @@ /// passes pipeline inline void createMLIRToLLVMPassPipeline(mlir::PassManager &pm, llvm::OptimizationLevel optLevel = defaultOptLevel, - bool stackArrays = false, bool underscoring = true) { + bool stackArrays = false, bool underscoring = true, + llvm::codegenoptions::DebugInfoKind debugInfo = NoDebugInfo) { fir::createHLFIRToFIRPassPipeline(pm, optLevel); // Add default optimizer pass pipeline. fir::createDefaultFIROptimizerPassPipeline(pm, optLevel, stackArrays); // Add codegen pass pipeline. - fir::createDefaultFIRCodeGenPassPipeline(pm, optLevel, underscoring); + fir::createDefaultFIRCodeGenPassPipeline(pm, optLevel, underscoring, debugInfo); } #undef FLANG_EXCLUDE_CODEGEN #endif Index: flang/include/flang/Frontend/CodeGenOptions.h =================================================================== --- flang/include/flang/Frontend/CodeGenOptions.h +++ flang/include/flang/Frontend/CodeGenOptions.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_BASIC_CODEGENOPTIONS_H #define LLVM_CLANG_BASIC_CODEGENOPTIONS_H +#include "llvm/Frontend/Debug/Options.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Regex.h" #include "llvm/Target/TargetOptions.h" Index: flang/include/flang/Frontend/CodeGenOptions.def =================================================================== --- flang/include/flang/Frontend/CodeGenOptions.def +++ flang/include/flang/Frontend/CodeGenOptions.def @@ -34,6 +34,7 @@ CODEGENOPT(Underscoring, 1, 1) ENUM_CODEGENOPT(RelocationModel, llvm::Reloc::Model, 3, llvm::Reloc::PIC_) ///< Name of the relocation model to use. +ENUM_CODEGENOPT(DebugInfo, llvm::codegenoptions::DebugInfoKind, 4, llvm::codegenoptions::NoDebugInfo) ///< Level of debug info to generate #undef CODEGENOPT #undef ENUM_CODEGENOPT Index: clang/lib/Driver/ToolChains/Flang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Flang.cpp +++ clang/lib/Driver/ToolChains/Flang.cpp @@ -11,6 +11,7 @@ #include "CommonArgs.h" #include "clang/Driver/Options.h" +#include "llvm/Frontend/Debug/Options.h" #include <cassert> @@ -68,6 +69,17 @@ if (Args.hasArg(options::OPT_flang_experimental_hlfir)) CmdArgs.push_back("-flang-experimental-hlfir"); + + llvm::codegenoptions::DebugInfoKind DebugInfoKind; + if (Args.hasArg(options::OPT_gN_Group)) { + Arg *gNArg = Args.getLastArg(options::OPT_gN_Group); + DebugInfoKind = DebugLevelToInfoKind(*gNArg); + } else if (Args.hasArg(options::OPT_g_Flag)) { + DebugInfoKind = llvm::codegenoptions::DebugLineTablesOnly; + } else { + DebugInfoKind = llvm::codegenoptions::NoDebugInfo; + } + addDebugInfoKind(CmdArgs, DebugInfoKind); } void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const { Index: clang/lib/Driver/ToolChains/CommonArgs.h =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.h +++ clang/lib/Driver/ToolChains/CommonArgs.h @@ -104,6 +104,12 @@ unsigned ParseFunctionAlignment(const ToolChain &TC, const llvm::opt::ArgList &Args); +void addDebugInfoKind(llvm::opt::ArgStringList &CmdArgs, + llvm::codegenoptions::DebugInfoKind DebugInfoKind); + +llvm::codegenoptions::DebugInfoKind +DebugLevelToInfoKind(const llvm::opt::Arg &A); + // Extract the integer N from a string spelled "-dwarf-N", returning 0 // on mismatch. The StringRef input (rather than an Arg) allows // for use by the "-Xassembler" option parser. Index: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1581,6 +1581,48 @@ return Value ? llvm::Log2_32_Ceil(std::min(Value, 65536u)) : Value; } +void tools::addDebugInfoKind( + ArgStringList &CmdArgs, llvm::codegenoptions::DebugInfoKind DebugInfoKind) { + switch (DebugInfoKind) { + case llvm::codegenoptions::DebugDirectivesOnly: + CmdArgs.push_back("-debug-info-kind=line-directives-only"); + break; + case llvm::codegenoptions::DebugLineTablesOnly: + CmdArgs.push_back("-debug-info-kind=line-tables-only"); + break; + case llvm::codegenoptions::DebugInfoConstructor: + CmdArgs.push_back("-debug-info-kind=constructor"); + break; + case llvm::codegenoptions::LimitedDebugInfo: + CmdArgs.push_back("-debug-info-kind=limited"); + break; + case llvm::codegenoptions::FullDebugInfo: + CmdArgs.push_back("-debug-info-kind=standalone"); + break; + case llvm::codegenoptions::UnusedTypeInfo: + CmdArgs.push_back("-debug-info-kind=unused-types"); + break; + default: + break; + } +} + +// Convert an arg of the form "-gN" or "-ggdbN" or one of their aliases +// to the corresponding DebugInfoKind. +llvm::codegenoptions::DebugInfoKind tools::DebugLevelToInfoKind(const Arg &A) { + assert(A.getOption().matches(options::OPT_gN_Group) && + "Not a -g option that specifies a debug-info level"); + if (A.getOption().matches(options::OPT_g0) || + A.getOption().matches(options::OPT_ggdb0)) + return llvm::codegenoptions::NoDebugInfo; + if (A.getOption().matches(options::OPT_gline_tables_only) || + A.getOption().matches(options::OPT_ggdb1)) + return llvm::codegenoptions::DebugLineTablesOnly; + if (A.getOption().matches(options::OPT_gline_directives_only)) + return llvm::codegenoptions::DebugDirectivesOnly; + return llvm::codegenoptions::DebugInfoConstructor; +} + static unsigned ParseDebugDefaultVersion(const ToolChain &TC, const ArgList &Args) { const Arg *A = Args.getLastArg(options::OPT_fdebug_default_version); Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -403,22 +403,6 @@ Default); } -// Convert an arg of the form "-gN" or "-ggdbN" or one of their aliases -// to the corresponding DebugInfoKind. -static llvm::codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) { - assert(A.getOption().matches(options::OPT_gN_Group) && - "Not a -g option that specifies a debug-info level"); - if (A.getOption().matches(options::OPT_g0) || - A.getOption().matches(options::OPT_ggdb0)) - return llvm::codegenoptions::NoDebugInfo; - if (A.getOption().matches(options::OPT_gline_tables_only) || - A.getOption().matches(options::OPT_ggdb1)) - return llvm::codegenoptions::DebugLineTablesOnly; - if (A.getOption().matches(options::OPT_gline_directives_only)) - return llvm::codegenoptions::DebugDirectivesOnly; - return llvm::codegenoptions::DebugInfoConstructor; -} - static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) { switch (Triple.getArch()){ default: @@ -977,28 +961,7 @@ llvm::codegenoptions::DebugInfoKind DebugInfoKind, unsigned DwarfVersion, llvm::DebuggerKind DebuggerTuning) { - switch (DebugInfoKind) { - case llvm::codegenoptions::DebugDirectivesOnly: - CmdArgs.push_back("-debug-info-kind=line-directives-only"); - break; - case llvm::codegenoptions::DebugLineTablesOnly: - CmdArgs.push_back("-debug-info-kind=line-tables-only"); - break; - case llvm::codegenoptions::DebugInfoConstructor: - CmdArgs.push_back("-debug-info-kind=constructor"); - break; - case llvm::codegenoptions::LimitedDebugInfo: - CmdArgs.push_back("-debug-info-kind=limited"); - break; - case llvm::codegenoptions::FullDebugInfo: - CmdArgs.push_back("-debug-info-kind=standalone"); - break; - case llvm::codegenoptions::UnusedTypeInfo: - CmdArgs.push_back("-debug-info-kind=unused-types"); - break; - default: - break; - } + addDebugInfoKind(CmdArgs, DebugInfoKind); if (DwarfVersion > 0) CmdArgs.push_back( Args.MakeArgString("-dwarf-version=" + Twine(DwarfVersion))); Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -3232,9 +3232,9 @@ NormalizedValuesScope<"llvm::EmitDwarfUnwindType">, MarshallingInfoEnum<CodeGenOpts<"EmitDwarfUnwind">, "Default">; def g_Flag : Flag<["-"], "g">, Group<g_Group>, - HelpText<"Generate source-level debug information">; + Flags<[CoreOption,FlangOption]>, HelpText<"Generate source-level debug information">; def gline_tables_only : Flag<["-"], "gline-tables-only">, Group<gN_Group>, - Flags<[CoreOption]>, HelpText<"Emit debug line number tables only">; + Flags<[CoreOption,FlangOption]>, HelpText<"Emit debug line number tables only">; def gline_directives_only : Flag<["-"], "gline-directives-only">, Group<gN_Group>, Flags<[CoreOption]>, HelpText<"Emit debug line info directives only">; def gmlt : Flag<["-"], "gmlt">, Alias<gline_tables_only>; @@ -5468,12 +5468,12 @@ NormalizedValuesScope<"llvm::Reloc">, NormalizedValues<["Static", "PIC_", "ROPI", "RWPI", "ROPI_RWPI", "DynamicNoPIC"]>, MarshallingInfoEnum<CodeGenOpts<"RelocationModel">, "PIC_">; +def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">; } // let Flags = [CC1Option, CC1AsOption, FC1Option, NoDriverOption] let Flags = [CC1Option, CC1AsOption, NoDriverOption] in { -def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">; def debug_info_macro : Flag<["-"], "debug-info-macro">, HelpText<"Emit macro debug information">, MarshallingInfoFlag<CodeGenOpts<"MacroDebugInfo">>;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits