diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h --- a/llvm/include/llvm/Object/ELFTypes.h +++ b/llvm/include/llvm/Object/ELFTypes.h @@ -800,15 +800,19 @@ // Struct representing the BBAddrMap information for one basic block. struct BBEntry { struct Metadata { - bool HasReturn : 1; // If this block ends with a return (or tail call). - bool HasTailCall : 1; // If this block ends with a tail call. - bool IsEHPad : 1; // If this is an exception handling block. - bool CanFallThrough : 1; // If this block can fall through to its next. + bool HasReturn : 1; // If this block ends with a return (or tail + // call). + bool HasTailCall : 1; // If this block ends with a tail call. + bool IsEHPad : 1; // If this is an exception handling block. + bool CanFallThrough : 1; // If this block can fall through to its next. + bool HasIndirectBranch : 1; // If this block ends with an indirect branch + // (branch via a register). bool operator==(const Metadata &Other) const { return HasReturn == Other.HasReturn && HasTailCall == Other.HasTailCall && IsEHPad == Other.IsEHPad && - CanFallThrough == Other.CanFallThrough; + CanFallThrough == Other.CanFallThrough && + HasIndirectBranch == Other.HasIndirectBranch; } // Encodes this struct as a uint32_t value. @@ -816,7 +820,8 @@ return static_cast(HasReturn) | (static_cast(HasTailCall) << 1) | (static_cast(IsEHPad) << 2) | - (static_cast(CanFallThrough) << 3); + (static_cast(CanFallThrough) << 3) | + (static_cast(HasIndirectBranch) << 4); } // Decodes and returns a Metadata struct from a uint32_t value. @@ -824,7 +829,8 @@ Metadata MD{/*HasReturn=*/static_cast(V & 1), /*HasTailCall=*/static_cast(V & (1 << 1)), /*IsEHPad=*/static_cast(V & (1 << 2)), - /*CanFallThrough=*/static_cast(V & (1 << 3))}; + /*CanFallThrough=*/static_cast(V & (1 << 3)), + /*HasIndirectBranch=*/static_cast(V & (1 << 4))}; if (MD.encode() != V) return createStringError( std::error_code(), "invalid encoding for BBEntry::Metadata: 0x%x", diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1330,7 +1330,8 @@ const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo(); return object::BBAddrMap::BBEntry::Metadata{ MBB.isReturnBlock(), !MBB.empty() && TII->isTailCall(MBB.back()), - MBB.isEHPad(), const_cast(MBB).canFallThrough()} + MBB.isEHPad(), const_cast(MBB).canFallThrough(), + !MBB.empty() && MBB.rbegin()->isIndirectBranch()} .encode(); } diff --git a/llvm/test/CodeGen/X86/basic-block-sections-labels.ll b/llvm/test/CodeGen/X86/basic-block-sections-labels.ll --- a/llvm/test/CodeGen/X86/basic-block-sections-labels.ll +++ b/llvm/test/CodeGen/X86/basic-block-sections-labels.ll @@ -3,24 +3,28 @@ ; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=false -basic-block-sections=labels | FileCheck %s --check-prefixes=CHECK,NOUNIQ ; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=true -basic-block-sections=labels -split-machine-functions | FileCheck %s --check-prefixes=CHECK,UNIQ -define void @_Z3bazb(i1 zeroext) personality ptr @__gxx_personality_v0 { - br i1 %0, label %2, label %7 +define void @_Z3bazb(i1 zeroext, i1 zeroext) personality ptr @__gxx_personality_v0 { + br i1 %0, label %3, label %8 -2: - %3 = invoke i32 @_Z3barv() - to label %7 unwind label %5 - br label %9 +3: + %4 = invoke i32 @_Z3barv() + to label %8 unwind label %6 + br label %10 -5: +6: landingpad { ptr, i32 } catch ptr null - br label %9 + br label %12 -7: - %8 = call i32 @_Z3foov() - br label %9 +8: + %9 = call i32 @_Z3foov() + br i1 %1, label %12, label %10 -9: +10: + %11 = select i1 %1, ptr blockaddress(@_Z3bazb, %3), ptr blockaddress(@_Z3bazb, %12) ; [#uses=1] + indirectbr ptr %11, [label %3, label %12] + +12: ret void } @@ -49,7 +53,7 @@ ; CHECK-NEXT: .byte 2 # version ; CHECK-NEXT: .byte 0 # feature ; CHECK-NEXT: .quad .Lfunc_begin0 # function address -; CHECK-NEXT: .byte 4 # number of basic blocks +; CHECK-NEXT: .byte 6 # number of basic blocks ; CHECK-NEXT: .byte 0 # BB id ; CHECK-NEXT: .uleb128 .Lfunc_begin0-.Lfunc_begin0 ; CHECK-NEXT: .uleb128 .LBB_END0_0-.Lfunc_begin0 @@ -61,8 +65,16 @@ ; CHECK-NEXT: .byte 3 # BB id ; CHECK-NEXT: .uleb128 .LBB0_2-.LBB_END0_1 ; CHECK-NEXT: .uleb128 .LBB_END0_2-.LBB0_2 -; CHECK-NEXT: .byte 1 -; CHECK-NEXT: .byte 2 # BB id +; CHECK-NEXT: .byte 8 +; CHECK-NEXT: .byte 4 # BB id ; CHECK-NEXT: .uleb128 .LBB0_3-.LBB_END0_2 ; CHECK-NEXT: .uleb128 .LBB_END0_3-.LBB0_3 +; CHECK-NEXT: .byte 16 +; CHECK-NEXT: .byte 5 # BB id +; CHECK-NEXT: .uleb128 .LBB0_4-.LBB_END0_3 +; CHECK-NEXT: .uleb128 .LBB_END0_4-.LBB0_4 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 2 # BB id +; CHECK-NEXT: .uleb128 .LBB0_5-.LBB_END0_4 +; CHECK-NEXT: .uleb128 .LBB_END0_5-.LBB0_5 ; CHECK-NEXT: .byte 5 diff --git a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-relocatable.test b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-relocatable.test --- a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-relocatable.test +++ b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map-relocatable.test @@ -20,6 +20,7 @@ # CHECK-NEXT: HasTailCall: No # CHECK-NEXT: IsEHPad: No # CHECK-NEXT: CanFallThrough: No +# CHECK-NEXT: HasIndirectBranch: No # CHECK-NEXT: } # CHECK-NEXT: ] # CHECK-NEXT: } @@ -35,6 +36,7 @@ # CHECK-NEXT: HasTailCall: No # CHECK-NEXT: IsEHPad: No # CHECK-NEXT: CanFallThrough: Yes +# CHECK-NEXT: HasIndirectBranch: No # CHECK-NEXT: } # CHECK-NEXT: ] # CHECK-NEXT: } @@ -205,6 +207,7 @@ # ET-DYN-NO-WARNING: HasTailCall: No # ET-DYN-NO-WARNING: IsEHPad: No # ET-DYN-NO-WARNING: CanFallThrough: No +# ET-DYN-NO-WARNING: HasIndirectBranch: No # ET-DYN-NO-WARNING: } # ET-DYN-NO-WARNING: ] # ET-DYN-NO-WARNING: } diff --git a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test --- a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test +++ b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test @@ -39,6 +39,7 @@ # CHECK-NEXT: HasTailCall: Yes # CHECK-NEXT: IsEHPad: No # CHECK-NEXT: CanFallThrough: No +# CHECK-NEXT: HasIndirectBranch: No # CHECK-NEXT: } # CHECK-NEXT: { # CHECK-NEXT: ID: 2 @@ -48,6 +49,7 @@ # CHECK-NEXT: HasTailCall: No # CHECK-NEXT: IsEHPad: Yes # CHECK-NEXT: CanFallThrough: No +# CHECK-NEXT: HasIndirectBranch: Yes # CHECK-NEXT: } # CHECK-NEXT: ] # CHECK-NEXT: } @@ -63,6 +65,7 @@ # CHECK-NEXT: HasTailCall: No # CHECK-NEXT: IsEHPad: No # CHECK-NEXT: CanFallThrough: Yes +# CHECK-NEXT: HasIndirectBranch: No # CHECK-NEXT: } # CHECK-NEXT: ] # CHECK-NEXT: } @@ -87,6 +90,7 @@ # TRUNCATED-NEXT: HasTailCall: Yes # TRUNCATED-NEXT: IsEHPad: No # TRUNCATED-NEXT: CanFallThrough: Yes +# TRUNCATED-NEXT: HasIndirectBranch: Yes # TRUNCATED-NEXT: } # TRUNCATED-NEXT: { # TRUNCATED-NEXT: ID: 7 @@ -96,6 +100,7 @@ # TRUNCATED-NEXT: HasTailCall: Yes # TRUNCATED-NEXT: IsEHPad: Yes # TRUNCATED-NEXT: CanFallThrough: Yes +# TRUNCATED-NEXT: HasIndirectBranch: No # TRUNCATED-NEXT: } # TRUNCATED-NEXT: ] # TRUNCATED-NEXT: } @@ -131,7 +136,7 @@ - ID: 2 AddressOffset: 0x3 Size: 0x4 - Metadata: 0x5 + Metadata: 0x15 - Version: 2 Address: 0x22222 BBEntries: @@ -152,7 +157,7 @@ - ID: 6 AddressOffset: 0x9 Size: 0xa - Metadata: 0xb + Metadata: 0x1b - ID: 7 AddressOffset: 0xc Size: 0xd @@ -192,6 +197,7 @@ # V0-NEXT: HasTailCall: # V0-NEXT: IsEHPad: # V0-NEXT: CanFallThrough: +# V0-NEXT: HasIndirectBranch: # V0-NEXT: } # V0-NEXT: { # V0-NEXT: ID: 1 @@ -201,6 +207,7 @@ # V0-NEXT: HasTailCall: # V0-NEXT: IsEHPad: # V0-NEXT: CanFallThrough: +# V0-NEXT: HasIndirectBranch: # V0-NEXT: } # V0-NEXT: ] # V0-NEXT: } @@ -222,6 +229,7 @@ # V1-NEXT: HasTailCall: # V1-NEXT: IsEHPad: # V1-NEXT: CanFallThrough: +# V1-NEXT: HasIndirectBranch: # V1-NEXT: } # V1-NEXT: { # V1-NEXT: ID: 1 @@ -231,6 +239,7 @@ # V1-NEXT: HasTailCall: # V1-NEXT: IsEHPad: # V1-NEXT: CanFallThrough: +# V1-NEXT: HasIndirectBranch: # V1-NEXT: } # V1-NEXT: ] # V1-NEXT: } diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -7462,6 +7462,7 @@ W.printBoolean("HasTailCall", BBE.hasTailCall()); W.printBoolean("IsEHPad", BBE.isEHPad()); W.printBoolean("CanFallThrough", BBE.canFallThrough()); + W.printBoolean("HasIndirectBranch", BBE.MD.HasIndirectBranch); } } } diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp --- a/llvm/unittests/Object/ELFObjectFileTest.cpp +++ b/llvm/unittests/Object/ELFObjectFileTest.cpp @@ -658,13 +658,13 @@ - ID: 0 AddressOffset: 0x0 Size: 0x4 - Metadata: 0x8 + Metadata: 0x18 )"); - BBAddrMap E1 = {0x11111, {{1, 0x0, 0x1, {false, true, false, false}}}}; - BBAddrMap E2 = {0x22222, {{2, 0x0, 0x2, {false, false, true, false}}}}; - BBAddrMap E3 = {0x33333, {{0, 0x0, 0x3, {false, true, true, false}}}}; - BBAddrMap E4 = {0x44444, {{0, 0x0, 0x4, {false, false, false, true}}}}; + BBAddrMap E1 = {0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}}; + BBAddrMap E2 = {0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}}; + BBAddrMap E3 = {0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}}}; + BBAddrMap E4 = {0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}}}; std::vector Section0BBAddrMaps = {E4}; std::vector Section1BBAddrMaps = {E3}; diff --git a/llvm/unittests/Object/ELFTypesTest.cpp b/llvm/unittests/Object/ELFTypesTest.cpp --- a/llvm/unittests/Object/ELFTypesTest.cpp +++ b/llvm/unittests/Object/ELFTypesTest.cpp @@ -64,14 +64,15 @@ } TEST(ELFTypesTest, BBEntryMetadataEncodingTest) { - const std::array Decoded = { - {{false, false, false, false}, - {true, false, false, false}, - {false, true, false, false}, - {false, false, true, false}, - {false, false, false, true}, - {true, true, true, true}}}; - const std::array Encoded = {{0, 1, 2, 4, 8, 15}}; + const std::array Decoded = { + {{false, false, false, false, false}, + {true, false, false, false, false}, + {false, true, false, false, false}, + {false, false, true, false, false}, + {false, false, false, true, false}, + {false, false, false, false, true}, + {true, true, true, true, true}}}; + const std::array Encoded = {{0, 1, 2, 4, 8, 16, 31}}; for (size_t i = 0; i < Decoded.size(); ++i) EXPECT_EQ(Decoded[i].encode(), Encoded[i]); for (size_t i = 0; i < Encoded.size(); ++i) {