Index: include/llvm/CodeGen/DIE.h =================================================================== --- include/llvm/CodeGen/DIE.h +++ include/llvm/CodeGen/DIE.h @@ -185,6 +185,23 @@ Children.push_back(std::move(Child)); } + /// collapseChild - Add Child's children to Child's parent DIE, + /// and remove Child DIE. + /// + void collapseChild(DIE* Child) { + assert(Child->getParent() == this); + for (auto &Grandchild : Child->Children) { + Grandchild->Parent = nullptr; + addChild(std::move(Grandchild)); + } + Child->Parent = nullptr; + Children.erase(std::remove_if(Children.begin(), Children.end(), + [Child](std::unique_ptr &I) { return I.get() == Child; })); + + if (Children.empty()) + Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_no); + } + /// findAttribute - Find a value in the DIE with the attribute given, /// returns NULL if no such attribute exists. DIEValue *findAttribute(dwarf::Attribute Attribute) const; Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -344,16 +344,12 @@ constructImportedEntityDIE(cast(E.second))); } - // If there are only other scopes as children, put them directly in the - // parent instead, as this scope would serve no purpose. - if (Children.size() == ChildScopeCount) { - FinalChildren.insert(FinalChildren.end(), - std::make_move_iterator(Children.begin()), - std::make_move_iterator(Children.end())); - return; - } + // We create DIE for all debug info lexical scopes. Latter, + // lexical scope that has only other scopes as children will collapsed. ScopeDIE = constructLexicalScopeDIE(Scope); assert(ScopeDIE && "Scope DIE should not be null."); + // Add DIE lexical scope to scope map. + insertDIE(Scope->getScopeNode(), ScopeDIE.get()); } // Add children Index: lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.h +++ lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -360,6 +360,10 @@ void finishSubprogramDefinitions(); + /// \brief Collapse all lexical scope DIEs that have only other scope DIEs + /// as their children. + void finalizeLexicalScopeDefinitions(); + /// \brief Finish off debug information after all functions have been /// processed. void finalizeModuleInfo(); Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -455,8 +455,14 @@ // within the same scope, e.g. { namespace A = base; namespace B = A; } std::stable_sort(ScopesWithImportedEntities.begin(), ScopesWithImportedEntities.end(), less_first()); - for (auto *GV : CUNode->getGlobalVariables()) - CU.getOrCreateGlobalVariableDIE(GV); + for (auto *GV : CUNode->getGlobalVariables()) { + auto GVContext = GV->getScope(); + + // Skip, variables defined in a lexical block (e.g. static variables). We + // will revisit these variables after all lexical scope DIEs are created. + if (!GVContext || !DILexicalBlock::classof(GVContext)) + CU.getOrCreateGlobalVariableDIE(GV); + } for (auto *SP : CUNode->getSubprograms()) SPMap.insert(std::make_pair(SP, &CU)); for (auto *Ty : CUNode->getEnumTypes()) { @@ -526,9 +532,53 @@ } } +void DwarfDebug::finalizeLexicalScopeDefinitions() { + std::vector Dies; + for (const auto &P : CUMap) { + DwarfCompileUnit* TheU = P.second; + Dies.push_back(&TheU->getUnitDie()); + if (auto *Skeleton = TheU->getSkeleton()) + Dies.push_back(&Skeleton->getUnitDie()); + } + + while (!Dies.empty()) { + DIE* Die = Dies.back(); + Dies.pop_back(); + + // If there are only other scopes as children, put them directly in the + // parent instead, as this scope would serve no purpose. + bool Skip = Die->getAbbrev().getTag() == dwarf::DW_TAG_lexical_block; + for (auto &Child : Die->getChildren()) { + Dies.push_back(&*Child); + Skip &= (Child->getAbbrev().getTag() == dwarf::DW_TAG_lexical_block || + Child->getAbbrev().getTag() == dwarf::DW_TAG_inlined_subroutine); + } + + if (Skip) + Die->getParent()->collapseChild(Die); + } +} + void DwarfDebug::finalizeModuleInfo() { const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + // Now, after we generated all lexical scope DIEs, it is time to + // run over variables defined in a lexical scope and collect them. + const Module *M = MMI->getModule(); + if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) { + for (MDNode *N : CU_Nodes->operands()) { + auto *TheCU = cast(N); + DwarfCompileUnit *SPCU = + static_cast(CUMap.lookup(TheCU)); + for (auto *GV : TheCU->getGlobalVariables()) { + auto GVContext = GV->getScope(); + + if (GVContext && DILexicalBlock::classof(GVContext)) + SPCU->getOrCreateGlobalVariableDIE(GV); + } + } + } + finishSubprogramDefinitions(); finishVariableDefinitions(); @@ -536,6 +586,8 @@ // Collect info for variables that were optimized out. collectDeadVariables(); + finalizeLexicalScopeDefinitions(); + // Handle anything that needs to be done on a per-unit basis after // all other generation. for (const auto &P : CUMap) { Index: test/DebugInfo/LB-class.ll =================================================================== --- test/DebugInfo/LB-class.ll +++ test/DebugInfo/LB-class.ll @@ -0,0 +1,162 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj -O0 < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s + +;; This test was generated by running following command: +;; clang -cc1 -O0 -g -emit-llvm class.cpp +;; Where class.cpp: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;int foo(int x) { +;; if(x) { +;; class X { +;; public: +;; char z; +;; X(int y) : z(y) {} +;; }; +;; { +;; X a(x); +;; return a.z; +;; } +;; } +;; return 0; +;;} +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +; CHECK: DW_TAG_subprogram +; CHECK-NOT: DW_TAG +; CHECK: DW_AT_name {{.*}} "foo" +; CHECK-NOT: NULL +; CHECK: DW_TAG_lexical_block +; CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] +; CHECK-NEXT: DW_AT_high_pc [DW_FORM_{{.*}}] +; CHECK-NOT: {{DW_|NULL}} +; CHECK: DW_TAG_lexical_block +; CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] +; CHECK-NEXT: DW_AT_high_pc [DW_FORM_{{.*}}] +; CHECK-NOT: {{DW_|NULL}} +; CHECK: DW_TAG_variable +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_name {{.*}} "a" +; CHECK: NULL +; CHECK-NOT: {{DW_|NULL}} +; CHECK: DW_TAG_class +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_name {{.*}} "X" + +%class.X = type { i8 } + +; Function Attrs: nounwind +define i32 @_Z3fooi(i32 %x) #0 { +entry: + %retval = alloca i32, align 4 + %x.addr = alloca i32, align 4 + %a = alloca %class.X, align 1 + store i32 %x, i32* %x.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !23, metadata !24), !dbg !25 + %0 = load i32, i32* %x.addr, align 4, !dbg !26 + %tobool = icmp ne i32 %0, 0, !dbg !26 + br i1 %tobool, label %if.then, label %if.end, !dbg !27 + +if.then: ; preds = %entry + call void @llvm.dbg.declare(metadata %class.X* %a, metadata !28, metadata !24), !dbg !30 + %1 = load i32, i32* %x.addr, align 4, !dbg !30 + call void @_ZZ3fooiEN1XC1Ei(%class.X* %a, i32 %1), !dbg !30 + %z = getelementptr inbounds %class.X, %class.X* %a, i32 0, i32 0, !dbg !31 + %2 = load i8, i8* %z, align 1, !dbg !31 + %conv = sext i8 %2 to i32, !dbg !31 + store i32 %conv, i32* %retval, !dbg !31 + br label %return, !dbg !31 + +if.end: ; preds = %entry + store i32 0, i32* %retval, !dbg !32 + br label %return, !dbg !32 + +return: ; preds = %if.end, %if.then + %3 = load i32, i32* %retval, !dbg !33 + ret i32 %3, !dbg !33 +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: nounwind +define internal void @_ZZ3fooiEN1XC1Ei(%class.X* %this, i32 %y) unnamed_addr #0 align 2 { +entry: + %this.addr = alloca %class.X*, align 8 + %y.addr = alloca i32, align 4 + store %class.X* %this, %class.X** %this.addr, align 8 + call void @llvm.dbg.declare(metadata %class.X** %this.addr, metadata !34, metadata !24), !dbg !36 + store i32 %y, i32* %y.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %y.addr, metadata !37, metadata !24), !dbg !38 + %this1 = load %class.X*, %class.X** %this.addr + %0 = load i32, i32* %y.addr, align 4, !dbg !38 + call void @_ZZ3fooiEN1XC2Ei(%class.X* %this1, i32 %0), !dbg !38 + ret void, !dbg !38 +} + +; Function Attrs: nounwind +define internal void @_ZZ3fooiEN1XC2Ei(%class.X* %this, i32 %y) unnamed_addr #0 align 2 { +entry: + %this.addr = alloca %class.X*, align 8 + %y.addr = alloca i32, align 4 + store %class.X* %this, %class.X** %this.addr, align 8 + call void @llvm.dbg.declare(metadata %class.X** %this.addr, metadata !39, metadata !24), !dbg !40 + store i32 %y, i32* %y.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %y.addr, metadata !41, metadata !24), !dbg !42 + %this1 = load %class.X*, %class.X** %this.addr + %z = getelementptr inbounds %class.X, %class.X* %this1, i32 0, i32 0, !dbg !42 + %0 = load i32, i32* %y.addr, align 4, !dbg !42 + %conv = trunc i32 %0 to i8, !dbg !42 + store i8 %conv, i8* %z, align 1, !dbg !42 + ret void, !dbg !42 +} + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!20, !21} +!llvm.ident = !{!22} + +!0 = !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.7.0 (trunk 236102)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !2, subprograms: !3, globals: !2, imports: !2) +!1 = !DIFile(filename: "class.cpp", directory: "/") +!2 = !{} +!3 = !{!4, !8, !19} +!4 = !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, function: i32 (i32)* @_Z3fooi, variables: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{!7, !7} +!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!8 = !DISubprogram(name: "X", linkageName: "_ZZ3fooiEN1XC1Ei", scope: !9, file: !1, line: 6, type: !16, isLocal: true, isDefinition: true, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: false, function: void (%class.X*, i32)* @_ZZ3fooiEN1XC1Ei, declaration: !15, variables: !2) +!9 = !DICompositeType(tag: DW_TAG_class_type, name: "X", scope: !10, file: !1, line: 3, size: 8, align: 8, elements: !12) +!10 = distinct !DILexicalBlock(scope: !11, file: !1, line: 2) +!11 = distinct !DILexicalBlock(scope: !4, file: !1, line: 2) +!12 = !{!13, !15} +!13 = !DIDerivedType(tag: DW_TAG_member, name: "z", scope: !9, file: !1, line: 5, baseType: !14, size: 8, align: 8, flags: DIFlagPublic) +!14 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) +!15 = !DISubprogram(name: "X", scope: !9, file: !1, line: 6, type: !16, isLocal: false, isDefinition: false, scopeLine: 6, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: false) +!16 = !DISubroutineType(types: !17) +!17 = !{null, !18, !7} +!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!19 = !DISubprogram(name: "X", linkageName: "_ZZ3fooiEN1XC2Ei", scope: !9, file: !1, line: 6, type: !16, isLocal: true, isDefinition: true, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: false, function: void (%class.X*, i32)* @_ZZ3fooiEN1XC2Ei, declaration: !15, variables: !2) +!20 = !{i32 2, !"Dwarf Version", i32 4} +!21 = !{i32 2, !"Debug Info Version", i32 3} +!22 = !{!"clang version 3.7.0 (trunk 236102)"} +!23 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "x", arg: 1, scope: !4, file: !1, line: 1, type: !7) +!24 = !DIExpression() +!25 = !DILocation(line: 1, scope: !4) +!26 = !DILocation(line: 2, scope: !11) +!27 = !DILocation(line: 2, scope: !4) +!28 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "a", scope: !29, file: !1, line: 9, type: !9) +!29 = distinct !DILexicalBlock(scope: !10, file: !1, line: 8) +!30 = !DILocation(line: 9, scope: !29) +!31 = !DILocation(line: 10, scope: !29) +!32 = !DILocation(line: 13, scope: !4) +!33 = !DILocation(line: 14, scope: !4) +!34 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this", arg: 1, scope: !8, type: !35, flags: DIFlagArtificial | DIFlagObjectPointer) +!35 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64, align: 64) +!36 = !DILocation(line: 0, scope: !8) +!37 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "y", arg: 2, scope: !8, file: !1, line: 6, type: !7) +!38 = !DILocation(line: 6, scope: !8) +!39 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this", arg: 1, scope: !19, type: !35, flags: DIFlagArtificial | DIFlagObjectPointer) +!40 = !DILocation(line: 0, scope: !19) +!41 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "y", arg: 2, scope: !19, file: !1, line: 6, type: !7) +!42 = !DILocation(line: 6, scope: !19) Index: test/DebugInfo/LB-static.ll =================================================================== --- test/DebugInfo/LB-static.ll +++ test/DebugInfo/LB-static.ll @@ -0,0 +1,110 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj -O0 < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s + +;; This test was generated by running following command: +;; clang -cc1 -O0 -g -emit-llvm static.cpp +;; Where static.cpp: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;int foo(int x) { +;; if(x) { +;; static int bar = 0; +;; { +;; int a = bar++; +;; return a; +;; } +;; } +;; return 0; +;;} +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +; CHECK: DW_TAG_subprogram +; CHECK-NOT: DW_TAG +; CHECK: DW_AT_name {{.*}} "foo" +; CHECK-NOT: NULL +; CHECK: DW_TAG_lexical_block +; CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] +; CHECK-NEXT: DW_AT_high_pc [DW_FORM_{{.*}}] +; CHECK-NOT: {{DW_|NULL}} +; CHECK: DW_TAG_lexical_block +; CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] +; CHECK-NEXT: DW_AT_high_pc [DW_FORM_{{.*}}] +; CHECK-NOT: {{DW_|NULL}} +; CHECK: DW_TAG_variable +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_name {{.*}} "a" +; CHECK: NULL +; CHECK-NOT: {{DW_|NULL}} +; CHECK: DW_TAG_variable +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_name {{.*}} "bar" + + +@_ZZ3fooiE3bar = internal global i32 0, align 4 + +; Function Attrs: nounwind +define i32 @_Z3fooi(i32 %x) #0 { +entry: + %retval = alloca i32, align 4 + %x.addr = alloca i32, align 4 + %a = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !15, metadata !16), !dbg !17 + %0 = load i32, i32* %x.addr, align 4, !dbg !18 + %tobool = icmp ne i32 %0, 0, !dbg !18 + br i1 %tobool, label %if.then, label %if.end, !dbg !19 + +if.then: ; preds = %entry + call void @llvm.dbg.declare(metadata i32* %a, metadata !20, metadata !16), !dbg !22 + %1 = load i32, i32* @_ZZ3fooiE3bar, align 4, !dbg !22 + %inc = add nsw i32 %1, 1, !dbg !22 + store i32 %inc, i32* @_ZZ3fooiE3bar, align 4, !dbg !22 + store i32 %1, i32* %a, align 4, !dbg !22 + %2 = load i32, i32* %a, align 4, !dbg !23 + store i32 %2, i32* %retval, !dbg !23 + br label %return, !dbg !23 + +if.end: ; preds = %entry + store i32 0, i32* %retval, !dbg !24 + br label %return, !dbg !24 + +return: ; preds = %if.end, %if.then + %3 = load i32, i32* %retval, !dbg !25 + ret i32 %3, !dbg !25 +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!12, !13} +!llvm.ident = !{!14} + +!0 = !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.7.0 (trunk 236102)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !2, subprograms: !3, globals: !8, imports: !2) +!1 = !DIFile(filename: "static.cpp", directory: "/") +!2 = !{} +!3 = !{!4} +!4 = !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, function: i32 (i32)* @_Z3fooi, variables: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{!7, !7} +!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!8 = !{!9} +!9 = !DIGlobalVariable(name: "bar", scope: !10, file: !1, line: 3, type: !7, isLocal: true, isDefinition: true, variable: i32* @_ZZ3fooiE3bar) +!10 = distinct !DILexicalBlock(scope: !11, file: !1, line: 2) +!11 = distinct !DILexicalBlock(scope: !4, file: !1, line: 2) +!12 = !{i32 2, !"Dwarf Version", i32 4} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{!"clang version 3.7.0 (trunk 236102)"} +!15 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "x", arg: 1, scope: !4, file: !1, line: 1, type: !7) +!16 = !DIExpression() +!17 = !DILocation(line: 1, scope: !4) +!18 = !DILocation(line: 2, scope: !11) +!19 = !DILocation(line: 2, scope: !4) +!20 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "a", scope: !21, file: !1, line: 5, type: !7) +!21 = distinct !DILexicalBlock(scope: !10, file: !1, line: 4) +!22 = !DILocation(line: 5, scope: !21) +!23 = !DILocation(line: 6, scope: !21) +!24 = !DILocation(line: 9, scope: !4) +!25 = !DILocation(line: 10, scope: !4) Index: test/DebugInfo/LB-typedef.ll =================================================================== --- test/DebugInfo/LB-typedef.ll +++ test/DebugInfo/LB-typedef.ll @@ -0,0 +1,108 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj -O0 < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s + +;; This test was generated by running following command: +;; clang -cc1 -O0 -g -emit-llvm typedef.cpp +;; Where typedef.cpp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;int foo(int x) { +;; if(x) { +;; typedef char X; +;; { +;; X a = x; +;; return a; +;; } +;; } +;; return 0; +;;} +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +; CHECK: DW_TAG_subprogram +; CHECK-NOT: DW_TAG +; CHECK: DW_AT_name {{.*}} "foo" +; CHECK-NOT: NULL +; CHECK: DW_TAG_lexical_block +; CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] +; CHECK-NEXT: DW_AT_high_pc [DW_FORM_{{.*}}] +; CHECK-NOT: {{DW_|NULL}} +; CHECK: DW_TAG_lexical_block +; CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] +; CHECK-NEXT: DW_AT_high_pc [DW_FORM_{{.*}}] +; CHECK-NOT: {{DW_|NULL}} +; CHECK: DW_TAG_variable +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_name {{.*}} "a" +; CHECK: NULL +; CHECK-NOT: {{DW_|NULL}} +; CHECK: DW_TAG_typedef +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_name {{.*}} "X" + + +; Function Attrs: nounwind +define i32 @_Z3fooi(i32 %x) #0 { +entry: + %retval = alloca i32, align 4 + %x.addr = alloca i32, align 4 + %a = alloca i8, align 1 + store i32 %x, i32* %x.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !11, metadata !12), !dbg !13 + %0 = load i32, i32* %x.addr, align 4, !dbg !14 + %tobool = icmp ne i32 %0, 0, !dbg !14 + br i1 %tobool, label %if.then, label %if.end, !dbg !16 + +if.then: ; preds = %entry + call void @llvm.dbg.declare(metadata i8* %a, metadata !17, metadata !12), !dbg !22 + %1 = load i32, i32* %x.addr, align 4, !dbg !22 + %conv = trunc i32 %1 to i8, !dbg !22 + store i8 %conv, i8* %a, align 1, !dbg !22 + %2 = load i8, i8* %a, align 1, !dbg !23 + %conv1 = sext i8 %2 to i32, !dbg !23 + store i32 %conv1, i32* %retval, !dbg !23 + br label %return, !dbg !23 + +if.end: ; preds = %entry + store i32 0, i32* %retval, !dbg !24 + br label %return, !dbg !24 + +return: ; preds = %if.end, %if.then + %3 = load i32, i32* %retval, !dbg !25 + ret i32 %3, !dbg !25 +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!8, !9} +!llvm.ident = !{!10} + +!0 = !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.7.0 (trunk 236102)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !2, subprograms: !3, globals: !2, imports: !2) +!1 = !DIFile(filename: "typedef.cpp", directory: "/") +!2 = !{} +!3 = !{!4} +!4 = !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, function: i32 (i32)* @_Z3fooi, variables: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{!7, !7} +!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{!"clang version 3.7.0 (trunk 236102)"} +!11 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "x", arg: 1, scope: !4, file: !1, line: 1, type: !7) +!12 = !DIExpression() +!13 = !DILocation(line: 1, scope: !4) +!14 = !DILocation(line: 2, scope: !15) +!15 = distinct !DILexicalBlock(scope: !4, file: !1, line: 2) +!16 = !DILocation(line: 2, scope: !4) +!17 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "a", scope: !18, file: !1, line: 5, type: !20) +!18 = distinct !DILexicalBlock(scope: !19, file: !1, line: 4) +!19 = distinct !DILexicalBlock(scope: !15, file: !1, line: 2) +!20 = !DIDerivedType(tag: DW_TAG_typedef, name: "X", scope: !19, file: !1, line: 3, baseType: !21) +!21 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) +!22 = !DILocation(line: 5, scope: !18) +!23 = !DILocation(line: 6, scope: !18) +!24 = !DILocation(line: 9, scope: !4) +!25 = !DILocation(line: 10, scope: !4)