Index: llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp +++ llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp @@ -1204,6 +1204,10 @@ MCTargetStreamer &TS = *OutStreamer->getTargetStreamer(); ARMTargetStreamer &ATS = static_cast(TS); + const MachineFunction &MF = *MI->getParent()->getParent(); + const ARMSubtarget &STI = MF.getSubtarget(); + unsigned FramePtr = STI.useR7AsFramePointer() ? ARM::R7 : ARM::R11; + // If we just ended a constant pool, mark it as such. if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) { OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); @@ -1884,13 +1888,33 @@ .addImm(ARMCC::AL) .addReg(0)); - EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) - .addReg(ARM::R7) - .addReg(SrcReg) - .addImm(0) - // Predicate. - .addImm(ARMCC::AL) - .addReg(0)); + if (STI.isTargetDarwin() || STI.isTargetWindows()) { + // These platforms always use the same frame register + EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) + .addReg(FramePtr) + .addReg(SrcReg) + .addImm(0) + // Predicate. + .addImm(ARMCC::AL) + .addReg(0)); + } else { + // If the calling code might use either R7 or R11 as + // frame pointer register, restore it into both. + EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) + .addReg(ARM::R7) + .addReg(SrcReg) + .addImm(0) + // Predicate. + .addImm(ARMCC::AL) + .addReg(0)); + EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) + .addReg(ARM::R11) + .addReg(SrcReg) + .addImm(0) + // Predicate. + .addImm(ARMCC::AL) + .addReg(0)); + } assert(Subtarget->hasV4TOps()); EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BX) @@ -1934,13 +1958,33 @@ .addImm(ARMCC::AL) .addReg(0)); - EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) - .addReg(ARM::R7) - .addReg(SrcReg) - .addImm(0) - // Predicate. - .addImm(ARMCC::AL) - .addReg(0)); + if (STI.isTargetDarwin() || STI.isTargetWindows()) { + // These platforms always use the same frame register + EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) + .addReg(FramePtr) + .addReg(SrcReg) + .addImm(0) + // Predicate. + .addImm(ARMCC::AL) + .addReg(0)); + } else { + // If the calling code might use either R7 or R11 as + // frame pointer register, restore it into both. + EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) + .addReg(ARM::R7) + .addReg(SrcReg) + .addImm(0) + // Predicate. + .addImm(ARMCC::AL) + .addReg(0)); + EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) + .addReg(ARM::R11) + .addReg(SrcReg) + .addImm(0) + // Predicate. + .addImm(ARMCC::AL) + .addReg(0)); + } EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBX) .addReg(ScratchReg) Index: llvm/trunk/test/CodeGen/ARM/setjmp_longjmp.ll =================================================================== --- llvm/trunk/test/CodeGen/ARM/setjmp_longjmp.ll +++ llvm/trunk/test/CodeGen/ARM/setjmp_longjmp.ll @@ -1,4 +1,6 @@ ; RUN: llc %s -o - | FileCheck %s +; RUN: llc -mtriple=armv7-linux -exception-model sjlj %s -o - | FileCheck %s -check-prefix CHECK-LINUX +; RUN: llc -mtriple=thumbv7-win32 -exception-model sjlj %s -o - | FileCheck %s -check-prefix CHECK-WIN32 target triple = "armv7-apple-ios" declare i32 @llvm.eh.sjlj.setjmp(i8*) @@ -28,6 +30,16 @@ ; CHECK-NEXT: ldr [[DESTREG:r[0-9]+]], {{\[}}[[BUFREG]], #4] ; CHECK-NEXT: ldr r7, {{\[}}[[BUFREG]]{{\]}} ; CHECK-NEXT: bx [[DESTREG]] + +; CHECK-LINUX: ldr sp, [{{\s*}}[[BUFREG:r[0-9]+]], #8] +; CHECK-LINUX-NEXT: ldr [[DESTREG:r[0-9]+]], {{\[}}[[BUFREG]], #4] +; CHECK-LINUX-NEXT: ldr r7, {{\[}}[[BUFREG]]{{\]}} +; CHECK-LINUX-NEXT: ldr r11, {{\[}}[[BUFREG]]{{\]}} +; CHECK-LINUX-NEXT: bx [[DESTREG]] + +; CHECK-WIN32: ldr.w r11, [{{\s*}}[[BUFREG:r[0-9]+]]] +; CHECK-WIN32-NEXT: ldr.w sp, {{\[}}[[BUFREG]], #8] +; CHECK-WIN32-NEXT: ldr.w pc, {{\[}}[[BUFREG]], #4] define void @foobar() { entry: %buf = alloca [5 x i8*], align 4