[llvm] [llvm-objdump] Add the --visualize-jumps option (PR #74858)

via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 8 08:23:29 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-binary-utilities

Author: None (ostannard)

<details>
<summary>Changes</summary>

This is a feature which GNU objdump currently has, which prints a control-flow graph showing all of the direct branches alongside the disassembly.

This should work for any architecture which implements the MCInstrAnalysis class, I've tested it on ARM, Thumb and AArch64.

There are a few (known) differences between this and the GNU objdump
version:
* This has the option to draw the lines using unicode line-drawing charcters, instead of ASCII. This is on by default because I find the connected lines much easier to read. I've included an option to revert back to ASCII for terminals or fonts which don't support the right bits of unicode.
* I haven't yet implemented the extended-color mode yet. With GNU objdump this often results in some very similar colors, so we might want to carefully pick a pallet which minimises that.

Related issue: #<!-- -->60172

Demo:  ![Screenshot from 2023-12-08 16-11-24](https://github.com/llvm/llvm-project/assets/3903045/5267f249-5e6a-438d-a026-135f015ee0aa)

---

Patch is 60.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/74858.diff


19 Files Affected:

- (modified) llvm/lib/Support/FormattedStream.cpp (+1) 
- (added) llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-ascii.txt (+31) 
- (added) llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-unicode-color.txt (+31) 
- (added) llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-unicode-relocs.txt (+34) 
- (added) llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-unicode.txt (+31) 
- (added) llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-arm-ascii.txt (+27) 
- (added) llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-arm-unicode.txt (+27) 
- (added) llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-thumb-ascii.txt (+34) 
- (added) llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-thumb-unicode.txt (+34) 
- (added) llvm/test/tools/llvm-objdump/visualize-jumps-aarch64.s (+69) 
- (added) llvm/test/tools/llvm-objdump/visualize-jumps-arm.s (+54) 
- (added) llvm/test/tools/llvm-objdump/visualize-jumps-thumb.s (+63) 
- (modified) llvm/tools/llvm-objdump/ObjdumpOpts.td (+7) 
- (modified) llvm/tools/llvm-objdump/SourcePrinter.cpp (+194-2) 
- (modified) llvm/tools/llvm-objdump/SourcePrinter.h (+112-1) 
- (modified) llvm/tools/llvm-objdump/XCOFFDump.cpp (+1-1) 
- (modified) llvm/tools/llvm-objdump/llvm-objdump.cpp (+235-80) 
- (modified) llvm/tools/llvm-objdump/llvm-objdump.h (+13) 
- (modified) llvm/unittests/Support/formatted_raw_ostream_test.cpp (+4-5) 


``````````diff
diff --git a/llvm/lib/Support/FormattedStream.cpp b/llvm/lib/Support/FormattedStream.cpp
index c0d28435099570..48b02889c6d3e5 100644
--- a/llvm/lib/Support/FormattedStream.cpp
+++ b/llvm/lib/Support/FormattedStream.cpp
@@ -45,6 +45,7 @@ void formatted_raw_ostream::UpdatePosition(const char *Ptr, size_t Size) {
       break;
     case '\t':
       // Assumes tab stop = 8 characters.
+      Column += 1;
       Column += (8 - (Column & 0x7)) & 0x7;
       break;
     }
diff --git a/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-ascii.txt b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-ascii.txt
new file mode 100644
index 00000000000000..592e50d98f8ff7
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-ascii.txt
@@ -0,0 +1,31 @@
+
+<stdin>:	file format elf64-littleaarch64
+
+Disassembly of section .text:
+
+0000000000000000 <test_func>:
+       0:           94000000   	bl	0x0 <test_func>
+       4:           14000000   	b	0x4 <test_func+0x4>
+       8:       /-- 14000001   	b	0xc <test_func+0xc>
+       c:       +-> d503201f   	nop
+      10:       \-- 17ffffff   	b	0xc <test_func+0xc>
+      14:           14000000   	b	0x14 <test_func+0x14>
+      18:       /-- 54000040   	b.eq	0x20 <test_func+0x20>
+      1c:       +-- b4000020   	cbz	x0, 0x20 <test_func+0x20>
+      20:       \-> d503201f   	nop
+      24:   /------ 14000005   	b	0x38 <test_func+0x38>
+      28:   | /---- 14000003   	b	0x34 <test_func+0x34>
+      2c:   | | /-- 14000001   	b	0x30 <test_func+0x30>
+      30:   | | \-> d503201f   	nop
+      34:   | \---> d503201f   	nop
+      38:   \-----> d503201f   	nop
+      3c:       /-- 14000002   	b	0x44 <test_func+0x44>
+      40:     /-|-- 14000002   	b	0x48 <test_func+0x48>
+      44:     | \-> d503201f   	nop
+      48:     \---> d503201f   	nop
+      4c:       /-- 14000001   	b	0x50 <test_func+0x50>
+      50:     /-|-- 14000001   	b	0x54 <test_func+0x54>
+      54:     \---> d503201f   	nop
+      58:       /-- 14000002   	b	0x60 <test_func+0x60>
+      5c:       |   94000000   	bl	0x5c <test_func+0x5c>
+      60:       \-> d503201f   	nop
diff --git a/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-unicode-color.txt b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-unicode-color.txt
new file mode 100644
index 00000000000000..925c5ef52a8d22
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-unicode-color.txt
@@ -0,0 +1,31 @@
+
+<stdin>:	file format elf64-littleaarch64
+
+Disassembly of section .text:
+
+0000000000000000 <test_func>:
+       0:           94000000   	bl	0x0 <test_func>
+       4:           14000000   	b	0x4 <test_func+0x4>
+       8:       ╭── 14000001   	b	0xc <test_func+0xc>
+       c:       ├─> d503201f   	nop
+      10:       ╰── 17ffffff   	b	0xc <test_func+0xc>
+      14:           14000000   	b	0x14 <test_func+0x14>
+      18:       ╭── 54000040   	b.eq	0x20 <test_func+0x20>
+      1c:       ├── b4000020   	cbz	x0, 0x20 <test_func+0x20>
+      20:       ╰─> d503201f   	nop
+      24:   ╭────── 14000005   	b	0x38 <test_func+0x38>
+      28:   │ ╭──── 14000003   	b	0x34 <test_func+0x34>
+      2c:   │ │ ╭── 14000001   	b	0x30 <test_func+0x30>
+      30:   │ │ ╰─> d503201f   	nop
+      34:   │ ╰───> d503201f   	nop
+      38:   ╰─────> d503201f   	nop
+      3c:       ╭── 14000002   	b	0x44 <test_func+0x44>
+      40:     ╭─│── 14000002   	b	0x48 <test_func+0x48>
+      44:     │ ╰─> d503201f   	nop
+      48:     ╰───> d503201f   	nop
+      4c:       ╭── 14000001   	b	0x50 <test_func+0x50>
+      50:     ╭─│── 14000001   	b	0x54 <test_func+0x54>
+      54:     ╰───> d503201f   	nop
+      58:       ╭── 14000002   	b	0x60 <test_func+0x60>
+      5c:       │   94000000   	bl	0x5c <test_func+0x5c>
+      60:       ╰─> d503201f   	nop
diff --git a/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-unicode-relocs.txt b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-unicode-relocs.txt
new file mode 100644
index 00000000000000..75ec5741fdaae2
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-unicode-relocs.txt
@@ -0,0 +1,34 @@
+
+<stdin>:	file format elf64-littleaarch64
+
+Disassembly of section .text:
+
+0000000000000000 <test_func>:
+       0:           94000000   	bl	0x0 <test_func>
+                   		0000000000000000:  R_AARCH64_CALL26	extern_func
+       4:           14000000   	b	0x4 <test_func+0x4>
+                   		0000000000000004:  R_AARCH64_JUMP26	extern_func
+       8:       ╭── 14000001   	b	0xc <test_func+0xc>
+       c:       ├─> d503201f   	nop
+      10:       ╰── 17ffffff   	b	0xc <test_func+0xc>
+      14:           14000000   	b	0x14 <test_func+0x14>
+      18:       ╭── 54000040   	b.eq	0x20 <test_func+0x20>
+      1c:       ├── b4000020   	cbz	x0, 0x20 <test_func+0x20>
+      20:       ╰─> d503201f   	nop
+      24:   ╭────── 14000005   	b	0x38 <test_func+0x38>
+      28:   │ ╭──── 14000003   	b	0x34 <test_func+0x34>
+      2c:   │ │ ╭── 14000001   	b	0x30 <test_func+0x30>
+      30:   │ │ ╰─> d503201f   	nop
+      34:   │ ╰───> d503201f   	nop
+      38:   ╰─────> d503201f   	nop
+      3c:       ╭── 14000002   	b	0x44 <test_func+0x44>
+      40:     ╭─│── 14000002   	b	0x48 <test_func+0x48>
+      44:     │ ╰─> d503201f   	nop
+      48:     ╰───> d503201f   	nop
+      4c:       ╭── 14000001   	b	0x50 <test_func+0x50>
+      50:     ╭─│── 14000001   	b	0x54 <test_func+0x54>
+      54:     ╰───> d503201f   	nop
+      58:       ╭── 14000002   	b	0x60 <test_func+0x60>
+      5c:       │   94000000   	bl	0x5c <test_func+0x5c>
+                │  		000000000000005c:  R_AARCH64_CALL26	extern_func
+      60:       ╰─> d503201f   	nop
diff --git a/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-unicode.txt b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-unicode.txt
new file mode 100644
index 00000000000000..4cabdc92d61c1d
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-aarch64-unicode.txt
@@ -0,0 +1,31 @@
+
+<stdin>:	file format elf64-littleaarch64
+
+Disassembly of section .text:
+
+0000000000000000 <test_func>:
+       0:           94000000   	bl	0x0 <test_func>
+       4:           14000000   	b	0x4 <test_func+0x4>
+       8:       ╭── 14000001   	b	0xc <test_func+0xc>
+       c:       ├─> d503201f   	nop
+      10:       ╰── 17ffffff   	b	0xc <test_func+0xc>
+      14:           14000000   	b	0x14 <test_func+0x14>
+      18:       ╭── 54000040   	b.eq	0x20 <test_func+0x20>
+      1c:       ├── b4000020   	cbz	x0, 0x20 <test_func+0x20>
+      20:       ╰─> d503201f   	nop
+      24:   ╭────── 14000005   	b	0x38 <test_func+0x38>
+      28:   │ ╭──── 14000003   	b	0x34 <test_func+0x34>
+      2c:   │ │ ╭── 14000001   	b	0x30 <test_func+0x30>
+      30:   │ │ ╰─> d503201f   	nop
+      34:   │ ╰───> d503201f   	nop
+      38:   ╰─────> d503201f   	nop
+      3c:       ╭── 14000002   	b	0x44 <test_func+0x44>
+      40:     ╭─│── 14000002   	b	0x48 <test_func+0x48>
+      44:     │ ╰─> d503201f   	nop
+      48:     ╰───> d503201f   	nop
+      4c:       ╭── 14000001   	b	0x50 <test_func+0x50>
+      50:     ╭─│── 14000001   	b	0x54 <test_func+0x54>
+      54:     ╰───> d503201f   	nop
+      58:       ╭── 14000002   	b	0x60 <test_func+0x60>
+      5c:       │   94000000   	bl	0x5c <test_func+0x5c>
+      60:       ╰─> d503201f   	nop
diff --git a/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-arm-ascii.txt b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-arm-ascii.txt
new file mode 100644
index 00000000000000..7e006841980534
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-arm-ascii.txt
@@ -0,0 +1,27 @@
+
+<stdin>:	file format elf32-littlearm
+
+Disassembly of section .text:
+
+00000000 <test_func>:
+       0:           ebfffffe   	bl	0x0 <test_func>         @ imm = #-0x8
+       4:           eafffffe   	b	0x4 <test_func+0x4>     @ imm = #-0x8
+       8:       /-- eaffffff   	b	0xc <test_func+0xc>     @ imm = #-0x4
+       c:       +-> e320f000   	nop
+      10:       \-- eafffffd   	b	0xc <test_func+0xc>     @ imm = #-0xc
+      14:           eafffffe   	b	0x14 <test_func+0x14>   @ imm = #-0x8
+      18:       /-- 0affffff   	beq	0x1c <test_func+0x1c>   @ imm = #-0x4
+      1c:       \-> e320f000   	nop
+      20:   /------ ea000003   	b	0x34 <test_func+0x34>   @ imm = #0xc
+      24:   | /---- ea000001   	b	0x30 <test_func+0x30>   @ imm = #0x4
+      28:   | | /-- eaffffff   	b	0x2c <test_func+0x2c>   @ imm = #-0x4
+      2c:   | | \-> e320f000   	nop
+      30:   | \---> e320f000   	nop
+      34:   \-----> e320f000   	nop
+      38:       /-- ea000000   	b	0x40 <test_func+0x40>   @ imm = #0x0
+      3c:     /-|-- ea000000   	b	0x44 <test_func+0x44>   @ imm = #0x0
+      40:     | \-> e320f000   	nop
+      44:     \---> e320f000   	nop
+      48:     /---- eaffffff   	b	0x4c <test_func+0x4c>   @ imm = #-0x4
+      4c:     \-|-> eaffffff   	b	0x50 <test_func+0x50>   @ imm = #-0x4
+      50:       \-> e320f000   	nop
diff --git a/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-arm-unicode.txt b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-arm-unicode.txt
new file mode 100644
index 00000000000000..62194b4b33c172
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-arm-unicode.txt
@@ -0,0 +1,27 @@
+
+<stdin>:	file format elf32-littlearm
+
+Disassembly of section .text:
+
+00000000 <test_func>:
+       0:           ebfffffe   	bl	0x0 <test_func>         @ imm = #-0x8
+       4:           eafffffe   	b	0x4 <test_func+0x4>     @ imm = #-0x8
+       8:       ╭── eaffffff   	b	0xc <test_func+0xc>     @ imm = #-0x4
+       c:       ├─> e320f000   	nop
+      10:       ╰── eafffffd   	b	0xc <test_func+0xc>     @ imm = #-0xc
+      14:           eafffffe   	b	0x14 <test_func+0x14>   @ imm = #-0x8
+      18:       ╭── 0affffff   	beq	0x1c <test_func+0x1c>   @ imm = #-0x4
+      1c:       ╰─> e320f000   	nop
+      20:   ╭────── ea000003   	b	0x34 <test_func+0x34>   @ imm = #0xc
+      24:   │ ╭──── ea000001   	b	0x30 <test_func+0x30>   @ imm = #0x4
+      28:   │ │ ╭── eaffffff   	b	0x2c <test_func+0x2c>   @ imm = #-0x4
+      2c:   │ │ ╰─> e320f000   	nop
+      30:   │ ╰───> e320f000   	nop
+      34:   ╰─────> e320f000   	nop
+      38:       ╭── ea000000   	b	0x40 <test_func+0x40>   @ imm = #0x0
+      3c:     ╭─│── ea000000   	b	0x44 <test_func+0x44>   @ imm = #0x0
+      40:     │ ╰─> e320f000   	nop
+      44:     ╰───> e320f000   	nop
+      48:     ╭──── eaffffff   	b	0x4c <test_func+0x4c>   @ imm = #-0x4
+      4c:     ╰─│─> eaffffff   	b	0x50 <test_func+0x50>   @ imm = #-0x4
+      50:       ╰─> e320f000   	nop
diff --git a/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-thumb-ascii.txt b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-thumb-ascii.txt
new file mode 100644
index 00000000000000..f18062167dd97d
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-thumb-ascii.txt
@@ -0,0 +1,34 @@
+
+<stdin>:	file format elf32-littlearm
+
+Disassembly of section .text:
+
+00000000 <test_func>:
+       0:           f7ff fffe  	bl	0x0 <test_func>         @ imm = #-0x4
+       4:           f7ff bffe  	b.w	0x4 <test_func+0x4>     @ imm = #-0x4
+       8:       /-- e7ff       	b	0xa <test_func+0xa>     @ imm = #-0x2
+       a:       +-> bf00       	nop
+       c:       \-- e7fd       	b	0xa <test_func+0xa>     @ imm = #-0x6
+       e:           e7fe       	b	0xe <test_func+0xe>     @ imm = #-0x4
+      10:       /-- f000 b807  	b.w	0x22 <test_func+0x22>   @ imm = #0xe
+      14:       +-- d005       	beq	0x22 <test_func+0x22>   @ imm = #0xa
+      16:       +-- f040 8004  	bne.w	0x22 <test_func+0x22>   @ imm = #0x8
+      1a:       +-- b110       	cbz	r0, 0x22 <test_func+0x22> @ imm = #0x4
+      1c:       |   bfd8       	it	le
+      1e:       +-- e000       	ble	0x22 <test_func+0x22>   @ imm = #0x0
+      20:       |   bf00       	nop
+      22:       \-> bf00       	nop
+      24:           bf00       	nop
+      26:   /------ e003       	b	0x30 <test_func+0x30>   @ imm = #0x6
+      28:   | /---- e001       	b	0x2e <test_func+0x2e>   @ imm = #0x2
+      2a:   | | /-- e7ff       	b	0x2c <test_func+0x2c>   @ imm = #-0x2
+      2c:   | | \-> bf00       	nop
+      2e:   | \---> bf00       	nop
+      30:   \-----> bf00       	nop
+      32:       /-- e000       	b	0x36 <test_func+0x36>   @ imm = #0x0
+      34:     /-|-- e000       	b	0x38 <test_func+0x38>   @ imm = #0x0
+      36:     | \-> bf00       	nop
+      38:     \---> bf00       	nop
+      3a:       /-- e7ff       	b	0x3c <test_func+0x3c>   @ imm = #-0x2
+      3c:     /-|-- e7ff       	b	0x3e <test_func+0x3e>   @ imm = #-0x2
+      3e:     \---> bf00       	nop
diff --git a/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-thumb-unicode.txt b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-thumb-unicode.txt
new file mode 100644
index 00000000000000..b171fb1c5d28c2
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/visualize-jumps-thumb-unicode.txt
@@ -0,0 +1,34 @@
+
+<stdin>:	file format elf32-littlearm
+
+Disassembly of section .text:
+
+00000000 <test_func>:
+       0:           f7ff fffe  	bl	0x0 <test_func>         @ imm = #-0x4
+       4:           f7ff bffe  	b.w	0x4 <test_func+0x4>     @ imm = #-0x4
+       8:       ╭── e7ff       	b	0xa <test_func+0xa>     @ imm = #-0x2
+       a:       ├─> bf00       	nop
+       c:       ╰── e7fd       	b	0xa <test_func+0xa>     @ imm = #-0x6
+       e:           e7fe       	b	0xe <test_func+0xe>     @ imm = #-0x4
+      10:       ╭── f000 b807  	b.w	0x22 <test_func+0x22>   @ imm = #0xe
+      14:       ├── d005       	beq	0x22 <test_func+0x22>   @ imm = #0xa
+      16:       ├── f040 8004  	bne.w	0x22 <test_func+0x22>   @ imm = #0x8
+      1a:       ├── b110       	cbz	r0, 0x22 <test_func+0x22> @ imm = #0x4
+      1c:       │   bfd8       	it	le
+      1e:       ├── e000       	ble	0x22 <test_func+0x22>   @ imm = #0x0
+      20:       │   bf00       	nop
+      22:       ╰─> bf00       	nop
+      24:           bf00       	nop
+      26:   ╭────── e003       	b	0x30 <test_func+0x30>   @ imm = #0x6
+      28:   │ ╭──── e001       	b	0x2e <test_func+0x2e>   @ imm = #0x2
+      2a:   │ │ ╭── e7ff       	b	0x2c <test_func+0x2c>   @ imm = #-0x2
+      2c:   │ │ ╰─> bf00       	nop
+      2e:   │ ╰───> bf00       	nop
+      30:   ╰─────> bf00       	nop
+      32:       ╭── e000       	b	0x36 <test_func+0x36>   @ imm = #0x0
+      34:     ╭─│── e000       	b	0x38 <test_func+0x38>   @ imm = #0x0
+      36:     │ ╰─> bf00       	nop
+      38:     ╰───> bf00       	nop
+      3a:       ╭── e7ff       	b	0x3c <test_func+0x3c>   @ imm = #-0x2
+      3c:     ╭─│── e7ff       	b	0x3e <test_func+0x3e>   @ imm = #-0x2
+      3e:     ╰───> bf00       	nop
diff --git a/llvm/test/tools/llvm-objdump/visualize-jumps-aarch64.s b/llvm/test/tools/llvm-objdump/visualize-jumps-aarch64.s
new file mode 100644
index 00000000000000..f78b3e27975556
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/visualize-jumps-aarch64.s
@@ -0,0 +1,69 @@
+// RUN: llvm-mc < %s -triple aarch64 -filetype=obj | \
+// RUN:   llvm-objdump --triple aarch64 -d --visualize-jumps=unicode - | \
+// RUN:   diff - %p/Inputs/visualize-jumps-aarch64-unicode.txt
+
+// RUN: llvm-mc < %s -triple aarch64 -filetype=obj | \
+// RUN:   llvm-objdump --triple aarch64 -d --visualize-jumps=ascii - | \
+// RUN:   diff - %p/Inputs/visualize-jumps-aarch64-ascii.txt
+
+// RUN: llvm-mc < %s -triple aarch64 -filetype=obj | \
+// RUN:   llvm-objdump --triple aarch64 -d --visualize-jumps=unicode,color - | \
+// RUN:   diff - %p/Inputs/visualize-jumps-aarch64-unicode-color.txt
+
+// RUN: llvm-mc < %s -triple aarch64 -filetype=obj | \
+// RUN:   llvm-objdump --triple aarch64 -d --visualize-jumps=unicode --reloc - | \
+// RUN:   diff - %p/Inputs/visualize-jumps-aarch64-unicode-relocs.txt
+
+test_func:
+  // Relocated instructions don't get control-flow edges.
+  bl extern_func
+  b extern_func
+  
+  // Two branches to the same label, one forward and one backward.
+  b .Llabel1
+.Llabel1:
+  nop
+  b .Llabel1
+
+  // Branch to self, no CFG edge shown
+  b .
+
+  // Conditional branches
+  b.eq .Llabel2
+  cbz x0, .Llabel2
+.Llabel2:
+  nop
+
+  // Branches are sorted with shorter ones to the right, to reduce number of
+  // crossings, and keep the lines for short branches short themselves.
+  b .Llabel5
+  b .Llabel4
+  b .Llabel3
+.Llabel3:
+  nop
+.Llabel4:
+  nop
+.Llabel5:
+  nop
+
+  // Sometimes crossings can't be avoided.
+  b .Llabel6
+  b .Llabel7
+.Llabel6:
+  nop
+.Llabel7:
+  nop
+
+  // TODO If a branch goes to another branch instruction, we don't have a way
+  // to represent that. Can we improve on this?
+  b .Llabel8
+.Llabel8:
+  b .Llabel9
+.Llabel9:
+  nop
+
+  // Graph lines need to be drawn on the same output line as relocations.
+  b .Llabel10
+  bl extern_func
+.Llabel10:
+  nop
diff --git a/llvm/test/tools/llvm-objdump/visualize-jumps-arm.s b/llvm/test/tools/llvm-objdump/visualize-jumps-arm.s
new file mode 100644
index 00000000000000..6855e6ff84e32a
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/visualize-jumps-arm.s
@@ -0,0 +1,54 @@
+// RUN: llvm-mc < %s -triple armv8a -filetype=obj | \
+// RUN:   llvm-objdump --triple armv8a -d --visualize-jumps=unicode - | \
+// RUN:   diff - %p/Inputs/visualize-jumps-arm-unicode.txt
+
+// RUN: llvm-mc < %s -triple armv8a -filetype=obj | \
+// RUN:   llvm-objdump --triple armv8a -d --visualize-jumps=ascii - | \
+// RUN:   diff - %p/Inputs/visualize-jumps-arm-ascii.txt
+
+test_func:
+  // Relocated instructions don't get control-flow edges.
+  bl extern_func
+  b extern_func
+  
+  // Two branches to the same label, one forward and one backward.
+  b .Llabel1
+.Llabel1:
+  nop
+  b .Llabel1
+
+  // Branch to self, no CFG edge shown
+  b .
+
+  // Conditional branches
+  beq .Llabel2
+.Llabel2:
+  nop
+
+  // Branches are sorted with shorter ones to the right, to reduce number of
+  // crossings, and keep the lines for short branches short themselves.
+  b .Llabel5
+  b .Llabel4
+  b .Llabel3
+.Llabel3:
+  nop
+.Llabel4:
+  nop
+.Llabel5:
+  nop
+
+  // Sometimes crossings can't be avoided.
+  b .Llabel6
+  b .Llabel7
+.Llabel6:
+  nop
+.Llabel7:
+  nop
+
+  // TODO If a branch goes to another branch instruction, we don't have a way
+  // to represent that. Can we improve on this?
+  b .Llabel8
+.Llabel8:
+  b .Llabel9
+.Llabel9:
+  nop
diff --git a/llvm/test/tools/llvm-objdump/visualize-jumps-thumb.s b/llvm/test/tools/llvm-objdump/visualize-jumps-thumb.s
new file mode 100644
index 00000000000000..8be73d3aa4c946
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/visualize-jumps-thumb.s
@@ -0,0 +1,63 @@
+// RUN: llvm-mc < %s -triple thumbv8a -filetype=obj | \
+// RUN:   llvm-objdump --triple thumbv8a -d --visualize-jumps=unicode - | \
+// RUN:   diff - %p/Inputs/visualize-jumps-thumb-unicode.txt
+
+// RUN: llvm-mc < %s -triple thumbv8a -filetype=obj | \
+// RUN:   llvm-objdump --triple thumbv8a -d --visualize-jumps=ascii - | \
+// RUN:   diff - %p/Inputs/visualize-jumps-thumb-ascii.txt
+
+test_func:
+  // Relocated instructions don't get control-flow edges.
+  bl extern_func
+  b extern_func
+  
+  // Two branches to the same label, one forward and one backward.
+  b .Llabel1
+.Llabel1:
+  nop
+  b .Llabel1
+
+  // Branch to self, no CFG edge shown
+  b .
+
+  // Different branch instructions
+  b.w .Llabel2
+  beq .Llabel2
+  bne.w .Llabel2
+  cbz r0, .Llabel2
+  it le
+  ble .Llabel2
+  nop
+.Llabel2:
+  nop
+.Llabel2.1:
+  nop
+
+  // Branches are sorted with shorter ones to the right, to reduce number of
+  // crossings, and keep the lines for short branches short themselves.
+  b .Llabel5
+  b .Llabel4
+  b .Llabel3
+.Llabel3:
+  nop
+.Llabel4:
+  nop
+.Llabel5:
+  nop
+
+  // Sometimes crossings can't be avoided.
+  b ....
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/74858


More information about the llvm-commits mailing list