const char *trapname(int trapno) {
  static const char *const excnames[] = {"Divide error",
                                         "Debug",
                                         "Non-Maskable Interrupt",
                                         "Breakpoint",
                                         "Overflow",
                                         "BOUND Range Exceeded",
                                         "Invalid Opcode",
                                         "Device Not Available",
                                         "Double Fault",
                                         "Coprocessor Segment Overrun",
                                         "Invalid TSS",
                                         "Segment Not Present",
                                         "Stack Fault",
                                         "General Protection",
                                         "Page Fault",
                                         "(unknown trap)",
                                         "x87 FPU Floating-Point Error",
                                         "Alignment Check",
                                         "Machine-Check",
                                         "SIMD Floating-Point Exception"};
  if (trapno < sizeof(excnames) / sizeof(excnames[0]))
    return excnames[trapno];
  if (trapno == 48)
    return "System call";
  if (trapno >= 32 && trapno < 32 + 16)
    return "Hardware Interrupt";
  return "(unknown trap)";
}


x86 assembly (clang, -O0):
<trapname>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0xc(%rbp)
movslq -0xc(%rbp),%rax
cmp    $0x14,%rax
jae    112d <trapname+0x2d>
movslq -0xc(%rbp),%rcx
lea    0x2c90(%rip),%rax
mov    (%rax,%rcx,8),%rax
mov    %rax,-0x8(%rbp)
jmp    1176 <trapname+0x76>
cmpl   $0x30,-0xc(%rbp)
jne    1147 <trapname+0x47>
lea    0x1014(%rip),%rax
mov    %rax,-0x8(%rbp)
jmp    1176 <trapname+0x76>
cmpl   $0x20,-0xc(%rbp)
jl     116b <trapname+0x6b>
cmpl   $0x30,-0xc(%rbp)
jge    116b <trapname+0x6b>
lea    0xffc(%rip),%rax
mov    %rax,-0x8(%rbp)
jmp    1176 <trapname+0x76>
lea    0xf78(%rip),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<trapname>:
cmp    $0x13,%edi
ja     1116 <trapname+0x16>
mov    %edi,%eax
lea    0xef2(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
ret
cmp    $0x30,%edi
jne    1123 <trapname+0x23>
lea    0x1080(%rip),%rax
ret
and    $0xfffffff0,%edi
cmp    $0x20,%edi
lea    0x107e(%rip),%rcx
lea    0x1003(%rip),%rax
cmove  %rcx,%rax
ret

LLVM IR (-O0):
@trapname.excnames = internal constant [20 x i8*] [i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i32 0, i32 0), i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.2, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.3, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.4, i32 0, i32 0), i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.5, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.6, i32 0, i32 0), i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.7, i32 0, i32 0), i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.8, i32 0, i32 0), i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.9, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.10, i32 0, i32 0), i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.11, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.12, i32 0, i32 0), i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.13, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.14, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.15, i32 0, i32 0), i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str.16, i32 0, i32 0), i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.17, i32 0, i32 0), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.18, i32 0, i32 0), i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.19, i32 0, i32 0)]
@.str = [13 x i8] c"Divide error\00"
@.str.1 = [6 x i8] c"Debug\00"
@.str.2 = [23 x i8] c"Non-Maskable Interrupt\00"
@.str.3 = [11 x i8] c"Breakpoint\00"
@.str.4 = [9 x i8] c"Overflow\00"
@.str.5 = [21 x i8] c"BOUND Range Exceeded\00"
@.str.6 = [15 x i8] c"Invalid Opcode\00"
@.str.7 = [21 x i8] c"Device Not Available\00"
@.str.8 = [13 x i8] c"Double Fault\00"
@.str.9 = [28 x i8] c"Coprocessor Segment Overrun\00"
@.str.10 = [12 x i8] c"Invalid TSS\00"
@.str.11 = [20 x i8] c"Segment Not Present\00"
@.str.12 = [12 x i8] c"Stack Fault\00"
@.str.13 = [19 x i8] c"General Protection\00"
@.str.14 = [11 x i8] c"Page Fault\00"
@.str.15 = [15 x i8] c"(unknown trap)\00"
@.str.16 = [29 x i8] c"x87 FPU Floating-Point Error\00"
@.str.17 = [16 x i8] c"Alignment Check\00"
@.str.18 = [14 x i8] c"Machine-Check\00"
@.str.19 = [30 x i8] c"SIMD Floating-Point Exception\00"
@.str.20 = [12 x i8] c"System call\00"
@.str.21 = [19 x i8] c"Hardware Interrupt\00"
define i8* @trapname(i32 %0) {
%2 = alloca i8*
%3 = alloca i32
store i32 %0, i32* %3
%4 = load i32, i32* %3
%5 = sext i32 %4 to i64
%6 = icmp ult i64 %5, 20
br i1 %6, label %7, label %12
7: ; preds = %1
%8 = load i32, i32* %3
%9 = sext i32 %8 to i64
%10 = getelementptr inbounds [20 x i8*], [20 x i8*]* @trapname.excnames, i64 0, i64 %9
%11 = load i8*, i8** %10
store i8* %11, i8** %2
br label %24
12: ; preds = %1
%13 = load i32, i32* %3
%14 = icmp eq i32 %13, 48
br i1 %14, label %15, label %16
15: ; preds = %12
store i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.20, i64 0, i64 0), i8** %2
br label %24
16: ; preds = %12
%17 = load i32, i32* %3
%18 = icmp sge i32 %17, 32
br i1 %18, label %19, label %23
19: ; preds = %16
%20 = load i32, i32* %3
%21 = icmp slt i32 %20, 48
br i1 %21, label %22, label %23
22: ; preds = %19
store i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.21, i64 0, i64 0), i8** %2
br label %24
23: ; preds = %19, %16
store i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.15, i64 0, i64 0), i8** %2
br label %24
24: ; preds = %23, %22, %15, %7
%25 = load i8*, i8** %2
ret i8* %25
}

