RTL is inspired by Lisp lists. It has both an internal form, made up of structures that point at other structures, and a textual form that is used in the machine description and in printed debugging dumps.
The structure representation contains a variable length array of unions. This makes it impossible for debuggers like gdb to display sensibly, but gcc has helper functions for gdb.
(gdb) p *insn
$1 = {code = INSN, mode = VOIDmode, jump = 0, call = 0, unchanging = 0,
volatil = 0, in_struct = 0, used = 0, integrated = 1, frame_related = 0,
fld = {{rtwint = 22, rtint = 22, rtuint = 22,
rtstr = 0x16 <Address 0x16 out of bounds>, rtx = 0x16, rtvec = 0x16,
rttype = DCmode, rt_addr_diff_vec_flags = {min_align = 22,
base_after_vec = 0, min_after_vec = 0, max_after_vec = 0,
min_after_base = 0, max_after_base = 0, offset_unsigned = 0, 0,
scale = 0}, rt_cselib = 0x16, rtbit = 0x16, rttree = 0x16, bb = 0x16}}}
(gdb) p debug_rtx (insn)
(insn/i 22 21 23 (set (reg:DI 100)
(lshiftrt:DI (reg/v:DI 99)
(const_int 16 [0x10]))) 264 {*lshrdi3_internal1} (insn_list 21 (nil))
(expr_list:REG_DEAD (reg/v:DI 99)
(nil)))