ARM: fix WoA PEI instruction selection
authorSaleem Abdulrasool <compnerd@compnerd.org>
Wed, 7 May 2014 03:03:27 +0000 (03:03 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Wed, 7 May 2014 03:03:27 +0000 (03:03 +0000)
The ARM::BLX instruction is an ARM mode instruction.  The Windows on ARM target
is limited to Thumb instructions.  Correctly use the thumb mode tBLXr
instruction.  This would manifest as an errant write into the object file as the
instruction is 4-bytes in length rather than 2.  The result would be a corrupted
object file that would eventually result in an executable that would crash at
runtime.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208152 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMFrameLowering.cpp
test/CodeGen/ARM/Windows/chkstk-movw-movt-isel.ll [new file with mode: 0644]

index 5a114a94e6f88b5b7254bb43ec8a5f74352488a2..8da7fb89401ab1b44123776329aff1baee8ffbdd 100644 (file)
@@ -319,7 +319,8 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const {
       BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), ARM::R12)
         .addExternalSymbol("__chkstk");
 
-      BuildMI(MBB, MBBI, dl, TII.get(ARM::BLX))
+      BuildMI(MBB, MBBI, dl, TII.get(ARM::tBLXr))
+        .addImm((unsigned)ARMCC::AL).addReg(0)
         .addReg(ARM::R12, RegState::Kill)
         .addReg(ARM::R4, RegState::Implicit);
       break;
diff --git a/test/CodeGen/ARM/Windows/chkstk-movw-movt-isel.ll b/test/CodeGen/ARM/Windows/chkstk-movw-movt-isel.ll
new file mode 100644 (file)
index 0000000..a82f614
--- /dev/null
@@ -0,0 +1,27 @@
+; RUN: llc -mtriple thumbv7--windows-itanium -code-model large -filetype obj -o - %s \
+; RUN:    | llvm-objdump -no-show-raw-insn -d - | FileCheck %s
+
+; ModuleID = 'reduced.c'
+target datalayout = "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "thumbv7--windows-itanium"
+
+define arm_aapcs_vfpcc i8 @isel(i32 %i) {
+entry:
+  %i.addr = alloca i32, align 4
+  %buffer = alloca [4096 x i8], align 1
+  store i32 %i, i32* %i.addr, align 4
+  %0 = load i32* %i.addr, align 4
+  %rem = urem i32 %0, 4096
+  %arrayidx = getelementptr inbounds [4096 x i8]* %buffer, i32 0, i32 %rem
+  %1 = load volatile i8* %arrayidx, align 1
+  ret i8 %1
+}
+
+; CHECK-LABEL: isel
+; CHECK: push {r4, r5}
+; CHECK: movw r4, #{{\d*}}
+; CHECK: movw r12, #0
+; CHECK: movt r12, #0
+; CHECK: blx r12
+; CHECK: sub.w sp, sp, r4
+