summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/MC/MCObjectFileInfo.h5
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp139
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h30
-rw-r--r--llvm/lib/MC/MCObjectFileInfo.cpp13
-rw-r--r--llvm/test/DebugInfo/COFF/inlining.ll160
5 files changed, 342 insertions, 5 deletions
diff --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h
index 8a3a6af3bf7..f8346f22a23 100644
--- a/llvm/include/llvm/MC/MCObjectFileInfo.h
+++ b/llvm/include/llvm/MC/MCObjectFileInfo.h
@@ -127,6 +127,7 @@ protected:
MCSection *DwarfGnuPubTypesSection;
MCSection *COFFDebugSymbolsSection;
+ MCSection *COFFDebugTypesSection;
/// Extra TLS Variable Data section.
///
@@ -274,6 +275,10 @@ public:
MCSection *getCOFFDebugSymbolsSection() const {
return COFFDebugSymbolsSection;
}
+ MCSection *getCOFFDebugTypesSection() const {
+ return COFFDebugTypesSection;
+ }
+
MCSection *getTLSExtraDataSection() const { return TLSExtraDataSection; }
const MCSection *getTLSDataSection() const { return TLSDataSection; }
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index b503f1dc31e..e3c48296f34 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -15,6 +15,8 @@
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/COFF.h"
@@ -87,6 +89,17 @@ unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) {
return Insertion.first->second;
}
+CodeViewDebug::InlineSite &CodeViewDebug::getInlineSite(const DILocation *Loc) {
+ const DILocation *InlinedAt = Loc->getInlinedAt();
+ auto Insertion = CurFn->InlineSites.insert({InlinedAt, InlineSite()});
+ if (Insertion.second) {
+ InlineSite &Site = Insertion.first->second;
+ Site.SiteFuncId = NextFuncId++;
+ Site.Inlinee = Loc->getScope()->getSubprogram();
+ }
+ return Insertion.first->second;
+}
+
void CodeViewDebug::maybeRecordLocation(DebugLoc DL,
const MachineFunction *MF) {
// Skip this instruction if it has the same location as the previous one.
@@ -115,7 +128,28 @@ void CodeViewDebug::maybeRecordLocation(DebugLoc DL,
else
FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile());
CurFn->LastLoc = DL;
- Asm->OutStreamer->EmitCVLocDirective(CurFn->FuncId, FileId, DL.getLine(),
+
+ unsigned FuncId = CurFn->FuncId;
+ if (const DILocation *Loc = DL->getInlinedAt()) {
+ // If this location was actually inlined from somewhere else, give it the ID
+ // of the inline call site.
+ FuncId = getInlineSite(DL.get()).SiteFuncId;
+ // Ensure we have links in the tree of inline call sites.
+ const DILocation *ChildLoc = nullptr;
+ while (Loc->getInlinedAt()) {
+ InlineSite &Site = getInlineSite(Loc);
+ if (ChildLoc) {
+ // Record the child inline site if not already present.
+ auto B = Site.ChildSites.begin(), E = Site.ChildSites.end();
+ if (std::find(B, E, Loc) != E)
+ break;
+ Site.ChildSites.push_back(Loc);
+ }
+ ChildLoc = Loc;
+ }
+ }
+
+ Asm->OutStreamer->EmitCVLocDirective(FuncId, FileId, DL.getLine(),
DL.getCol(), /*PrologueEnd=*/false,
/*IsStmt=*/false, DL->getFilename());
}
@@ -139,6 +173,8 @@ void CodeViewDebug::endModule() {
if (FnDebugInfo.empty())
return;
+ emitTypeInformation();
+
// FIXME: For functions that are comdat, we should emit separate .debug$S
// sections that are comdat associative with the main function instead of
// having one big .debug$S section.
@@ -167,6 +203,60 @@ void CodeViewDebug::endModule() {
clear();
}
+template <typename T> static void emitRecord(MCStreamer &OS, const T &Rec) {
+ OS.EmitBytes(StringRef(reinterpret_cast<const char *>(&Rec), sizeof(Rec)));
+}
+
+void CodeViewDebug::emitTypeInformation() {
+ // Start the .debug$T section with 0x4.
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getCOFFDebugTypesSection());
+ Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC);
+
+ NamedMDNode *CU_Nodes =
+ Asm->MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
+ if (!CU_Nodes)
+ return;
+
+ // This type info currently only holds function ids for use with inline call
+ // frame info. All functions are assigned a simple 'void ()' type. Emit that
+ // type here.
+ TypeIndex ArgListIdx = getNextTypeIndex();
+ Asm->EmitInt16(2 + sizeof(ArgList));
+ Asm->EmitInt16(LF_ARGLIST);
+ Asm->EmitInt32(0);
+
+ TypeIndex VoidProcIdx = getNextTypeIndex();
+ Asm->EmitInt16(2 + sizeof(ProcedureType));
+ Asm->EmitInt16(LF_PROCEDURE);
+ ProcedureType Proc{}; // Zero initialize.
+ Proc.ReturnType = TypeIndex::Void();
+ Proc.CallConv = CallingConvention::NearC;
+ Proc.Options = FunctionOptions::None;
+ Proc.NumParameters = 0;
+ Proc.ArgListType = ArgListIdx;
+ emitRecord(*Asm->OutStreamer, Proc);
+
+ for (MDNode *N : CU_Nodes->operands()) {
+ auto *CUNode = cast<DICompileUnit>(N);
+ for (auto *SP : CUNode->getSubprograms()) {
+ StringRef DisplayName = SP->getDisplayName();
+ Asm->EmitInt16(2 + sizeof(FuncId) + DisplayName.size() + 1);
+ Asm->EmitInt16(LF_FUNC_ID);
+
+ FuncId Func{}; // Zero initialize.
+ Func.ParentScope = TypeIndex();
+ Func.FunctionType = VoidProcIdx;
+ emitRecord(*Asm->OutStreamer, Func);
+ Asm->OutStreamer->EmitBytes(DisplayName);
+ Asm->EmitInt8(0);
+
+ TypeIndex FuncIdIdx = getNextTypeIndex();
+ SubprogramToFuncId.insert(std::make_pair(SP, FuncIdIdx));
+ }
+ }
+}
+
static void EmitLabelDiff(MCStreamer &Streamer,
const MCSymbol *From, const MCSymbol *To,
unsigned int Size = 4) {
@@ -179,6 +269,44 @@ static void EmitLabelDiff(MCStreamer &Streamer,
Streamer.EmitValue(AddrDelta, Size);
}
+void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
+ const DILocation *InlinedAt,
+ const InlineSite &Site) {
+ MCStreamer &OS = *Asm->OutStreamer;
+
+ MCSymbol *InlineBegin = Asm->MMI->getContext().createTempSymbol(),
+ *InlineEnd = Asm->MMI->getContext().createTempSymbol();
+
+ assert(SubprogramToFuncId.count(Site.Inlinee));
+ TypeIndex InlineeIdx = SubprogramToFuncId[Site.Inlinee];
+
+ // SymbolRecord
+ EmitLabelDiff(OS, InlineBegin, InlineEnd, 2); // RecordLength
+ OS.EmitLabel(InlineBegin);
+ Asm->EmitInt16(SymbolRecordKind::S_INLINESITE); // RecordKind
+
+ InlineSiteSym SiteBytes{};
+ SiteBytes.Inlinee = InlineeIdx;
+ Asm->OutStreamer->EmitBytes(
+ StringRef(reinterpret_cast<const char *>(&SiteBytes), sizeof(SiteBytes)));
+
+ // FIXME: annotations
+
+ OS.EmitLabel(InlineEnd);
+
+ // Recurse on child inlined call sites before closing the scope.
+ for (const DILocation *ChildSite : Site.ChildSites) {
+ auto I = FI.InlineSites.find(ChildSite);
+ assert(I != FI.InlineSites.end() &&
+ "child site not in function inline site map");
+ emitInlinedCallSite(FI, ChildSite, I->second);
+ }
+
+ // Close the scope.
+ Asm->EmitInt16(2); // RecordLength
+ Asm->EmitInt16(SymbolRecordKind::S_INLINESITE_END); // RecordKind
+}
+
void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
FunctionInfo &FI) {
// For each function there is a separate subsection
@@ -224,6 +352,15 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
Asm->EmitInt8(0);
Asm->OutStreamer->EmitLabel(ProcSegmentEnd);
+ // Emit inlined call site information. Only emit functions inlined directly
+ // into the parent function. We'll emit the other sites recursively as part
+ // of their parent inline site.
+ for (auto &KV : FI.InlineSites) {
+ const DILocation *InlinedAt = KV.first;
+ if (!InlinedAt->getInlinedAt())
+ emitInlinedCallSite(FI, InlinedAt, KV.second);
+ }
+
// We're done with this function.
Asm->EmitInt16(0x0002);
Asm->EmitInt16(unsigned(SymbolRecordKind::S_PROC_ID_END));
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 77b5ed39c1f..4883905e907 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -22,6 +22,7 @@
#include "llvm/CodeGen/LexicalScopes.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/MC/MCStreamer.h"
@@ -33,19 +34,31 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler {
AsmPrinter *Asm;
DebugLoc PrevInstLoc;
+ struct InlineSite {
+ TinyPtrVector<const DILocation *> ChildSites;
+ const DISubprogram *Inlinee = nullptr;
+ unsigned SiteFuncId = 0;
+ };
+
// For each function, store a vector of labels to its instructions, as well as
// to the end of the function.
struct FunctionInfo {
+ /// Map from inlined call site to inlined instructions and child inlined
+ /// call sites. Listed in program order.
+ MapVector<const DILocation *, InlineSite> InlineSites;
+
DebugLoc LastLoc;
MCSymbol *End = nullptr;
unsigned FuncId = 0;
- unsigned LastFileId;
+ unsigned LastFileId = 0;
bool HaveLineInfo = false;
};
FunctionInfo *CurFn;
unsigned NextFuncId = 0;
+ InlineSite &getInlineSite(const DILocation *Loc);
+
/// Remember some debug info about each function. Keep it in a stable order to
/// emit at the end of the TU.
MapVector<const Function *, FunctionInfo> FnDebugInfo;
@@ -53,6 +66,16 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler {
/// Map from DIFile to .cv_file id.
DenseMap<const DIFile *, unsigned> FileIdMap;
+ DenseMap<const DISubprogram *, codeview::TypeIndex> SubprogramToFuncId;
+
+ unsigned TypeCount = 0;
+
+ /// Gets the next type index and increments the count of types streamed so
+ /// far.
+ codeview::TypeIndex getNextTypeIndex() {
+ return codeview::TypeIndex(codeview::TypeIndex::FirstNonSimpleIndex + TypeCount++);
+ }
+
typedef std::map<const DIFile *, std::string> FileToFilepathMapTy;
FileToFilepathMapTy FileToFilepathMap;
StringRef getFullFilepath(const DIFile *S);
@@ -68,8 +91,13 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler {
FileToFilepathMap.clear();
}
+ void emitTypeInformation();
+
void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI);
+ void emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt,
+ const InlineSite &Site);
+
public:
CodeViewDebug(AsmPrinter *Asm);
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 0c86fa81c1b..05eadeb44a5 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -191,6 +191,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) {
SectionKind::getReadOnlyWithRel());
COFFDebugSymbolsSection = nullptr;
+ COFFDebugTypesSection = nullptr;
if (useCompactUnwind(T)) {
CompactUnwindSection =
@@ -484,6 +485,7 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) {
ELF::SHF_ALLOC);
COFFDebugSymbolsSection = nullptr;
+ COFFDebugTypesSection = nullptr;
// Debug Info Sections.
DwarfAbbrevSection = Ctx->getELFSection(".debug_abbrev", ELF::SHT_PROGBITS, 0,
@@ -623,9 +625,14 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(Triple T) {
// Debug info.
COFFDebugSymbolsSection =
- Ctx->getCOFFSection(".debug$S", COFF::IMAGE_SCN_MEM_DISCARDABLE |
- COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
+ Ctx->getCOFFSection(".debug$S", (COFF::IMAGE_SCN_MEM_DISCARDABLE |
+ COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ),
+ SectionKind::getMetadata());
+ COFFDebugTypesSection =
+ Ctx->getCOFFSection(".debug$T", (COFF::IMAGE_SCN_MEM_DISCARDABLE |
+ COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ),
SectionKind::getMetadata());
DwarfAbbrevSection = Ctx->getCOFFSection(
diff --git a/llvm/test/DebugInfo/COFF/inlining.ll b/llvm/test/DebugInfo/COFF/inlining.ll
new file mode 100644
index 00000000000..08e26c789a2
--- /dev/null
+++ b/llvm/test/DebugInfo/COFF/inlining.ll
@@ -0,0 +1,160 @@
+; RUN: llc -mcpu=core2 -mtriple=i686-pc-win32 < %s | FileCheck %s --check-prefix=ASM
+; RUN: llc -mcpu=core2 -mtriple=i686-pc-win32 < %s -filetype=obj | llvm-readobj -codeview | FileCheck %s --check-prefix=OBJ
+
+; This LL file was generated by running 'clang -O1 -g -gcodeview' on the
+; following code:
+; 1: extern volatile int x;
+; 2: static inline void foo() {
+; 3: int y = 1;
+; 4: x += (int)&y;
+; 5: x += 2;
+; 6: x += 3;
+; 7: }
+; 8: static inline void bar() {
+; 9: x += 4;
+; 10: foo();
+; 11: x += 5;
+; 12: }
+; 13: void baz() {
+; 14: x += 6;
+; 15: bar();
+; 16: x += 7;
+; 17: }
+
+; ASM: .cv_loc 0 1 13 0 is_stmt 0 # t.cpp:13:0
+; ASM: .cv_loc 0 1 14 5 # t.cpp:14:5
+; ASM: addl $6, "?x@@3HC"
+; ASM: .cv_loc 1 1 9 5 # t.cpp:9:5
+; ASM: addl $4, "?x@@3HC"
+; ASM: .cv_loc 2 1 3 7 # t.cpp:3:7
+; ASM: .cv_loc 2 1 4 5 # t.cpp:4:5
+; ASM: addl {{.*}}, "?x@@3HC"
+; ASM: .cv_loc 2 1 5 5 # t.cpp:5:5
+; ASM: addl $2, "?x@@3HC"
+; ASM: .cv_loc 2 1 6 5 # t.cpp:6:5
+; ASM: addl $3, "?x@@3HC"
+; ASM: .cv_loc 1 1 11 5 # t.cpp:11:5
+; ASM: addl $5, "?x@@3HC"
+; ASM: .cv_loc 0 1 16 5 # t.cpp:16:5
+; ASM: addl $7, "?x@@3HC"
+; ASM: .cv_loc 0 1 17 1 # t.cpp:17:1
+
+; OBJ: ProcStart {
+; OBJ: PtrParent: 0x0
+; OBJ: PtrEnd: 0x0
+; OBJ: PtrNext: 0x0
+; OBJ: CodeSize: 0x3D
+; OBJ: DbgStart: 0x0
+; OBJ: DbgEnd: 0x0
+; OBJ: FunctionType: 0x0
+; OBJ: CodeOffset: ?baz@@YAXXZ+0x0
+; OBJ: Segment: 0x0
+; OBJ: Flags [ (0x0)
+; OBJ: ]
+; OBJ: DisplayName: baz
+; OBJ: LinkageName: ?baz@@YAXXZ
+; OBJ: }
+; OBJ: InlineSite {
+; OBJ: PtrParent: 0x0
+; OBJ: PtrEnd: 0x0
+; OBJ: Inlinee: bar (0x1003)
+; OBJ: BinaryAnnotations [
+; OBJ: ]
+; OBJ: }
+; OBJ: InlineSite {
+; OBJ: PtrParent: 0x0
+; OBJ: PtrEnd: 0x0
+; OBJ: Inlinee: foo (0x1004)
+; OBJ: BinaryAnnotations [
+; OBJ: ]
+; OBJ: }
+; OBJ: InlineSiteEnd {
+; OBJ: }
+; OBJ: InlineSiteEnd {
+; OBJ: }
+; OBJ: ProcEnd
+
+; ModuleID = 't.cpp'
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc18.0.0"
+
+@"\01?x@@3HC" = external global i32, align 4
+
+; Function Attrs: norecurse nounwind uwtable
+define void @"\01?baz@@YAXXZ"() #0 !dbg !4 {
+entry:
+ %y.i.i = alloca i32, align 4
+ %0 = load volatile i32, i32* @"\01?x@@3HC", align 4, !dbg !12, !tbaa !13
+ %add = add nsw i32 %0, 6, !dbg !12
+ store volatile i32 %add, i32* @"\01?x@@3HC", align 4, !dbg !12, !tbaa !13
+ %1 = load volatile i32, i32* @"\01?x@@3HC", align 4, !dbg !17, !tbaa !13
+ %add.i = add nsw i32 %1, 4, !dbg !17
+ store volatile i32 %add.i, i32* @"\01?x@@3HC", align 4, !dbg !17, !tbaa !13
+ %2 = bitcast i32* %y.i.i to i8*, !dbg !19
+ call void @llvm.lifetime.start(i64 4, i8* %2) #2, !dbg !19
+ store i32 1, i32* %y.i.i, align 4, !dbg !21, !tbaa !13
+ %3 = ptrtoint i32* %y.i.i to i64, !dbg !22
+ %4 = trunc i64 %3 to i32, !dbg !22
+ %5 = load volatile i32, i32* @"\01?x@@3HC", align 4, !dbg !23, !tbaa !13
+ %add.i.i = add nsw i32 %5, %4, !dbg !23
+ store volatile i32 %add.i.i, i32* @"\01?x@@3HC", align 4, !dbg !23, !tbaa !13
+ %6 = load volatile i32, i32* @"\01?x@@3HC", align 4, !dbg !24, !tbaa !13
+ %add1.i.i = add nsw i32 %6, 2, !dbg !24
+ store volatile i32 %add1.i.i, i32* @"\01?x@@3HC", align 4, !dbg !24, !tbaa !13
+ %7 = load volatile i32, i32* @"\01?x@@3HC", align 4, !dbg !25, !tbaa !13
+ %add2.i.i = add nsw i32 %7, 3, !dbg !25
+ store volatile i32 %add2.i.i, i32* @"\01?x@@3HC", align 4, !dbg !25, !tbaa !13
+ call void @llvm.lifetime.end(i64 4, i8* %2) #2, !dbg !26
+ %8 = load volatile i32, i32* @"\01?x@@3HC", align 4, !dbg !27, !tbaa !13
+ %add1.i = add nsw i32 %8, 5, !dbg !27
+ store volatile i32 %add1.i, i32* @"\01?x@@3HC", align 4, !dbg !27, !tbaa !13
+ %9 = load volatile i32, i32* @"\01?x@@3HC", align 4, !dbg !28, !tbaa !13
+ %add1 = add nsw i32 %9, 7, !dbg !28
+ store volatile i32 %add1, i32* @"\01?x@@3HC", align 4, !dbg !28, !tbaa !13
+ ret void, !dbg !29
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start(i64, i8* nocapture) #1
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end(i64, i8* nocapture) #1
+
+attributes #0 = { norecurse nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind }
+attributes #2 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!8, !9, !10}
+!llvm.ident = !{!11}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: 2, enums: !2, subprograms: !3)
+!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
+!2 = !{}
+!3 = !{!4, !6, !7}
+!4 = distinct !DISubprogram(name: "baz", scope: !1, file: !1, line: 13, type: !5, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: true, variables: !2)
+!5 = !DISubroutineType(types: !2)
+!6 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 8, type: !5, isLocal: true, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, variables: !2)
+!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !5, isLocal: true, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, variables: !2)
+!8 = !{i32 2, !"CodeView", i32 1}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!10 = !{i32 1, !"PIC Level", i32 2}
+!11 = !{!"clang version 3.9.0 "}
+!12 = !DILocation(line: 14, column: 5, scope: !4)
+!13 = !{!14, !14, i64 0}
+!14 = !{!"int", !15, i64 0}
+!15 = !{!"omnipotent char", !16, i64 0}
+!16 = !{!"Simple C/C++ TBAA"}
+!17 = !DILocation(line: 9, column: 5, scope: !6, inlinedAt: !18)
+!18 = distinct !DILocation(line: 15, column: 3, scope: !4)
+!19 = !DILocation(line: 3, column: 3, scope: !7, inlinedAt: !20)
+!20 = distinct !DILocation(line: 10, column: 3, scope: !6, inlinedAt: !18)
+!21 = !DILocation(line: 3, column: 7, scope: !7, inlinedAt: !20)
+!22 = !DILocation(line: 4, column: 8, scope: !7, inlinedAt: !20)
+!23 = !DILocation(line: 4, column: 5, scope: !7, inlinedAt: !20)
+!24 = !DILocation(line: 5, column: 5, scope: !7, inlinedAt: !20)
+!25 = !DILocation(line: 6, column: 5, scope: !7, inlinedAt: !20)
+!26 = !DILocation(line: 7, column: 1, scope: !7, inlinedAt: !20)
+!27 = !DILocation(line: 11, column: 5, scope: !6, inlinedAt: !18)
+!28 = !DILocation(line: 16, column: 5, scope: !4)
+!29 = !DILocation(line: 17, column: 1, scope: !4)
OpenPOWER on IntegriCloud