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:
Adrian Prantl 2014-01-07 01:19:08 +00:00
parent 0b8e3b2cb4
commit a763447124
15 changed files with 87 additions and 41 deletions

View File

@ -312,12 +312,19 @@ Currently equivalent to B<-O3>
Generate debug information. Note that Clang debug information works best at
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
needed by the module and could be replaced with a forward
declaration. By specifying B<-fno-limit-debug-info> this optimization
can be turned off. Note that Clang will never emit type information
Clang supports a number of optimizations to reduce the size of debug
information in the binary. They work based on the assumption that the
debug type information can be spread out over multiple compilation
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.
=item B<-fexceptions>

View File

@ -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 flat__namespace : Flag<["-"], "flat_namespace">;
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 flto : Flag<["-"], "flto">, 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_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]>;
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>,
Flags<[CC1Option]>, HelpText<"Disallow merging of constants">;
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 fstack_protector_all : Flag<["-"], "fstack-protector-all">, 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_enums : Flag<["-"], "fstrict-enums">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable optimizations based on the strict definition of an enum's "

View File

@ -50,12 +50,20 @@ public:
};
enum DebugInfoKind {
NoDebugInfo, // Don't generate debug info.
DebugLineTablesOnly, // Emit only debug info necessary for generating
// line number tables (-gline-tables-only).
LimitedDebugInfo, // Limit generated debug info to reduce size
// (-flimit-debug-info).
FullDebugInfo // Generate complete debug info.
NoDebugInfo, /// Don't generate debug info.
DebugLineTablesOnly, /// Emit only debug info necessary for generating
/// line number tables (-gline-tables-only).
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 {

View File

@ -1464,13 +1464,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
// declaration. The completeType, completeRequiredType, and completeClassData
// callbacks will handle promoting the declaration to a definition.
if (T ||
// Under -flimit-debug-info:
(DebugKind <= CodeGenOptions::LimitedDebugInfo &&
// Under -flimit-debug-info, emit only a declaration unless the type is
// required to be complete.
!RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) ||
// If the class is dynamic, only emit a declaration. A definition will be
// emitted whenever the vtable is emitted.
(CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())) {
// Emit only a forward declaration unless the type is required.
((!RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) ||
// If the class is dynamic, only emit a declaration. A definition will be
// emitted whenever the vtable is emitted.
(CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())))) {
llvm::DIDescriptor FDContext =
getContextDescriptor(cast<Decl>(RD->getDeclContext()));
if (!T)

View File

@ -2945,8 +2945,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Forward -f (flag) options which we can pass directly.
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info);
Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info);
Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug);
Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug);
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
// AltiVec language extensions aren't relevant for assembling.
if (!isa<PreprocessJobAction>(JA) ||

View File

@ -296,7 +296,8 @@ static void ParseCommentArgs(CommentOptions &Opts, ArgList &Args) {
}
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags) {
DiagnosticsEngine &Diags,
const TargetOptions &TargetOpts) {
using namespace options;
bool Success = true;
@ -323,10 +324,16 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.setDebugInfo(CodeGenOptions::DebugLineTablesOnly);
} else if (Args.hasArg(OPT_g_Flag) || Args.hasArg(OPT_gdwarf_2) ||
Args.hasArg(OPT_gdwarf_3) || Args.hasArg(OPT_gdwarf_4)) {
if (Args.hasFlag(OPT_flimit_debug_info, OPT_fno_limit_debug_info, true))
Opts.setDebugInfo(CodeGenOptions::LimitedDebugInfo);
else
bool Default = false;
// Until dtrace (via CTF) can deal with distributed debug info,
// 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);
else
Opts.setDebugInfo(CodeGenOptions::LimitedDebugInfo);
}
Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info);
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
@ -1662,8 +1669,9 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
ParseFileSystemArgs(Res.getFileSystemOpts(), *Args);
// FIXME: We shouldn't have to pass the DashX option around here
InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
Success = ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags)
&& Success;
ParseTargetArgs(Res.getTargetOpts(), *Args);
Success = ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags,
Res.getTargetOpts()) && Success;
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
if (DashX != IK_AST && DashX != IK_LLVM_IR) {
ParseLangArgs(*Res.getLangOpts(), *Args, DashX, Diags);
@ -1678,8 +1686,6 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, FileMgr, Diags);
ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args,
Res.getFrontendOpts().ProgramAction);
ParseTargetArgs(Res.getTargetOpts(), *Args);
return Success;
}

View File

@ -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 {
// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [def]

View File

@ -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
// Check that we emit debug info for the definition of a struct if the

View File

@ -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
{

View File

@ -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
// Preserve type qualifiers in -flimit-debug-info mode.

View File

@ -1,6 +1,6 @@
// RUN: %clang -g -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 -fno-limit-debug-info -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %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 -fstandalone-debug -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s
namespace A {
#line 1 "foo.cpp"

View File

@ -1,5 +1,5 @@
// 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.
//CHECK: Lpubtypes_begin[[SECNUM:[0-9]:]]

View File

@ -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: ![[LINE:[0-9]+]] = {{.*}}"TC<int>", {{.*}} metadata !"_ZTS2TCIiE"} ; [ DW_TAG_class_type ]

View File

@ -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 {
template <int i> int add(int j) {

View File

@ -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;
}