Index: include/llvm/MC/MCParser/MCAsmParser.h =================================================================== --- include/llvm/MC/MCParser/MCAsmParser.h +++ include/llvm/MC/MCParser/MCAsmParser.h @@ -59,6 +59,12 @@ typedef MCAsmParserSemaCallback::InlineAsmIdentifierInfo InlineAsmIdentifierInfo; +enum MCAsmKind { + MAK_Raw = 0, // Raw assembly file + MAK_MsInline, // MS-style inline assembly + MAK_GnuInline // GNU inline assembly +}; + /// MCAsmParser - Generic assembler parser interface, for use by target specific /// assembly parsers. class MCAsmParser { @@ -105,8 +111,8 @@ /// Run - Run the parser on the input source buffer. virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0; - virtual void setParsingInlineAsm(bool V) = 0; - virtual bool isParsingInlineAsm() = 0; + virtual void setInlineAsmKind(MCAsmKind V) = 0; + virtual MCAsmKind getInlineAsmKind() = 0; /// parseMSInlineAsm - Parse ms-style inline assembly. virtual bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, Index: include/llvm/MC/MCTargetAsmParser.h =================================================================== --- include/llvm/MC/MCTargetAsmParser.h +++ include/llvm/MC/MCTargetAsmParser.h @@ -90,8 +90,8 @@ /// AvailableFeatures - The current set of available features. unsigned AvailableFeatures; - /// ParsingInlineAsm - Are we parsing ms-style inline assembly? - bool ParsingInlineAsm; + /// AsmKind - Are we parsing ms-style or GNU inline assembly? + MCAsmKind AsmKind; /// SemaCallback - The Sema callback implementation. Must be set when parsing /// ms-style inline assembly. @@ -103,8 +103,8 @@ unsigned getAvailableFeatures() const { return AvailableFeatures; } void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } - bool isParsingInlineAsm () { return ParsingInlineAsm; } - void setParsingInlineAsm (bool Value) { ParsingInlineAsm = Value; } + MCAsmKind getInlineAsmKind () { return AsmKind; } + void setInlineAsmKind (MCAsmKind Value) { AsmKind = Value; } void setSemaCallback(MCAsmParserSemaCallback *Callback) { SemaCallback = Callback; Index: lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -129,6 +129,7 @@ " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); + Parser->setInlineAsmKind(MAK_GnuInline); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -242,6 +242,13 @@ virtual void eatToEndOfStatement(); virtual void checkForValidSection(); + + void setInlineAsmKind(MCAsmKind V) { + getTargetParser().setInlineAsmKind(V); + } + MCAsmKind getInlineAsmKind() { + return getTargetParser().getInlineAsmKind(); + } /// } private: Index: lib/MC/MCParser/MCTargetAsmParser.cpp =================================================================== --- lib/MC/MCParser/MCTargetAsmParser.cpp +++ lib/MC/MCParser/MCTargetAsmParser.cpp @@ -11,7 +11,7 @@ using namespace llvm; MCTargetAsmParser::MCTargetAsmParser() - : AvailableFeatures(0), ParsingInlineAsm(false) + : AvailableFeatures(0), AsmKind(MAK_Raw) { } Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -7840,6 +7840,9 @@ /// parseDirectiveThumb /// ::= .thumb bool ARMAsmParser::parseDirectiveThumb(SMLoc L) { + if (getInlineAsmKind() != MAK_Raw) + return Error(L, ".thumb directive is not permitted in inline assembly"); + if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(L, "unexpected token in directive"); Parser.Lex(); @@ -7856,6 +7859,9 @@ /// parseDirectiveARM /// ::= .arm bool ARMAsmParser::parseDirectiveARM(SMLoc L) { + if (getInlineAsmKind() != MAK_Raw) + return Error(L, ".arm directive is not permitted in inline assembly"); + if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(L, "unexpected token in directive"); Parser.Lex(); @@ -7942,6 +7948,9 @@ else return Error(L, "invalid operand to .code directive"); + if (getInlineAsmKind() != MAK_Raw) + return Error(L, ".code directive is not permitted in inline assembly"); + if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(Parser.getTok().getLoc(), "unexpected token in directive"); Parser.Lex(); Index: lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmParser.cpp +++ lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -1314,7 +1314,7 @@ UpdateLocLex = false; break; } else { - if (!isParsingInlineAsm()) { + if (getInlineAsmKind() != MAK_MsInline) { if (getParser().parsePrimaryExpr(Val, End)) return Error(Tok.getLoc(), "Unexpected identifier!"); } else { @@ -1330,7 +1330,7 @@ return Error(Tok.getLoc(), "Unexpected identifier!"); } case AsmToken::Integer: - if (isParsingInlineAsm() && SM.getAddImmPrefix()) + if (getInlineAsmKind() == MAK_MsInline && SM.getAddImmPrefix()) InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_ImmPrefix, Tok.getLoc())); SM.onInteger(Tok.getIntVal()); @@ -1374,7 +1374,7 @@ if (const MCExpr *Sym = SM.getSym()) { // A symbolic displacement. Disp = Sym; - if (isParsingInlineAsm()) + if (getInlineAsmKind() == MAK_MsInline) RewriteIntelBracExpression(InstInfo->AsmRewrites, SM.getSymName(), ImmDisp, SM.getImm(), BracLoc, StartInBrac, End); @@ -1397,7 +1397,7 @@ int BaseReg = SM.getBaseReg(); int IndexReg = SM.getIndexReg(); int Scale = SM.getScale(); - if (!isParsingInlineAsm()) { + if (getInlineAsmKind() != MAK_MsInline) { // handle [-42] if (!BaseReg && !IndexReg) { if (!SegReg) @@ -1419,7 +1419,7 @@ StringRef &Identifier, InlineAsmIdentifierInfo &Info, bool IsUnevaluatedOperand, SMLoc &End) { - assert (isParsingInlineAsm() && "Expected to be parsing inline assembly."); + assert (getInlineAsmKind() == MAK_MsInline && "Expected to be parsing inline assembly."); Val = 0; StringRef LineBuf(Identifier.data()); @@ -1461,7 +1461,7 @@ ImmDisp = Tok.getIntVal(); AsmToken ImmDispToken = Parser.Lex(); // Eat the integer. - if (isParsingInlineAsm()) + if (getInlineAsmKind() == MAK_MsInline) InstInfo->AsmRewrites->push_back( AsmRewrite(AOK_ImmPrefix, ImmDispToken.getLoc())); @@ -1481,7 +1481,7 @@ const MCExpr *Val; SMLoc End; - if (!isParsingInlineAsm()) { + if (getInlineAsmKind() != MAK_MsInline) { if (getParser().parsePrimaryExpr(Val, End)) return ErrorOperand(Tok.getLoc(), "unknown token in expression"); @@ -1508,7 +1508,7 @@ return ParseIntelBracExpression(/*SegReg=*/0, Start, ImmDisp, Size); const MCExpr *Val; - if (!isParsingInlineAsm()) { + if (getInlineAsmKind() != MAK_MsInline) { if (getParser().parsePrimaryExpr(Val, End)) return ErrorOperand(Tok.getLoc(), "unknown token in expression"); @@ -1544,7 +1544,7 @@ APInt DotDisp; DotDispStr.getAsInteger(10, DotDisp); DotDispVal = DotDisp.getZExtValue(); - } else if (isParsingInlineAsm() && Tok.is(AsmToken::Identifier)) { + } else if (getInlineAsmKind() == MAK_MsInline && Tok.is(AsmToken::Identifier)) { unsigned DotDisp; std::pair BaseMember = DotDispStr.split('.'); if (SemaCallback->LookupInlineAsmField(BaseMember.first, BaseMember.second, @@ -1554,7 +1554,7 @@ } else return Error(Tok.getLoc(), "Unexpected token type!"); - if (isParsingInlineAsm() && Tok.is(AsmToken::Identifier)) { + if (getInlineAsmKind() == MAK_MsInline && Tok.is(AsmToken::Identifier)) { SMLoc Loc = SMLoc::getFromPointer(DotDispStr.data()); unsigned Len = DotDispStr.size(); unsigned Val = OrigDispVal + DotDispVal; @@ -1642,7 +1642,7 @@ SMLoc Start, End; // Offset, length, type and size operators. - if (isParsingInlineAsm()) { + if (getInlineAsmKind() == MAK_MsInline) { StringRef AsmTokStr = Tok.getString(); if (AsmTokStr == "offset" || AsmTokStr == "OFFSET") return ParseIntelOffsetOfOperator(); @@ -1673,7 +1673,7 @@ return 0; int64_t Imm = SM.getImm(); - if (isParsingInlineAsm()) { + if (getInlineAsmKind() == MAK_MsInline) { unsigned Len = Tok.getLoc().getPointer() - Start.getPointer(); if (StartTok.getString().size() == Len) // Just add a prefix if this wasn't a complex immediate expression. Index: test/CodeGen/ARM/2013-12-02-inline-asm-switch-mode.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/2013-12-02-inline-asm-switch-mode.ll @@ -0,0 +1,11 @@ +;RUN: not llc -mtriple=thumbv7-linux-gnueabi -filetype=obj 2>&1 < %s | FileCheck %s +;RUN: not llc -mtriple=armv7-linux-gnueabi -filetype=obj 2>&1 < %s | FileCheck %s + +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: .code directive is not permitted in inline assembly +; CHECK: .code directive is not permitted in inline assembly + Index: test/CodeGen/ARM/2013-12-02-inline-asm-switch-to-arm.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/2013-12-02-inline-asm-switch-to-arm.ll @@ -0,0 +1,11 @@ +;RUN: not llc -mtriple=thumbv7-linux-gnueabi -filetype=obj 2>&1 < %s | FileCheck %s +;RUN: not llc -mtriple=armv7-linux-gnueabi -filetype=obj 2>&1 < %s | FileCheck %s + +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.arm \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.thumb \0A2: \0A\09", "={r0},{r0},{r1},{r2},r,~{r3}"(i32 %1, i32 %1, i32 0, i32 983042) #3 + ret void +} +; CHECK: .arm directive is not permitted in inline assembly +; CHECK: .thumb directive is not permitted in inline assembly + Index: test/CodeGen/ARM/2013-12-02-inline-asm-switch-to-thumb.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/2013-12-02-inline-asm-switch-to-thumb.ll @@ -0,0 +1,10 @@ +;RUN: not llc -mtriple=thumbv7-linux-gnueabi -filetype=obj 2>&1 < %s | FileCheck %s +;RUN: not llc -mtriple=armv7-linux-gnueabi -filetype=obj 2>&1 < %s | FileCheck %s + +define hidden void @bah(i8* %start) #0 align 2 { + %1 = ptrtoint i8* %start to i32 + %2 = tail call i32 asm sideeffect "@ Enter THUMB Mode\0A\09adr r3, 1f+1 \0A\09bx r3 \0A\09.thumb \0A1: \0A\09@ Enter ARM Mode \0A\09adr r3, 2f \0A\09bx r3 \0A\09.align 2 \0A\09.arm \0A2: 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: .thumb directive is not permitted in inline assembly +; CHECK: .arm directive is not permitted in inline assembly