diff options
author | Eric Astor <epastor@google.com> | 2019-12-22 00:09:37 -0500 |
---|---|---|
committer | Eric Astor <epastor@google.com> | 2019-12-22 09:16:34 -0500 |
commit | dc5b614fa9a1c83e8275fcb9c3f78444d0a30514 (patch) | |
tree | 38cc0f3cbaf41050d00d06e2f277fba322979f43 /llvm/lib/Target/X86 | |
parent | 0b38af89e2c0adc13a6efb1dd04485229ef0d1c6 (diff) | |
download | bcm5719-llvm-dc5b614fa9a1c83e8275fcb9c3f78444d0a30514.tar.gz bcm5719-llvm-dc5b614fa9a1c83e8275fcb9c3f78444d0a30514.zip |
[ms] [X86] Use "P" modifier on operands to call instructions in inline X86 assembly.
Summary:
This is documented as the appropriate template modifier for call operands.
Fixes PR44272, and adds a regression test.
Also adds support for operand modifiers in Intel-style inline assembly.
Reviewers: rnk
Reviewed By: rnk
Subscribers: merge_guards_bot, hiraditya, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D71677
Diffstat (limited to 'llvm/lib/Target/X86')
-rw-r--r-- | llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/Target/X86/AsmParser/X86Operand.h | 6 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86AsmPrinter.cpp | 37 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86AsmPrinter.h | 2 |
4 files changed, 41 insertions, 13 deletions
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index 17ce31f01ed..646b4070556 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -2866,6 +2866,15 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } } + // Mark the operands of a call instruction. These need to be handled + // differently when referenced in MS-style inline assembly. + if (Name.startswith("call") || Name.startswith("lcall")) { + for (size_t i = 1; i < Operands.size(); ++i) { + X86Operand &Op = static_cast<X86Operand &>(*Operands[i]); + Op.setCallOperand(true); + } + } + if (Flags) Operands.push_back(X86Operand::CreatePrefix(Flags, NameLoc, NameLoc)); return false; diff --git a/llvm/lib/Target/X86/AsmParser/X86Operand.h b/llvm/lib/Target/X86/AsmParser/X86Operand.h index 593932e6aea..93626f8254e 100644 --- a/llvm/lib/Target/X86/AsmParser/X86Operand.h +++ b/llvm/lib/Target/X86/AsmParser/X86Operand.h @@ -36,6 +36,7 @@ struct X86Operand final : public MCParsedAsmOperand { StringRef SymName; void *OpDecl; bool AddressOf; + bool CallOperand; struct TokOp { const char *Data; @@ -77,7 +78,7 @@ struct X86Operand final : public MCParsedAsmOperand { }; X86Operand(KindTy K, SMLoc Start, SMLoc End) - : Kind(K), StartLoc(Start), EndLoc(End) {} + : Kind(K), StartLoc(Start), EndLoc(End), CallOperand(false) {} StringRef getSymName() override { return SymName; } void *getOpDecl() override { return OpDecl; } @@ -286,6 +287,9 @@ struct X86Operand final : public MCParsedAsmOperand { return AddressOf; } + bool isCallOperand() const override { return CallOperand; } + void setCallOperand(bool IsCallOperand) { CallOperand = IsCallOperand; } + bool isMem() const override { return Kind == Memory; } bool isMemUnsized() const { return Kind == Memory && Mem.Size == 0; diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp index de13d59bca9..8c2b90144b4 100644 --- a/llvm/lib/Target/X86/X86AsmPrinter.cpp +++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -337,14 +337,22 @@ void X86AsmPrinter::PrintMemReference(const MachineInstr *MI, unsigned OpNo, PrintLeaMemReference(MI, OpNo, O, Modifier); } + void X86AsmPrinter::PrintIntelMemReference(const MachineInstr *MI, - unsigned OpNo, raw_ostream &O) { + unsigned OpNo, raw_ostream &O, + const char *Modifier) { const MachineOperand &BaseReg = MI->getOperand(OpNo + X86::AddrBaseReg); unsigned ScaleVal = MI->getOperand(OpNo + X86::AddrScaleAmt).getImm(); const MachineOperand &IndexReg = MI->getOperand(OpNo + X86::AddrIndexReg); const MachineOperand &DispSpec = MI->getOperand(OpNo + X86::AddrDisp); const MachineOperand &SegReg = MI->getOperand(OpNo + X86::AddrSegmentReg); + // If we really don't want to print out (rip), don't. + bool HasBaseReg = BaseReg.getReg() != 0; + if (HasBaseReg && Modifier && !strcmp(Modifier, "no-rip") && + BaseReg.getReg() == X86::RIP) + HasBaseReg = false; + // If this has a segment register, print it. if (SegReg.getReg()) { PrintOperand(MI, OpNo + X86::AddrSegmentReg, O); @@ -354,7 +362,7 @@ void X86AsmPrinter::PrintIntelMemReference(const MachineInstr *MI, O << '['; bool NeedPlus = false; - if (BaseReg.getReg()) { + if (HasBaseReg) { PrintOperand(MI, OpNo + X86::AddrBaseReg, O); NeedPlus = true; } @@ -372,7 +380,7 @@ void X86AsmPrinter::PrintIntelMemReference(const MachineInstr *MI, PrintOperand(MI, OpNo + X86::AddrDisp, O); } else { int64_t DispVal = DispSpec.getImm(); - if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) { + if (DispVal || (!IndexReg.getReg() && !HasBaseReg)) { if (NeedPlus) { if (DispVal > 0) O << " + "; @@ -525,11 +533,6 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &O) { - if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) { - PrintIntelMemReference(MI, OpNo, O); - return false; - } - if (ExtraCode && ExtraCode[0]) { if (ExtraCode[1] != 0) return true; // Unknown modifier. @@ -543,14 +546,26 @@ bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, // These only apply to registers, ignore on mem. break; case 'H': - PrintMemReference(MI, OpNo, O, "H"); + if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) { + return true; // Unsupported modifier in Intel inline assembly. + } else { + PrintMemReference(MI, OpNo, O, "H"); + } return false; case 'P': // Don't print @PLT, but do print as memory. - PrintMemReference(MI, OpNo, O, "no-rip"); + if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) { + PrintIntelMemReference(MI, OpNo, O, "no-rip"); + } else { + PrintMemReference(MI, OpNo, O, "no-rip"); + } return false; } } - PrintMemReference(MI, OpNo, O, nullptr); + if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) { + PrintIntelMemReference(MI, OpNo, O, nullptr); + } else { + PrintMemReference(MI, OpNo, O, nullptr); + } return false; } diff --git a/llvm/lib/Target/X86/X86AsmPrinter.h b/llvm/lib/Target/X86/X86AsmPrinter.h index c5b9d2875fe..ee79401dc80 100644 --- a/llvm/lib/Target/X86/X86AsmPrinter.h +++ b/llvm/lib/Target/X86/X86AsmPrinter.h @@ -112,7 +112,7 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter { void PrintMemReference(const MachineInstr *MI, unsigned OpNo, raw_ostream &O, const char *Modifier); void PrintIntelMemReference(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O); + raw_ostream &O, const char *Modifier); public: X86AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer); |