LLVM IR (-O2):
@reltable.trapname = internal unnamed_addr constant [20 x i32] [i32 trunc (i64 sub (i64 ptrtoint ([13 x i8]* @.str to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([6 x i8]* @.str.1 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([23 x i8]* @.str.2 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([11 x i8]* @.str.3 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([9 x i8]* @.str.4 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([21 x i8]* @.str.5 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([15 x i8]* @.str.6 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([21 x i8]* @.str.7 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([13 x i8]* @.str.8 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([28 x i8]* @.str.9 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([12 x i8]* @.str.10 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([20 x i8]* @.str.11 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([12 x i8]* @.str.12 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([19 x i8]* @.str.13 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([11 x i8]* @.str.14 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([15 x i8]* @.str.15 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([29 x i8]* @.str.16 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([16 x i8]* @.str.17 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([14 x i8]* @.str.18 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([30 x i8]* @.str.19 to i64), i64 ptrtoint ([20 x i32]* @reltable.trapname to i64)) to i32)]
@.str = [13 x i8] c"Divide error\00"
@.str.1 = [6 x i8] c"Debug\00"
@.str.2 = [23 x i8] c"Non-Maskable Interrupt\00"
@.str.3 = [11 x i8] c"Breakpoint\00"
@.str.4 = [9 x i8] c"Overflow\00"
@.str.5 = [21 x i8] c"BOUND Range Exceeded\00"
@.str.6 = [15 x i8] c"Invalid Opcode\00"
@.str.7 = [21 x i8] c"Device Not Available\00"
@.str.8 = [13 x i8] c"Double Fault\00"
@.str.9 = [28 x i8] c"Coprocessor Segment Overrun\00"
@.str.10 = [12 x i8] c"Invalid TSS\00"
@.str.11 = [20 x i8] c"Segment Not Present\00"
@.str.12 = [12 x i8] c"Stack Fault\00"
@.str.13 = [19 x i8] c"General Protection\00"
@.str.14 = [11 x i8] c"Page Fault\00"
@.str.15 = [15 x i8] c"(unknown trap)\00"
@.str.16 = [29 x i8] c"x87 FPU Floating-Point Error\00"
@.str.17 = [16 x i8] c"Alignment Check\00"
@.str.18 = [14 x i8] c"Machine-Check\00"
@.str.19 = [30 x i8] c"SIMD Floating-Point Exception\00"
@.str.20 = [12 x i8] c"System call\00"
@.str.21 = [19 x i8] c"Hardware Interrupt\00"
define i8* @trapname(i32 %0) {
%2 = icmp ult i32 %0, 20
br i1 %2, label %3, label %7
3: ; preds = %1
%4 = zext i32 %0 to i64
%5 = shl i64 %4, 2
%6 = call i8* @llvm.load.relative.i64(i8* bitcast ([20 x i32]* @reltable.trapname to i8*), i64 %5)
br label %13
7: ; preds = %1
%8 = icmp eq i32 %0, 48
br i1 %8, label %13, label %9
9: ; preds = %7
%10 = and i32 %0, -16
%11 = icmp eq i32 %10, 32
%12 = select i1 %11, i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.21, i64 0, i64 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.15, i64 0, i64 0)
br label %13
13: ; preds = %9, %7, %3
%14 = phi i8* [ %6, %3 ], [ getelementptr inbounds ([12 x i8], [12 x i8]* @.str.20, i64 0, i64 0), %7 ], [ %12, %9 ]
ret i8* %14
}