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,18 @@ /// 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; + // setParsingInlineAsm - true if parsing MS-style inline assembly + virtual void setParsingInlineAsm(bool V) { + setInlineAsmKind(V ? MAK_MSInline : MAK_Raw); + } + + /// setInlineAsmKind - set the style of inline assembly being parsed + virtual void setInlineAsmKind(MCAsmKind V) = 0; + + /// getInlineAsmKind - get the style of inline assembly being parsed + /// + /// \return The style of inline assembly being parsed or MAK_Raw if not inline + 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,21 @@ unsigned getAvailableFeatures() const { return AvailableFeatures; } void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } - bool isParsingInlineAsm () { return ParsingInlineAsm; } - void setParsingInlineAsm (bool Value) { ParsingInlineAsm = Value; } + /// isParsingMSInlineAsm - are we parsing MS-style inline assembly + // + /// \return true if parsing MS-style of inline assembly + bool isParsingMSInlineAsm() { return AsmKind == MAK_MSInline; } + + /// isParsingAnyInlineAsm - are we parsing any style inline assembly + bool isParsingAnyInlineAsm() { return AsmKind != MAK_Raw; } + + MCAsmKind getInlineAsmKind () { return AsmKind; } + void setInlineAsmKind (MCAsmKind Value) { AsmKind = Value; } + + // Legacy function to set MS-style. Used by clang. + void setParsingInlineAsm(bool Value) { + setInlineAsmKind(Value ? MAK_MSInline : MAK_Raw); + } 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 @@ -178,9 +178,6 @@ /// \brief is Darwin compatibility enabled? bool IsDarwin; - /// \brief Are we parsing ms-style inline assembly? - bool ParsingInlineAsm; - public: AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, const MCAsmInfo &MAI); @@ -218,8 +215,8 @@ virtual const AsmToken &Lex(); - void setParsingInlineAsm(bool V) { ParsingInlineAsm = V; } - bool isParsingInlineAsm() { return ParsingInlineAsm; } + void setParsingInlineAsm(bool V) { setInlineAsmKind(MAK_MSInline); } + bool isParsingMSInlineAsm() { return getInlineAsmKind() == MAK_MSInline; } bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, @@ -242,6 +239,13 @@ virtual void eatToEndOfStatement(); virtual void checkForValidSection(); + + void setInlineAsmKind(MCAsmKind V) { + getTargetParser().setInlineAsmKind(V); + } + MCAsmKind getInlineAsmKind() { + return getTargetParser().getInlineAsmKind(); + } /// } private: @@ -482,8 +486,7 @@ const MCAsmInfo &_MAI) : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM), PlatformParser(0), CurBuffer(0), MacrosEnabledFlag(true), - CppHashLineNumber(0), AssemblerDialect(~0U), IsDarwin(false), - ParsingInlineAsm(false) { + CppHashLineNumber(0), AssemblerDialect(~0U), IsDarwin(false) { // Save the old handler. SavedDiagHandler = SrcMgr.getDiagHandler(); SavedDiagContext = SrcMgr.getDiagContext(); @@ -682,7 +685,7 @@ } void AsmParser::checkForValidSection() { - if (!ParsingInlineAsm && !getStreamer().getCurrentSection().first) { + if (!isParsingMSInlineAsm() && !getStreamer().getCurrentSection().first) { TokError("expected section directive before assembly directive"); Out.InitToTextSection(); } @@ -1269,7 +1272,7 @@ return Error(IDLoc, "invalid symbol redefinition"); // Emit the label. - if (!ParsingInlineAsm) + if (!isParsingMSInlineAsm()) Out.EmitLabel(Sym); // If we are generating dwarf for assembly source files then gather the @@ -1514,12 +1517,12 @@ } // __asm _emit or __asm __emit - if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit" || + if (isParsingMSInlineAsm() && (IDVal == "_emit" || IDVal == "__emit" || IDVal == "_EMIT" || IDVal == "__EMIT")) return parseDirectiveMSEmit(IDLoc, Info, IDVal.size()); // __asm align - if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN")) + if (isParsingMSInlineAsm() && (IDVal == "align" || IDVal == "ALIGN")) return parseDirectiveMSAlign(IDLoc, Info); checkForValidSection(); @@ -1593,7 +1596,7 @@ unsigned ErrorInfo; HadError = getTargetParser().MatchAndEmitInstruction( IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo, - ParsingInlineAsm); + isParsingMSInlineAsm()); } // Don't skip the rest of the line, the instruction parser is responsible for 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 (isParsingAnyInlineAsm()) + 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 (isParsingAnyInlineAsm()) + 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 (isParsingAnyInlineAsm()) + 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 (!isParsingMSInlineAsm()) { 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 (isParsingMSInlineAsm() && 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 (isParsingMSInlineAsm()) 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 (!isParsingMSInlineAsm()) { // 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 (isParsingMSInlineAsm() && "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 (isParsingMSInlineAsm()) InstInfo->AsmRewrites->push_back( AsmRewrite(AOK_ImmPrefix, ImmDispToken.getLoc())); @@ -1481,7 +1481,7 @@ const MCExpr *Val; SMLoc End; - if (!isParsingInlineAsm()) { + if (!isParsingMSInlineAsm()) { 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 (!isParsingMSInlineAsm()) { 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 (isParsingMSInlineAsm() && 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 (isParsingMSInlineAsm() && 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 (isParsingMSInlineAsm()) { 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 (isParsingMSInlineAsm()) { 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