Index: clang/include/clang/Basic/CodeGenOptions.h =================================================================== --- clang/include/clang/Basic/CodeGenOptions.h +++ clang/include/clang/Basic/CodeGenOptions.h @@ -110,6 +110,22 @@ Embed_Marker // Embed a marker as a placeholder for bitcode. }; + // This field stores one of the allowed values for the option + // -fbasicblock-sections=. The allowed values with this option are: + // {"labels", "all", "", "none"}. + // + // "labels": Only generate basic block symbols (labels) for all basic + // blocks, do not generate unique sections for basic blocks. + // Use the machine basic block id in the symbol name to + // associate profile info from virtual address to machine + // basic block. + // "all" : Generate basic block sections for all basic blocks. + // "": Generate basic block sections for a subset of basic blocks. + // The functions and the machine basic block ids are specified + // in the file. + // "none": Disable sections/labels for basic blocks. + std::string BBSections; + enum class FramePointerKind { None, // Omit all frame pointers. NonLeaf, // Keep non-leaf frame pointers. Index: clang/include/clang/Basic/CodeGenOptions.def =================================================================== --- clang/include/clang/Basic/CodeGenOptions.def +++ clang/include/clang/Basic/CodeGenOptions.def @@ -48,6 +48,9 @@ ///< aliases to base ctors when possible. CODEGENOPT(DataSections , 1, 0) ///< Set when -fdata-sections is enabled. CODEGENOPT(UniqueSectionNames, 1, 1) ///< Set for -funique-section-names. +CODEGENOPT(UniqueBBSectionNames, 1, 1) ///< Set for -funique-bb-section-names, + ///< Produce unique section names with + ///< basic block sections. ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,none CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory. Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1971,6 +1971,8 @@ Flags<[CC1Option]>, HelpText<"Place each function in its own section">; def fno_function_sections : Flag<["-"], "fno-function-sections">, Group; +def fbasicblock_sections_EQ : Joined<["-"], "fbasicblock-sections=">, Group, Flags<[CC1Option, CC1AsOption]>, + HelpText<"Place each function's basic blocks in unique sections (ELF Only) : all | labels | none | ">; def fdata_sections : Flag <["-"], "fdata-sections">, Group, Flags<[CC1Option]>, HelpText<"Place each data in its own section">; def fno_data_sections : Flag <["-"], "fno-data-sections">, Group; @@ -1985,6 +1987,12 @@ def fno_unique_section_names : Flag <["-"], "fno-unique-section-names">, Group, Flags<[CC1Option]>; +def funique_bb_section_names : Flag <["-"], "funique-bb-section-names">, + Group, Flags<[CC1Option]>, + HelpText<"Use unique names for basic block sections (ELF Only)">; +def fno_unique_bb_section_names : Flag <["-"], "fno-unique-bb-section-names">, + Group; + def fstrict_return : Flag<["-"], "fstrict-return">, Group, Flags<[CC1Option]>, HelpText<"Always treat control flow paths that fall off the end of a " Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -482,9 +482,28 @@ Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath; Options.StackAlignmentOverride = CodeGenOpts.StackAlignment; + + Options.BBSections = + llvm::StringSwitch(CodeGenOpts.BBSections) + .Case("all", llvm::BasicBlockSection::All) + .Case("labels", llvm::BasicBlockSection::Labels) + .Case("none", llvm::BasicBlockSection::None) + .Default(llvm::BasicBlockSection::List); + + if (Options.BBSections == llvm::BasicBlockSection::List) { + ErrorOr> MBOrErr = + MemoryBuffer::getFile(CodeGenOpts.BBSections); + if (!MBOrErr) + errs() << "Error loading basic block sections function list file: " + << MBOrErr.getError().message() << "\n"; + else + Options.BBSectionsFuncListBuf = std::move(*MBOrErr); + } + Options.FunctionSections = CodeGenOpts.FunctionSections; Options.DataSections = CodeGenOpts.DataSections; Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames; + Options.UniqueBBSectionNames = CodeGenOpts.UniqueBBSectionNames; Options.TLSSize = CodeGenOpts.TLSSize; Options.EmulatedTLS = CodeGenOpts.EmulatedTLS; Options.ExplicitEmulatedTLS = CodeGenOpts.ExplicitEmulatedTLS; Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -4254,8 +4254,11 @@ options::OPT_fno_function_sections, options::OPT_fdata_sections, options::OPT_fno_data_sections, + options::OPT_fbasicblock_sections_EQ, options::OPT_funique_section_names, options::OPT_fno_unique_section_names, + options::OPT_funique_bb_section_names, + options::OPT_fno_unique_bb_section_names, options::OPT_mrestrict_it, options::OPT_mno_restrict_it, options::OPT_mstackrealign, @@ -4852,6 +4855,16 @@ CmdArgs.push_back("-ffunction-sections"); } + if (Arg *A = Args.getLastArg(options::OPT_fbasicblock_sections_EQ)) { + StringRef Val = A->getValue(); + if (Val != "all" && Val != "labels" && Val != "none" && + !llvm::sys::fs::exists(Val)) + D.Diag(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + else + A->render(Args, CmdArgs); + } + if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections, UseSeparateSections)) { CmdArgs.push_back("-fdata-sections"); @@ -4861,6 +4874,10 @@ options::OPT_fno_unique_section_names, true)) CmdArgs.push_back("-fno-unique-section-names"); + if (Args.hasFlag(options::OPT_funique_bb_section_names, + options::OPT_fno_unique_bb_section_names, false)) + CmdArgs.push_back("-funique-bb-section-names"); + Args.AddLastArg(CmdArgs, options::OPT_finstrument_functions, options::OPT_finstrument_functions_after_inlining, options::OPT_finstrument_function_entry_bare); Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -954,10 +954,18 @@ Opts.TrapFuncName = std::string(Args.getLastArgValue(OPT_ftrap_function_EQ)); Opts.UseInitArray = !Args.hasArg(OPT_fno_use_init_array); - Opts.FunctionSections = Args.hasArg(OPT_ffunction_sections); + Opts.BBSections = + std::string(Args.getLastArgValue(OPT_fbasicblock_sections_EQ, "none")); + + // Basic Block Sections implies Function Sections. + Opts.FunctionSections = + Args.hasArg(OPT_ffunction_sections) || + (Opts.BBSections != "none" && Opts.BBSections != "labels"); + Opts.DataSections = Args.hasArg(OPT_fdata_sections); Opts.StackSizeSection = Args.hasArg(OPT_fstack_size_section); Opts.UniqueSectionNames = !Args.hasArg(OPT_fno_unique_section_names); + Opts.UniqueBBSectionNames = Args.hasArg(OPT_funique_bb_section_names); Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions); Index: clang/test/CodeGen/basicblock-sections.c =================================================================== --- /dev/null +++ clang/test/CodeGen/basicblock-sections.c @@ -0,0 +1,47 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S -o - < %s | FileCheck %s --check-prefix=PLAIN +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S -fbasicblock-sections=all -fbasicblock-sections=none -o - < %s | FileCheck %s --check-prefix=PLAIN + +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S -fbasicblock-sections=labels -o - < %s | FileCheck %s --check-prefix=BB_LABELS +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S -fbasicblock-sections=all -o - < %s | FileCheck %s --check-prefix=BB_WORLD --check-prefix=BB_ALL +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S -fbasicblock-sections=%S/basicblock-sections.funcnames -o - < %s | FileCheck %s --check-prefix=BB_WORLD --check-prefix=BB_LIST +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S -fbasicblock-sections=all -funique-bb-section-names -o - < %s | FileCheck %s --check-prefix=UNIQUE + +int world(int a) { + if (a > 10) + return 10; + else if (a > 5) + return 5; + else + return 0; +} + +int another(int a) { + if (a > 10) + return 20; + return 0; +} + +// PLAIN-NOT: section +// PLAIN: world: +// +// BB_LABELS-NOT: section +// BB_LABELS: world: +// BB_LABELS: a.BB.world: +// BB_LABELS: aa.BB.world: +// BB_LABELS: a.BB.another: +// +// BB_WORLD: .section .text.world,"ax",@progbits{{$}} +// BB_WORLD: world: +// BB_WORLD: .section .text.world,"ax",@progbits,unique +// BB_WORLD: a.BB.world: +// BB_WORLD: .section .text.another,"ax",@progbits +// BB_ALL: .section .text.another,"ax",@progbits,unique +// BB_ALL: a.BB.another: +// BB_LIST-NOT: .section .text.another,"ax",@progbits,unique +// BB_LIST: another: +// BB_LIST-NOT: a.BB.another: +// +// UNIQUE: .section .text.world.a.BB.world, +// UNIQUE: .section .text.another.a.BB.another, Index: clang/test/CodeGen/basicblock-sections.funcnames =================================================================== --- /dev/null +++ clang/test/CodeGen/basicblock-sections.funcnames @@ -0,0 +1 @@ +!world Index: clang/test/Driver/fbasicblock-sections.c =================================================================== --- /dev/null +++ clang/test/Driver/fbasicblock-sections.c @@ -0,0 +1,9 @@ +// RUN: %clang -### -fbasicblock-sections=none %s -S 2>&1 | FileCheck -check-prefix=CHECK-OPT-NONE %s +// RUN: %clang -### -fbasicblock-sections=all %s -S 2>&1 | FileCheck -check-prefix=CHECK-OPT-ALL %s +// RUN: %clang -### -fbasicblock-sections=%s %s -S 2>&1 | FileCheck -check-prefix=CHECK-OPT-LIST %s +// RUN: %clang -### -fbasicblock-sections=labels %s -S 2>&1 | FileCheck -check-prefix=CHECK-OPT-LABELS %s +// +// CHECK-OPT-NONE: "-fbasicblock-sections=none" +// CHECK-OPT-ALL: "-fbasicblock-sections=all" +// CHECK-OPT-LIST: -fbasicblock-sections={{[^ ]*}}fbasicblock-sections.c +// CHECK-OPT-LABELS: "-fbasicblock-sections=labels" Index: clang/test/Driver/funique-bb-section-names.c =================================================================== --- /dev/null +++ clang/test/Driver/funique-bb-section-names.c @@ -0,0 +1,4 @@ +// RUN: %clang -### -funique-bb-section-names %s -S 2>&1 | FileCheck -check-prefix=CHECK-OPT %s +// RUN: %clang -### -funique-bb-section-names -fno-unique-bb-section-names %s -S 2>&1 | FileCheck -check-prefix=CHECK-NOOPT %s +// CHECK-OPT: "-funique-bb-section-names" +// CHECK-NOOPT-NOT: "-funique-bb-section-names"