def gused : Flag<"-gused">, Group<g_Group>;
def g_Flag : Flag<"-g">, Group<g_Group>, HelpText<"Generate source level debug information">,
Flags<[CC1Option]>;
+def gline_tables_only : Flag<"-gline-tables-only">, Group<g_Group>,
+ HelpText<"Emit debug line number tables only">, Flags<[CC1Option]>;
def headerpad__max__install__names : Joined<"-headerpad_max_install_names">;
def help : Flag<"-help">, Flags<[CC1Option]>,
HelpText<"Display available options">;
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.
const VarDecl *variable = ci->getVariable();
DI->EmitLocation(Builder, variable->getLocation());
- const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
- if (capture.isConstant()) {
- DI->EmitDeclareOfAutoVariable(variable, LocalDeclMap[variable],
- Builder);
- continue;
- }
+ if (CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo) {
+ const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
+ if (capture.isConstant()) {
+ DI->EmitDeclareOfAutoVariable(variable, LocalDeclMap[variable],
+ Builder);
+ continue;
+ }
- DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointer,
- Builder, blockInfo);
+ DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointer,
+ Builder, blockInfo);
+ }
}
}
/// getOrCreateRecordType - Emit record type's standalone debug info.
llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
SourceLocation Loc) {
+ assert(CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo);
llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc));
return T;
}
/// debug info.
llvm::DIType CGDebugInfo::getOrCreateInterfaceType(QualType D,
SourceLocation Loc) {
+ assert(CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo);
llvm::DIType T = getOrCreateType(D, getOrCreateFile(Loc));
DBuilder.retainType(T);
return T;
LinkageName = CGM.getMangledName(GD);
Flags |= llvm::DIDescriptor::FlagPrototyped;
}
- if (LinkageName == Name)
+ if (LinkageName == Name ||
+ CGM.getCodeGenOpts().DebugInfo <= CodeGenOptions::DebugLineTablesOnly)
LinkageName = StringRef();
- if (const NamespaceDecl *NSDecl =
- dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
- FDContext = getOrCreateNameSpace(NSDecl);
- else if (const RecordDecl *RDecl =
- dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))
- FDContext = getContextDescriptor(cast<Decl>(RDecl->getDeclContext()));
+ if (CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo) {
+ if (const NamespaceDecl *NSDecl =
+ dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
+ FDContext = getOrCreateNameSpace(NSDecl);
+ else if (const RecordDecl *RDecl =
+ dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))
+ FDContext = getContextDescriptor(cast<Decl>(RDecl->getDeclContext()));
- // Collect template parameters.
- TParamsArray = CollectFunctionTemplateParams(FD, Unit);
+ // Collect template parameters.
+ TParamsArray = CollectFunctionTemplateParams(FD, Unit);
+ }
} else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
Name = getObjCMethodName(OMD);
Flags |= llvm::DIDescriptor::FlagPrototyped;
if (D->isImplicit())
Flags |= llvm::DIDescriptor::FlagArtificial;
- llvm::DISubprogram SPDecl = getFunctionDeclaration(D);
- llvm::DISubprogram SP =
- DBuilder.createFunction(FDContext, Name, LinkageName, Unit,
- LineNo, getOrCreateFunctionType(D, FnType, Unit),
- Fn->hasInternalLinkage(), true/*definition*/,
- getLineNumber(CurLoc),
- Flags, CGM.getLangOpts().Optimize, Fn,
- TParamsArray, SPDecl);
+ llvm::DIType DIFnType;
+ llvm::DISubprogram SPDecl;
+ if (CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo) {
+ DIFnType = getOrCreateFunctionType(D, FnType, Unit);
+ SPDecl = getFunctionDeclaration(D);
+ } else {
+ // Create fake but valid subroutine type. Otherwise
+ // llvm::DISubprogram::Verify() would return false, and
+ // subprogram DIE will miss DW_AT_decl_file and
+ // DW_AT_decl_line fields.
+ SmallVector<llvm::Value*, 16> Elts;
+ llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
+ DIFnType = DBuilder.createSubroutineType(Unit, EltTypeArray);
+ }
+ llvm::DISubprogram SP;
+ SP = DBuilder.createFunction(FDContext, Name, LinkageName, Unit,
+ LineNo, DIFnType,
+ Fn->hasInternalLinkage(), true/*definition*/,
+ getLineNumber(CurLoc), Flags,
+ CGM.getLangOpts().Optimize,
+ Fn, TParamsArray, SPDecl);
// Push function on region stack.
llvm::MDNode *SPN = SP;
void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
llvm::Value *Storage,
unsigned ArgNo, CGBuilderTy &Builder) {
+ assert(CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo);
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
llvm::Value *Storage,
CGBuilderTy &Builder) {
+ assert(CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo);
EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder);
}
void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
const VarDecl *VD, llvm::Value *Storage, CGBuilderTy &Builder,
const CGBlockInfo &blockInfo) {
+ assert(CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo);
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
if (Builder.GetInsertBlock() == 0)
void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
unsigned ArgNo,
CGBuilderTy &Builder) {
+ assert(CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo);
EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, ArgNo, Builder);
}
void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::Value *addr,
CGBuilderTy &Builder) {
+ assert(CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo);
ASTContext &C = CGM.getContext();
const BlockDecl *blockDecl = block.getBlockDecl();
/// EmitGlobalVariable - Emit information about a global variable.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
const VarDecl *D) {
+ assert(CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo);
// Create global variable debug descriptor.
llvm::DIFile Unit = getOrCreateFile(D->getLocation());
unsigned LineNo = getLineNumber(D->getLocation());
/// EmitGlobalVariable - Emit information about an objective-c interface.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
ObjCInterfaceDecl *ID) {
+ assert(CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo);
// Create global variable debug descriptor.
llvm::DIFile Unit = getOrCreateFile(ID->getLocation());
unsigned LineNo = getLineNumber(ID->getLocation());
/// EmitGlobalVariable - Emit global variable's debug info.
void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
llvm::Constant *Init) {
+ assert(CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo);
// Create the descriptor for the variable.
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
StringRef Name = VD->getName();
// Emit global variable debug descriptor for static vars.
CGDebugInfo *DI = getDebugInfo();
- if (DI) {
+ if (DI &&
+ CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo) {
DI->setLocation(D.getLocation());
DI->EmitGlobalVariable(var, &D);
}
// Emit debug info for local var declaration.
if (HaveInsertPoint())
if (CGDebugInfo *DI = getDebugInfo()) {
- DI->setLocation(D.getLocation());
- if (Target.useGlobalsForAutomaticVariables()) {
- DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(DeclPtr), &D);
- } else
- DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder);
+ if (CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo) {
+ DI->setLocation(D.getLocation());
+ if (Target.useGlobalsForAutomaticVariables()) {
+ DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(DeclPtr),
+ &D);
+ } else
+ DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder);
+ }
}
if (D.hasAttr<AnnotateAttr>())
LocalDeclMap[&D] = Arg;
if (CGDebugInfo *DI = getDebugInfo()) {
- DI->setLocation(D.getLocation());
- DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, Arg, Builder);
+ if (CGM.getCodeGenOpts().DebugInfo >=
+ CodeGenOptions::LimitedDebugInfo) {
+ DI->setLocation(D.getLocation());
+ DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, Arg, Builder);
+ }
}
return;
DMEntry = DeclPtr;
// Emit debug info for param declaration.
- if (CGDebugInfo *DI = getDebugInfo())
- DI->EmitDeclareOfArgVariable(&D, DeclPtr, ArgNo, Builder);
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ if (CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo) {
+ DI->EmitDeclareOfArgVariable(&D, DeclPtr, ArgNo, Builder);
+ }
+ }
if (D.hasAttr<AnnotateAttr>())
EmitVarAnnotations(&D, DeclPtr);
llvm::Constant *Init) {
assert (Init && "Invalid DeclRefExpr initializer!");
if (CGDebugInfo *Dbg = getDebugInfo())
- Dbg->EmitGlobalVariable(E->getDecl(), Init);
+ if (CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo)
+ Dbg->EmitGlobalVariable(E->getDecl(), Init);
}
CodeGenFunction::PeepholeProtection
// Emit global variable debug information.
if (CGDebugInfo *DI = getModuleDebugInfo())
- DI->EmitGlobalVariable(GV, D);
+ if (getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo)
+ DI->EmitGlobalVariable(GV, D);
}
llvm::GlobalValue::LinkageTypes
if (!A->getOption().matches(options::OPT_g0)) {
CmdArgs.push_back("-g");
}
+ if (Args.hasArg(options::OPT_gline_tables_only))
+ CmdArgs.push_back("-gline-tables-only");
Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections);
Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections);
switch (Opts.DebugInfo) {
case CodeGenOptions::NoDebugInfo:
break;
+ case CodeGenOptions::DebugLineTablesOnly:
+ Res.push_back("-gline-tables-only");
+ break;
case CodeGenOptions::LimitedDebugInfo:
Res.push_back("-g");
Res.push_back("-flimit-debug-info");
Opts.Inlining = Args.hasArg(OPT_fno_inline_functions) ?
CodeGenOptions::OnlyAlwaysInlining : Opts.Inlining;
- if (Args.hasArg(OPT_g_Flag)) {
+ if (Args.hasArg(OPT_gline_tables_only)) {
+ Opts.DebugInfo = CodeGenOptions::DebugLineTablesOnly;
+ } else if (Args.hasArg(OPT_g_Flag)) {
if (Args.hasFlag(OPT_flimit_debug_info, OPT_fno_limit_debug_info, true))
Opts.DebugInfo = CodeGenOptions::LimitedDebugInfo;
else
--- /dev/null
+// RUN: %clang_cc1 %s -gline-tables-only -S -emit-llvm -o - | FileCheck %s
+// Checks that clang with "-gline-tables-only" doesn't emit debug info
+// for variables and types.
+
+// CHECK-NOT: DW_TAG_variable
+int global = 42;
+
+// CHECK-NOT: DW_TAG_typedef
+// CHECK-NOT: DW_TAG_const_type
+// CHECK-NOT: DW_TAG_pointer_type
+// CHECK-NOT: DW_TAG_array_type
+typedef const char* constCharPtrArray[10];
+
+// CHECK-NOT: DW_TAG_structure_type
+struct S {
+ // CHECK-NOT: DW_TAG_member
+ char a;
+ double b;
+ constCharPtrArray c;
+};
+
+// CHECK-NOT: DW_TAG_enumerator
+// CHECK-NOT: DW_TAG_enumeration_type
+enum E { ZERO = 0, ONE = 1 };
+
+// CHECK-NOT: DW_TAG_arg_variable
+int sum(int p, int q) {
+ // CHECK-NOT: DW_TAG_auto_variable
+ int r = p + q;
+ struct S s;
+ enum E e;
+ return r;
+}
--- /dev/null
+// RUN: %clang_cc1 %s -gline-tables-only -S -emit-llvm -o - | FileCheck %s
+// Checks that clang with "-gline-tables-only" emits metadata for
+// compile unit, subprogram and file.
+
+int main() {
+ // CHECK: ret i32 0, !dbg
+ return 0;
+}
+
+// CHECK: !llvm.dbg.cu = !{!0}
+// CHECK: DW_TAG_compile_unit
+// CHECK: {{.*main.* DW_TAG_subprogram}}
+// CHECK: DW_TAG_file_type
--- /dev/null
+// RUN: %clang_cc1 %s -O0 -gline-tables-only -S -emit-llvm -o - | FileCheck %s
+// Checks that clang with "-gline-tables-only" doesn't emit debug info
+// for variables and types.
+
+// CHECK-NOT: DW_TAG_namespace
+namespace NS {
+// CHECK-NOT: DW_TAG_class_type
+// CHECK-NOT: DW_TAG_friend
+class C { friend class D; };
+class D {};
+// CHECK-NOT: DW_TAG_inheritance
+class E : public C {
+ // CHECK-NOT: DW_TAG_reference type
+ void x(const D& d);
+};
+}
+
+// CHECK-NOT: DW_TAG_variable
+NS::C c;
+NS::D d;
+NS::E e;
// RUN: %clang -### -c -ganything %s 2>&1 | FileCheck -check-prefix=GANY %s
// RUN: %clang -### -c -ggdb %s 2>&1 | FileCheck -check-prefix=GGDB %s
// RUN: %clang -### -c -gfoo %s 2>&1 | FileCheck -check-prefix=GFOO %s
+// RUN: %clang -### -c -gline-tables-only %s 2>&1 \
+// RUN: | FileCheck -check-prefix=GLTO %s
//
// G: "-cc1"
// G: "-g"
//
// GFOO: "-cc1"
// GFOO-NOT: "-g"
+//
+// GLTO: "-cc1"
+// GLTO: "-g"