Implement a new -fstandalone-debug option. rdar://problem/15685848
It controls everything that -flimit-debug-info used to, plus the vtable type optimization. The old -fno-limit-debug-info option is now an alias to -fstandalone-debug and vice versa. Standalone is the default on Darwin until dtrace is updated to work with non-standalone debug info (rdar://problem/15758808). Note: I kept the LimitedDebugInfo name in CodeGenOptions::DebugInfoKind because NoStandaloneDebugInfo sounded even more confusing. llvm-svn: 198655
This commit is contained in:
parent
0b8e3b2cb4
commit
a763447124
|
@ -312,12 +312,19 @@ Currently equivalent to B<-O3>
|
||||||
Generate debug information. Note that Clang debug information works best at
|
Generate debug information. Note that Clang debug information works best at
|
||||||
B<-O0>.
|
B<-O0>.
|
||||||
|
|
||||||
=item B<-flimit-debug-info> B<-fno-limit-debug-info>
|
=item B<-fstandalone-debug> B<-fno-standalone-debug>
|
||||||
|
|
||||||
By default Clang does not emit type definitions for types that are not
|
Clang supports a number of optimizations to reduce the size of debug
|
||||||
needed by the module and could be replaced with a forward
|
information in the binary. They work based on the assumption that the
|
||||||
declaration. By specifying B<-fno-limit-debug-info> this optimization
|
debug type information can be spread out over multiple compilation
|
||||||
can be turned off. Note that Clang will never emit type information
|
units. For instance, Clang will not emit type definitions for types
|
||||||
|
that are not needed by a module and could be replaced with a forward
|
||||||
|
declaration. Further, Clang will only emit type info for a dynamic
|
||||||
|
C++ class in the module that contains the vtable for the class.
|
||||||
|
|
||||||
|
The B<-fstandalone-debug> option turns off these optimizations. This
|
||||||
|
is useful when working with 3rd-party libraries that don't come with
|
||||||
|
debug information. Note that Clang will never emit type information
|
||||||
for types that are not referenced at all by the program.
|
for types that are not referenced at all by the program.
|
||||||
|
|
||||||
=item B<-fexceptions>
|
=item B<-fexceptions>
|
||||||
|
|
|
@ -559,8 +559,6 @@ def finstrument_functions : Flag<["-"], "finstrument-functions">, Group<f_Group>
|
||||||
def fkeep_inline_functions : Flag<["-"], "fkeep-inline-functions">, Group<clang_ignored_f_Group>;
|
def fkeep_inline_functions : Flag<["-"], "fkeep-inline-functions">, Group<clang_ignored_f_Group>;
|
||||||
def flat__namespace : Flag<["-"], "flat_namespace">;
|
def flat__namespace : Flag<["-"], "flat_namespace">;
|
||||||
def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
|
def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
|
||||||
def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Group<f_Group>, Flags<[CC1Option]>,
|
|
||||||
HelpText<"Limit debug information produced to reduce size of debug binary">;
|
|
||||||
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
|
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
|
||||||
def flto : Flag<["-"], "flto">, Group<f_Group>;
|
def flto : Flag<["-"], "flto">, Group<f_Group>;
|
||||||
def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>;
|
def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>;
|
||||||
|
@ -654,8 +652,6 @@ def fno_inline : Flag<["-"], "fno-inline">, Group<f_clang_Group>, Flags<[CC1Opti
|
||||||
def fno_keep_inline_functions : Flag<["-"], "fno-keep-inline-functions">, Group<clang_ignored_f_Group>;
|
def fno_keep_inline_functions : Flag<["-"], "fno-keep-inline-functions">, Group<clang_ignored_f_Group>;
|
||||||
def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>,
|
def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>,
|
||||||
HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>;
|
HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>;
|
||||||
def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Group<f_Group>, Flags<[CC1Option]>,
|
|
||||||
HelpText<"Do not limit debug information produced to reduce size of debug binary">;
|
|
||||||
def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Group>,
|
def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Group>,
|
||||||
Flags<[CC1Option]>, HelpText<"Disallow merging of constants">;
|
Flags<[CC1Option]>, HelpText<"Disallow merging of constants">;
|
||||||
def fno_modules : Flag <["-"], "fno-modules">, Group<f_Group>,
|
def fno_modules : Flag <["-"], "fno-modules">, Group<f_Group>,
|
||||||
|
@ -783,6 +779,12 @@ def fno_signed_char : Flag<["-"], "fno-signed-char">, Flags<[CC1Option]>,
|
||||||
def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>;
|
def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>;
|
||||||
def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>;
|
def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>;
|
||||||
def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>;
|
def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>;
|
||||||
|
def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>, Flags<[CC1Option]>,
|
||||||
|
HelpText<"Emit full debug info for all types used by the program">;
|
||||||
|
def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>, Flags<[CC1Option]>,
|
||||||
|
HelpText<"Limit debug information produced to reduce size of debug binary">;
|
||||||
|
def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Alias<fno_standalone_debug>;
|
||||||
|
def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Alias<fstandalone_debug>;
|
||||||
def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group<f_Group>;
|
def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group<f_Group>;
|
||||||
def fstrict_enums : Flag<["-"], "fstrict-enums">, Group<f_Group>, Flags<[CC1Option]>,
|
def fstrict_enums : Flag<["-"], "fstrict-enums">, Group<f_Group>, Flags<[CC1Option]>,
|
||||||
HelpText<"Enable optimizations based on the strict definition of an enum's "
|
HelpText<"Enable optimizations based on the strict definition of an enum's "
|
||||||
|
|
|
@ -50,12 +50,20 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DebugInfoKind {
|
enum DebugInfoKind {
|
||||||
NoDebugInfo, // Don't generate debug info.
|
NoDebugInfo, /// Don't generate debug info.
|
||||||
DebugLineTablesOnly, // Emit only debug info necessary for generating
|
|
||||||
// line number tables (-gline-tables-only).
|
DebugLineTablesOnly, /// Emit only debug info necessary for generating
|
||||||
LimitedDebugInfo, // Limit generated debug info to reduce size
|
/// line number tables (-gline-tables-only).
|
||||||
// (-flimit-debug-info).
|
|
||||||
FullDebugInfo // Generate complete debug info.
|
LimitedDebugInfo, /// Limit generated debug info to reduce size
|
||||||
|
/// (-fno-standalone-debug). This emits
|
||||||
|
/// forward decls for types that could be
|
||||||
|
/// replaced with forward decls in the source
|
||||||
|
/// code. For dynamic C++ classes type info
|
||||||
|
/// is only emitted int the module that
|
||||||
|
/// contains the classe's vtable.
|
||||||
|
|
||||||
|
FullDebugInfo /// Generate complete debug info.
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TLSModel {
|
enum TLSModel {
|
||||||
|
|
|
@ -1464,13 +1464,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
|
||||||
// declaration. The completeType, completeRequiredType, and completeClassData
|
// declaration. The completeType, completeRequiredType, and completeClassData
|
||||||
// callbacks will handle promoting the declaration to a definition.
|
// callbacks will handle promoting the declaration to a definition.
|
||||||
if (T ||
|
if (T ||
|
||||||
|
// Under -flimit-debug-info:
|
||||||
(DebugKind <= CodeGenOptions::LimitedDebugInfo &&
|
(DebugKind <= CodeGenOptions::LimitedDebugInfo &&
|
||||||
// Under -flimit-debug-info, emit only a declaration unless the type is
|
// Emit only a forward declaration unless the type is required.
|
||||||
// required to be complete.
|
((!RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) ||
|
||||||
!RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) ||
|
|
||||||
// If the class is dynamic, only emit a declaration. A definition will be
|
// If the class is dynamic, only emit a declaration. A definition will be
|
||||||
// emitted whenever the vtable is emitted.
|
// emitted whenever the vtable is emitted.
|
||||||
(CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())) {
|
(CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())))) {
|
||||||
llvm::DIDescriptor FDContext =
|
llvm::DIDescriptor FDContext =
|
||||||
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
|
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
|
||||||
if (!T)
|
if (!T)
|
||||||
|
|
|
@ -2945,8 +2945,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||||
// Forward -f (flag) options which we can pass directly.
|
// Forward -f (flag) options which we can pass directly.
|
||||||
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
|
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
|
||||||
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
|
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
|
||||||
Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info);
|
Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug);
|
||||||
Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info);
|
Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug);
|
||||||
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
|
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
|
||||||
// AltiVec language extensions aren't relevant for assembling.
|
// AltiVec language extensions aren't relevant for assembling.
|
||||||
if (!isa<PreprocessJobAction>(JA) ||
|
if (!isa<PreprocessJobAction>(JA) ||
|
||||||
|
|
|
@ -296,7 +296,8 @@ static void ParseCommentArgs(CommentOptions &Opts, ArgList &Args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
||||||
DiagnosticsEngine &Diags) {
|
DiagnosticsEngine &Diags,
|
||||||
|
const TargetOptions &TargetOpts) {
|
||||||
using namespace options;
|
using namespace options;
|
||||||
bool Success = true;
|
bool Success = true;
|
||||||
|
|
||||||
|
@ -323,10 +324,16 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
||||||
Opts.setDebugInfo(CodeGenOptions::DebugLineTablesOnly);
|
Opts.setDebugInfo(CodeGenOptions::DebugLineTablesOnly);
|
||||||
} else if (Args.hasArg(OPT_g_Flag) || Args.hasArg(OPT_gdwarf_2) ||
|
} else if (Args.hasArg(OPT_g_Flag) || Args.hasArg(OPT_gdwarf_2) ||
|
||||||
Args.hasArg(OPT_gdwarf_3) || Args.hasArg(OPT_gdwarf_4)) {
|
Args.hasArg(OPT_gdwarf_3) || Args.hasArg(OPT_gdwarf_4)) {
|
||||||
if (Args.hasFlag(OPT_flimit_debug_info, OPT_fno_limit_debug_info, true))
|
bool Default = false;
|
||||||
Opts.setDebugInfo(CodeGenOptions::LimitedDebugInfo);
|
// Until dtrace (via CTF) can deal with distributed debug info,
|
||||||
else
|
// Darwin defaults to standalone/full debug info.
|
||||||
|
if (llvm::Triple(TargetOpts.Triple).isOSDarwin())
|
||||||
|
Default = true;
|
||||||
|
|
||||||
|
if (Args.hasFlag(OPT_fstandalone_debug, OPT_fno_standalone_debug, Default))
|
||||||
Opts.setDebugInfo(CodeGenOptions::FullDebugInfo);
|
Opts.setDebugInfo(CodeGenOptions::FullDebugInfo);
|
||||||
|
else
|
||||||
|
Opts.setDebugInfo(CodeGenOptions::LimitedDebugInfo);
|
||||||
}
|
}
|
||||||
Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info);
|
Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info);
|
||||||
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
|
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
|
||||||
|
@ -1662,8 +1669,9 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
|
||||||
ParseFileSystemArgs(Res.getFileSystemOpts(), *Args);
|
ParseFileSystemArgs(Res.getFileSystemOpts(), *Args);
|
||||||
// FIXME: We shouldn't have to pass the DashX option around here
|
// FIXME: We shouldn't have to pass the DashX option around here
|
||||||
InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
|
InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
|
||||||
Success = ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags)
|
ParseTargetArgs(Res.getTargetOpts(), *Args);
|
||||||
&& Success;
|
Success = ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags,
|
||||||
|
Res.getTargetOpts()) && Success;
|
||||||
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
|
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
|
||||||
if (DashX != IK_AST && DashX != IK_LLVM_IR) {
|
if (DashX != IK_AST && DashX != IK_LLVM_IR) {
|
||||||
ParseLangArgs(*Res.getLangOpts(), *Args, DashX, Diags);
|
ParseLangArgs(*Res.getLangOpts(), *Args, DashX, Diags);
|
||||||
|
@ -1678,8 +1686,6 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
|
||||||
ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, FileMgr, Diags);
|
ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, FileMgr, Diags);
|
||||||
ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args,
|
ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args,
|
||||||
Res.getFrontendOpts().ProgramAction);
|
Res.getFrontendOpts().ProgramAction);
|
||||||
ParseTargetArgs(Res.getTargetOpts(), *Args);
|
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %clang -emit-llvm -g -S %s -o - | FileCheck %s
|
// RUN: %clang -emit-llvm -fno-standalone-debug -g -S %s -o - | FileCheck %s
|
||||||
|
|
||||||
namespace PR16214_1 {
|
namespace PR16214_1 {
|
||||||
// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [def]
|
// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [def]
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// RUN: %clang_cc1 -triple x86_64-unk-unk -fno-limit-debug-info -o - -emit-llvm -g %s | FileCheck %s
|
// RUN: %clang_cc1 -triple x86_64-unk-unk -fstandalone-debug -o - -emit-llvm -g %s | FileCheck %s
|
||||||
|
// On Darwin, this should be the default:
|
||||||
|
// RUN: %clang_cc1 -triple x86_64-apple-darwin -o - -emit-llvm -g %s | FileCheck %s
|
||||||
|
|
||||||
namespace rdar14101097_1 { // see also PR16214
|
namespace rdar14101097_1 { // see also PR16214
|
||||||
// Check that we emit debug info for the definition of a struct if the
|
// Check that we emit debug info for the definition of a struct if the
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin -fno-limit-debug-info %s -o - | FileCheck %s
|
// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin -fstandalone-debug %s -o - | FileCheck %s
|
||||||
|
|
||||||
class Test
|
class Test
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %clang_cc1 -flimit-debug-info -x c++ -g -S -emit-llvm < %s | FileCheck %s
|
// RUN: %clang_cc1 -fno-standalone-debug -x c++ -g -S -emit-llvm < %s | FileCheck %s
|
||||||
// rdar://10336845
|
// rdar://10336845
|
||||||
// Preserve type qualifiers in -flimit-debug-info mode.
|
// Preserve type qualifiers in -flimit-debug-info mode.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// RUN: %clang -g -S -emit-llvm %s -o - | FileCheck %s
|
// RUN: %clang -g -fno-standalone-debug -S -emit-llvm %s -o - | FileCheck %s
|
||||||
// RUN: %clang -g -gline-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s
|
// RUN: %clang -g -gline-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s
|
||||||
// RUN: %clang -g -fno-limit-debug-info -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s
|
// RUN: %clang -g -fstandalone-debug -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s
|
||||||
|
|
||||||
namespace A {
|
namespace A {
|
||||||
#line 1 "foo.cpp"
|
#line 1 "foo.cpp"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// REQUIRES: x86-registered-target
|
// REQUIRES: x86-registered-target
|
||||||
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -fno-limit-debug-info -S -mllvm -generate-dwarf-pub-sections=Enable %s -o - | FileCheck %s
|
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -fstandalone-debug -S -mllvm -generate-dwarf-pub-sections=Enable %s -o - | FileCheck %s
|
||||||
|
|
||||||
// FIXME: This testcase shouldn't rely on assembly emission.
|
// FIXME: This testcase shouldn't rely on assembly emission.
|
||||||
//CHECK: Lpubtypes_begin[[SECNUM:[0-9]:]]
|
//CHECK: Lpubtypes_begin[[SECNUM:[0-9]:]]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %clang_cc1 -emit-llvm -flimit-debug-info -cxx-abi itanium -g %s -o - | FileCheck %s
|
// RUN: %clang_cc1 -emit-llvm -fno-standalone-debug -cxx-abi itanium -g %s -o - | FileCheck %s
|
||||||
|
|
||||||
// Check that this pointer type is TC<int>
|
// Check that this pointer type is TC<int>
|
||||||
// CHECK: ![[LINE:[0-9]+]] = {{.*}}"TC<int>", {{.*}} metadata !"_ZTS2TCIiE"} ; [ DW_TAG_class_type ]
|
// CHECK: ![[LINE:[0-9]+]] = {{.*}}"TC<int>", {{.*}} metadata !"_ZTS2TCIiE"} ; [ DW_TAG_class_type ]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s
|
// RUN: %clang_cc1 -emit-llvm -g -fno-standalone-debug -triple x86_64-apple-darwin %s -o - | FileCheck %s
|
||||||
|
|
||||||
struct MyClass {
|
struct MyClass {
|
||||||
template <int i> int add(int j) {
|
template <int i> int add(int j) {
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s
|
||||||
|
//
|
||||||
|
// This tests that the "emit debug info for a C++ class only in the
|
||||||
|
// module that has its vtable" optimization is disabled by default on
|
||||||
|
// Darwin.
|
||||||
|
//
|
||||||
|
// CHECK: [ DW_TAG_member ] [lost]
|
||||||
|
class A
|
||||||
|
{
|
||||||
|
virtual bool f() = 0;
|
||||||
|
int lost;
|
||||||
|
};
|
||||||
|
|
||||||
|
class B : public A
|
||||||
|
{
|
||||||
|
B *g();
|
||||||
|
};
|
||||||
|
|
||||||
|
B *B::g() {
|
||||||
|
return this;
|
||||||
|
}
|
Loading…
Reference in New Issue