Index: lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -33,6 +33,7 @@ #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; namespace { @@ -114,14 +115,12 @@ OutContext, OutStreamer, *MAI)); - // FIXME: It would be nice if we can avoid createing a new instance of - // MCSubtargetInfo here given TargetSubtargetInfo is available. However, - // we have to watch out for asm directives which can change subtarget - // state. e.g. .code 16, .code 32. - OwningPtr - STI(TM.getTarget().createMCSubtargetInfo(TM.getTargetTriple(), - TM.getTargetCPU(), - TM.getTargetFeatureString())); + // Reuse the existing Subtarget, because the AsmParser will + // modify it. For example, when switching between ARM and + // Thumb mode. + const MCSubtargetInfo* STC = TM.getSubtargetImpl(); + MCSubtargetInfo* STI = const_cast(STC); + OwningPtr TAP(TM.getTarget().createMCAsmParser(*STI, *Parser, *MII)); if (!TAP) @@ -129,12 +128,16 @@ " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); + uint64_t OrigFB = STI->getFeatureBits(); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); if (Res && !HasDiagHandler) report_fatal_error("Error parsing inline asm\n"); + + if (STI->getFeatureBits() != OrigFB) + report_fatal_error("Inline assembly did not restore ARM mode\n"); } static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI, Index: test/CodeGen/ARM/inlineasm-switch-mode-badly.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/inlineasm-switch-mode-badly.ll @@ -0,0 +1,10 @@ +;RUN: not llc -mtriple=thumbv7-linux-gnueabi -filetype=obj 2>&1 < %s | FileCheck %s + +target triple = "thumbv7--linux-gnueabi" + +define hidden void @bah(i8* %start) #0 align 2 { + %1 = ptrtoint i8* %start to i32 + %2 = tail call i32 asm sideeffect "@ Enter ARM Mode \0A\09adr r3, 1f \0A\09bx r3 \0A\09.align 2 \0A\09.code 32 \0A1: push {r7} \0A\09mov r7, $4 \0A\09svc 0x0 \0A\09pop {r7} \0A\09", "={r0},{r0},{r1},{r2},r,~{r3}"(i32 %1, i32 %1, i32 0, i32 983042) #3 + ret void +} +; CHECK: Inline assembly did not restore ARM mode Index: test/CodeGen/ARM/inlineasm-switch-mode.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/inlineasm-switch-mode.ll @@ -0,0 +1,12 @@ +;RUN: llc -mtriple=thumbv7-linux-gnueabi -filetype=obj < %s | llvm-objdump -arch=thumb -d - | FileCheck %s + +target triple = "thumbv7--linux-gnueabi" + +define hidden void @bah(i8* %start) #0 align 2 { + %1 = ptrtoint i8* %start to i32 + %2 = tail call i32 asm sideeffect "@ Enter ARM Mode \0A\09adr r3, 1f \0A\09bx r3 \0A\09.align 2 \0A\09.code 32 \0A1: push {r7} \0A\09mov r7, $4 \0A\09svc 0x0 \0A\09pop {r7} \0A\09@ Enter THUMB Mode\0A\09adr r3, 2f+1 \0A\09bx r3 \0A\09.code 16 \0A2: \0A\09", "={r0},{r0},{r1},{r2},r,~{r3}"(i32 %1, i32 %1, i32 0, i32 983042) #3 + ret void +} +; CHECK: $a +; CHECK-NEXT: 04 70 +; CHECK-NEXT: 2d e5