Skip to content

switch statement can cause invalid thumb addresses #11188

@llvmbot

Description

@llvmbot
Bugzilla Link 10816
Resolution FIXED
Resolved on Nov 07, 2018 00:22
Version trunk
OS Linux
Attachments example source code, and all intermediate files as well as makefile to produce the problem.
Reporter LLVM Bugzilla Contributor
CC @efriedma-quic

Extended Description

both with llvm 2.9 and trunk svn 138852 a simple switch statement like this:

switch(x)
{
case 0: fun_00(x); break;
case 1: fun_01(x); break;
case 2: fun_02(x); break;
case 3: fun_03(x); break;
case 4: fun_04(x); break;
case 5: fun_05(x); break;
case 6: fun_06(x); break;
case 7: fun_07(x); break;
case 8: fun_08(x); break;
case 9: fun_09(x); break;
default: fun_11(x); break;
}

is turned into a look up table

%x.addr = alloca i32, align 4
store i32 %x, i32* %x.addr, align 4
%tmp = load i32* %x.addr, align 4
switch i32 %tmp, label %sw.default [
i32 0, label %sw.bb
i32 1, label %sw.bb2
i32 2, label %sw.bb4
i32 3, label %sw.bb6
i32 4, label %sw.bb8
i32 5, label %sw.bb10
i32 6, label %sw.bb12
i32 7, label %sw.bb14
i32 8, label %sw.bb16
i32 9, label %sw.bb18
]

90: 0080 lsls r0, r0, #​2
92: a202 add r2, pc, #​8 ; (adr r2, 9c <more_fun+0x18>)
94: 1880 adds r0, r0, r2
96: 6800 ldr r0, [r0, #​0]
98: 4687 mov pc, r0
9a: 46c0 nop ; (mov r8, r8)
9c: 000000c4 andeq r0, r0, r4, asr #​1
a0: 000000ce andeq r0, r0, lr, asr #​1
a4: 000000d8 ldrdeq r0, [r0], -r8
a8: 000000e2 andeq r0, r0, r2, ror #​1
ac: 000000ec andeq r0, r0, ip, ror #​1
b0: 000000f6 strdeq r0, [r0], -r6
b4: 00000100 andeq r0, r0, r0, lsl #​2
b8: 0000010a andeq r0, r0, sl, lsl #​2
bc: 00000114 andeq r0, r0, r4, lsl r1
c0: 0000011e andeq r0, r0, lr, lsl r1

The problem is in thumb mode the lsbit of the pc needs to remain set, this is causing an even number to be placed in the program counter. It is interesting that a mov pc,r0 is used and not a bx r0 (which would have made the thing crash much sooner).

.LJTI13_0_0:
.long .LBB13_2
.long .LBB13_3
.long .LBB13_4
.long .LBB13_5

A very ugly hack would be

.LJTI13_0_0:
.long .LBB13_2+1
.long .LBB13_3+1

but it would work (if llc knew that these were lookup table addresses to thumb code, addresses to data would not work with the + 1).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugzillaIssues migrated from bugzillaclangClang issues not falling into any other category

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions