diff --git a/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/llvm/include/llvm/MC/MCParser/MCAsmParser.h --- a/llvm/include/llvm/MC/MCParser/MCAsmParser.h +++ b/llvm/include/llvm/MC/MCParser/MCAsmParser.h @@ -165,8 +165,10 @@ /// 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 setParsingInlineMSAsm(bool V) = 0; + virtual bool isParsingInlineMSAsm() = 0; + + virtual bool isParsingMasm() const { return false; } /// Parse MS-style inline assembly. virtual bool parseMSInlineAsm( diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h --- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h +++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h @@ -329,8 +329,8 @@ /// AvailableFeatures - The current set of available features. FeatureBitset AvailableFeatures; - /// ParsingInlineAsm - Are we parsing ms-style inline assembly? - bool ParsingInlineAsm = false; + /// ParsingInlineMSAsm - Are we parsing ms-style inline assembly? + bool ParsingInlineMSAsm = false; /// SemaCallback - The Sema callback implementation. Must be set when parsing /// ms-style inline assembly. @@ -359,8 +359,8 @@ AvailableFeatures = Value; } - bool isParsingInlineAsm () { return ParsingInlineAsm; } - void setParsingInlineAsm (bool Value) { ParsingInlineAsm = Value; } + bool isParsingInlineMSAsm () { return ParsingInlineMSAsm; } + void setParsingInlineMSAsm (bool Value) { ParsingInlineMSAsm = Value; } MCTargetOptions getTargetOptions() const { return MCOptions; } diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -174,7 +174,7 @@ bool IsDarwin = false; /// Are we parsing ms-style inline assembly? - bool ParsingInlineAsm = false; + bool ParsingInlineMSAsm = false; /// Did we already inform the user about inconsistent MD5 usage? bool ReportedInconsistentMD5 = false; @@ -226,13 +226,13 @@ const AsmToken &Lex() override; - void setParsingInlineAsm(bool V) override { - ParsingInlineAsm = V; + void setParsingInlineMSAsm(bool V) override { + ParsingInlineMSAsm = V; // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and // hex integer literals. Lexer.setLexMasmIntegers(V); } - bool isParsingInlineAsm() override { return ParsingInlineAsm; } + bool isParsingInlineMSAsm() override { return ParsingInlineMSAsm; } bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, @@ -994,7 +994,7 @@ } bool AsmParser::checkForValidSection() { - if (!ParsingInlineAsm && !getStreamer().getCurrentSectionOnly()) { + if (!ParsingInlineMSAsm && !getStreamer().getCurrentSectionOnly()) { Out.InitSections(false); return Error(getTok().getLoc(), "expected section directive before assembly directive"); @@ -1821,7 +1821,7 @@ // implicitly marked as external. MCSymbol *Sym; if (LocalLabelVal == -1) { - if (ParsingInlineAsm && SI) { + if (ParsingInlineMSAsm && SI) { StringRef RewrittenLabel = SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true); assert(!RewrittenLabel.empty() && @@ -1852,7 +1852,7 @@ getTargetParser().doBeforeLabelEmit(Sym); // Emit the label. - if (!getTargetParser().isParsingInlineAsm()) + if (!getTargetParser().isParsingInlineMSAsm()) Out.emitLabel(Sym, IDLoc); // If we are generating dwarf for assembly source files then gather the @@ -2193,15 +2193,15 @@ } // __asm _emit or __asm __emit - if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit" || - IDVal == "_EMIT" || IDVal == "__EMIT")) + if (ParsingInlineMSAsm && (IDVal == "_emit" || IDVal == "__emit" || + IDVal == "_EMIT" || IDVal == "__EMIT")) return parseDirectiveMSEmit(IDLoc, Info, IDVal.size()); // __asm align - if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN")) + if (ParsingInlineMSAsm && (IDVal == "align" || IDVal == "ALIGN")) return parseDirectiveMSAlign(IDLoc, Info); - if (ParsingInlineAsm && (IDVal == "even" || IDVal == "EVEN")) + if (ParsingInlineMSAsm && (IDVal == "even" || IDVal == "EVEN")) Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4); if (checkForValidSection()) return true; @@ -2268,7 +2268,7 @@ uint64_t ErrorInfo; if (getTargetParser().MatchAndEmitInstruction( IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo, - getTargetParser().isParsingInlineAsm())) + getTargetParser().isParsingInlineMSAsm())) return true; } return false; diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -182,7 +182,7 @@ bool IsDarwin = false; /// Are we parsing ms-style inline assembly? - bool ParsingInlineAsm = false; + bool ParsingInlineMSAsm = false; /// Did we already inform the user about inconsistent MD5 usage? bool ReportedInconsistentMD5 = false; @@ -237,13 +237,15 @@ const AsmToken &Lex() override; - void setParsingInlineAsm(bool V) override { - ParsingInlineAsm = V; + void setParsingInlineMSAsm(bool V) override { + ParsingInlineMSAsm = V; // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and // hex integer literals. Lexer.setLexMasmIntegers(V); } - bool isParsingInlineAsm() override { return ParsingInlineAsm; } + bool isParsingInlineMSAsm() override { return ParsingInlineMSAsm; } + + bool isParsingMasm() const override { return true; } bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, @@ -922,7 +924,7 @@ } bool MasmParser::checkForValidSection() { - if (!ParsingInlineAsm && !getStreamer().getCurrentSectionOnly()) { + if (!ParsingInlineMSAsm && !getStreamer().getCurrentSectionOnly()) { Out.InitSections(false); return Error(getTok().getLoc(), "expected section directive before assembly directive"); @@ -1606,7 +1608,7 @@ // implicitly marked as external. MCSymbol *Sym; if (LocalLabelVal == -1) { - if (ParsingInlineAsm && SI) { + if (ParsingInlineMSAsm && SI) { StringRef RewrittenLabel = SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true); assert(!RewrittenLabel.empty() && @@ -1637,7 +1639,7 @@ getTargetParser().doBeforeLabelEmit(Sym); // Emit the label. - if (!getTargetParser().isParsingInlineAsm()) + if (!getTargetParser().isParsingInlineMSAsm()) Out.emitLabel(Sym, IDLoc); // If we are generating dwarf for assembly source files then gather the @@ -1946,15 +1948,15 @@ } // __asm _emit or __asm __emit - if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit" || - IDVal == "_EMIT" || IDVal == "__EMIT")) + if (ParsingInlineMSAsm && (IDVal == "_emit" || IDVal == "__emit" || + IDVal == "_EMIT" || IDVal == "__EMIT")) return parseDirectiveMSEmit(IDLoc, Info, IDVal.size()); // __asm align - if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN")) + if (ParsingInlineMSAsm && (IDVal == "align" || IDVal == "ALIGN")) return parseDirectiveMSAlign(IDLoc, Info); - if (ParsingInlineAsm && (IDVal == "even" || IDVal == "EVEN")) + if (ParsingInlineMSAsm && (IDVal == "even" || IDVal == "EVEN")) Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4); if (checkForValidSection()) return true; @@ -2021,7 +2023,7 @@ uint64_t ErrorInfo; if (getTargetParser().MatchAndEmitInstruction( IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo, - getTargetParser().isParsingInlineAsm())) + getTargetParser().isParsingInlineMSAsm())) return true; } return false; diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -611,9 +611,9 @@ } bool onIdentifierExpr(const MCExpr *SymRef, StringRef SymRefName, const InlineAsmIdentifierInfo &IDInfo, - bool ParsingInlineAsm, StringRef &ErrMsg) { + bool ParsingInlineMSAsm, StringRef &ErrMsg) { // InlineAsm: Treat an enum value as an integer - if (ParsingInlineAsm) + if (ParsingInlineMSAsm) if (IDInfo.isKind(InlineAsmIdentifierInfo::IK_EnumVal)) return onInteger(IDInfo.Enum.EnumVal, ErrMsg); // Treat a symbolic constant like an integer @@ -634,7 +634,7 @@ MemExpr = true; State = IES_INTEGER; IC.pushOperand(IC_IMM); - if (ParsingInlineAsm) + if (ParsingInlineMSAsm) Info = IDInfo; break; } @@ -815,7 +815,7 @@ } } bool onOffset(const MCExpr *Val, SMLoc OffsetLoc, StringRef ID, - const InlineAsmIdentifierInfo &IDInfo, bool ParsingInlineAsm, + const InlineAsmIdentifierInfo &IDInfo, bool ParsingInlineMSAsm, StringRef &ErrMsg) { PrevState = State; switch (State) { @@ -833,7 +833,7 @@ // As we cannot yet resolve the actual value (offset), we retain // the requested semantics by pushing a '0' to the operands stack IC.pushOperand(IC_IMM); - if (ParsingInlineAsm) { + if (ParsingInlineMSAsm) { Info = IDInfo; } break; @@ -1177,7 +1177,7 @@ // The "flags" and "mxcsr" registers cannot be referenced directly. // Treat it as an identifier instead. - if (isParsingInlineAsm() && isParsingIntelSyntax() && + if (isParsingInlineMSAsm() && isParsingIntelSyntax() && (RegNo == X86::EFLAGS || RegNo == X86::MXCSR)) RegNo = 0; @@ -1498,7 +1498,8 @@ } else { BaseReg = BaseReg ? BaseReg : 1; return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg, - IndexReg, Scale, Start, End, Size, Identifier, + IndexReg, Scale, Start, End, Size, + /*DefaultBaseReg=*/X86::NoRegister, Identifier, Decl, FrontendSize); } } @@ -1536,7 +1537,7 @@ return true; StringRef ErrMsg; ParseError = - SM.onOffset(Val, OffsetLoc, ID, Info, isParsingInlineAsm(), ErrMsg); + SM.onOffset(Val, OffsetLoc, ID, Info, isParsingInlineMSAsm(), ErrMsg); if (ParseError) return Error(SMLoc::getFromPointer(Name.data()), ErrMsg); } else { @@ -1595,7 +1596,7 @@ // Symbol reference, when parsing assembly content InlineAsmIdentifierInfo Info; const MCExpr *Val; - if (!isParsingInlineAsm()) { + if (!isParsingInlineMSAsm()) { if (getParser().parsePrimaryExpr(Val, End)) { return Error(Tok.getLoc(), "Unexpected identifier!"); } else if (SM.onIdentifierExpr(Val, Identifier, Info, false, ErrMsg)) { @@ -1646,8 +1647,8 @@ return Error(Loc, "invalid reference to undefined symbol"); StringRef Identifier = Sym->getName(); InlineAsmIdentifierInfo Info; - if (SM.onIdentifierExpr(Val, Identifier, Info, - isParsingInlineAsm(), ErrMsg)) + if (SM.onIdentifierExpr(Val, Identifier, Info, isParsingInlineMSAsm(), + ErrMsg)) return Error(Loc, ErrMsg); End = consumeToken(); } else { @@ -1741,7 +1742,7 @@ const MCExpr *&Val, StringRef &Identifier, InlineAsmIdentifierInfo &Info, bool IsUnevaluatedOperand, SMLoc &End, bool IsParsingOffsetOperator) { MCAsmParser &Parser = getParser(); - assert(isParsingInlineAsm() && "Expected to be parsing inline assembly."); + assert(isParsingInlineMSAsm() && "Expected to be parsing inline assembly."); Val = nullptr; StringRef LineBuf(Identifier.data()); @@ -1844,7 +1845,7 @@ APInt DotDisp; DotDispStr.getAsInteger(10, DotDisp); Offset = DotDisp.getZExtValue(); - } else if (isParsingInlineAsm() && Tok.is(AsmToken::Identifier)) { + } else if (isParsingInlineMSAsm() && Tok.is(AsmToken::Identifier)) { std::pair BaseMember = DotDispStr.split('.'); if (SemaCallback->LookupInlineAsmField(BaseMember.first, BaseMember.second, Offset)) @@ -1869,7 +1870,7 @@ // Eat offset, mark start of identifier. SMLoc Start = Lex().getLoc(); ID = getTok().getString(); - if (!isParsingInlineAsm()) { + if (!isParsingInlineMSAsm()) { if ((getTok().isNot(AsmToken::Identifier) && getTok().isNot(AsmToken::String)) || getParser().parsePrimaryExpr(Val, End)) @@ -1992,7 +1993,7 @@ if (ParseIntelExpression(SM, End)) return nullptr; - if (isParsingInlineAsm()) + if (isParsingInlineMSAsm()) RewriteIntelExpression(SM, Start, Tok.getLoc()); int64_t Imm = SM.getImm(); @@ -2006,7 +2007,7 @@ // RegNo != 0 specifies a valid segment register, // and we are parsing a segment override if (!SM.isMemExpr() && !RegNo) { - if (isParsingInlineAsm() && SM.isOffsetOperator()) { + if (isParsingInlineMSAsm() && SM.isOffsetOperator()) { const InlineAsmIdentifierInfo Info = SM.getIdentifierInfo(); if (Info.isKind(InlineAsmIdentifierInfo::IK_Var)) { // Disp includes the address of a variable; make sure this is recorded @@ -2058,10 +2059,18 @@ CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(), ErrMsg)) return ErrorOperand(Start, ErrMsg); - if (isParsingInlineAsm()) + if (isParsingInlineMSAsm()) return CreateMemForInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale, Start, End, Size, SM.getSymName(), SM.getIdentifierInfo()); + + // When parsing x64 MS-style assembly, all memory operands default to + // RIP-relative when interpreted as non-absolute references. + if ((isParsingInlineMSAsm() || Parser.isParsingMasm()) && is64BitMode()) + return X86Operand::CreateMem(getPointerWidth(), RegNo, Disp, BaseReg, + IndexReg, Scale, Start, End, Size, + /*DefaultBaseReg=*/X86::RIP); + if (!(BaseReg || IndexReg || RegNo)) return X86Operand::CreateMem(getPointerWidth(), Disp, Start, End, Size); return X86Operand::CreateMem(getPointerWidth(), RegNo, Disp, @@ -2764,7 +2773,7 @@ // In MS inline asm curly braces mark the beginning/end of a block, // therefore they should be interepreted as end of statement CurlyAsEndOfStatement = - isParsingIntelSyntax() && isParsingInlineAsm() && + isParsingIntelSyntax() && isParsingInlineMSAsm() && (getLexer().is(AsmToken::LCurly) || getLexer().is(AsmToken::RCurly)); if (getLexer().isNot(AsmToken::EndOfStatement) && !CurlyAsEndOfStatement) return TokError("unexpected token in argument list"); diff --git a/llvm/lib/Target/X86/AsmParser/X86Operand.h b/llvm/lib/Target/X86/AsmParser/X86Operand.h --- a/llvm/lib/Target/X86/AsmParser/X86Operand.h +++ b/llvm/lib/Target/X86/AsmParser/X86Operand.h @@ -60,6 +60,7 @@ unsigned SegReg; const MCExpr *Disp; unsigned BaseReg; + unsigned DefaultBaseReg; unsigned IndexReg; unsigned Scale; unsigned Size; @@ -184,6 +185,10 @@ assert(Kind == Memory && "Invalid access!"); return Mem.BaseReg; } + unsigned getMemDefaultBaseReg() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.DefaultBaseReg; + } unsigned getMemIndexReg() const { assert(Kind == Memory && "Invalid access!"); return Mem.IndexReg; @@ -540,7 +545,10 @@ void addMemOperands(MCInst &Inst, unsigned N) const { assert((N == 5) && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getMemBaseReg())); + if (getMemBaseReg()) + Inst.addOperand(MCOperand::createReg(getMemBaseReg())); + else + Inst.addOperand(MCOperand::createReg(getMemDefaultBaseReg())); Inst.addOperand(MCOperand::createImm(getMemScale())); Inst.addOperand(MCOperand::createReg(getMemIndexReg())); addExpr(Inst, getMemDisp()); @@ -633,6 +641,7 @@ Res->Mem.SegReg = 0; Res->Mem.Disp = Disp; Res->Mem.BaseReg = 0; + Res->Mem.DefaultBaseReg = 0; Res->Mem.IndexReg = 0; Res->Mem.Scale = 1; Res->Mem.Size = Size; @@ -648,11 +657,14 @@ static std::unique_ptr CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc, - SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(), - void *OpDecl = nullptr, unsigned FrontendSize = 0) { + SMLoc EndLoc, unsigned Size = 0, + unsigned DefaultBaseReg = X86::NoRegister, + StringRef SymName = StringRef(), void *OpDecl = nullptr, + unsigned FrontendSize = 0) { // We should never just have a displacement, that should be parsed as an // absolute memory operand. - assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!"); + assert((SegReg || BaseReg || IndexReg || DefaultBaseReg) && + "Invalid memory operand!"); // The scale should always be one of {1,2,4,8}. assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) && @@ -661,6 +673,7 @@ Res->Mem.SegReg = SegReg; Res->Mem.Disp = Disp; Res->Mem.BaseReg = BaseReg; + Res->Mem.DefaultBaseReg = DefaultBaseReg; Res->Mem.IndexReg = IndexReg; Res->Mem.Scale = Scale; Res->Mem.Size = Size; diff --git a/llvm/test/tools/llvm-ml/rip-relative-addressing.test b/llvm/test/tools/llvm-ml/rip-relative-addressing.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ml/rip-relative-addressing.test @@ -0,0 +1,8 @@ +# RUN: llvm-ml -m32 -filetype=asm %s | FileCheck %s --check-prefix=CHECK-32 +# RUN: llvm-ml -m64 -filetype=asm %s | FileCheck %s --check-prefix=CHECK-64 + +.code +mov eax, [4] +; CHECK-32: mov eax, dword ptr [4] +; CHECK-64: mov eax, dword ptr [rip + 4] +END \ No newline at end of file