|
14 | 14 | #include "MCTargetDesc/X86TargetStreamer.h" |
15 | 15 | #include "TargetInfo/X86TargetInfo.h" |
16 | 16 | #include "X86Operand.h" |
| 17 | +#include "third_party/llvm/llvm-project/llvm/include/llvm/MC/MCInst.h" |
17 | 18 | #include "llvm/ADT/STLExtras.h" |
18 | 19 | #include "llvm/ADT/SmallString.h" |
19 | 20 | #include "llvm/ADT/SmallVector.h" |
|
32 | 33 | #include "llvm/MC/MCStreamer.h" |
33 | 34 | #include "llvm/MC/MCSubtargetInfo.h" |
34 | 35 | #include "llvm/MC/MCSymbol.h" |
| 36 | +#include "llvm/MC/MCSymbolCOFF.h" |
35 | 37 | #include "llvm/MC/TargetRegistry.h" |
36 | 38 | #include "llvm/Support/CommandLine.h" |
37 | 39 | #include "llvm/Support/Compiler.h" |
@@ -1202,6 +1204,10 @@ class X86AsmParser : public MCTargetAsmParser { |
1202 | 1204 | void MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, OperandVector &Operands, |
1203 | 1205 | MCStreamer &Out, bool MatchingInlineAsm); |
1204 | 1206 |
|
| 1207 | + void MatchMASMFarCallToNear(SMLoc IDLoc, X86Operand &Op, |
| 1208 | + OperandVector &Operands, MCStreamer &Out, |
| 1209 | + bool MatchingInlineAsm); |
| 1210 | + |
1205 | 1211 | bool ErrorMissingFeature(SMLoc IDLoc, const FeatureBitset &MissingFeatures, |
1206 | 1212 | bool MatchingInlineAsm); |
1207 | 1213 |
|
@@ -2740,11 +2746,11 @@ bool X86AsmParser::parseIntelOperand(OperandVector &Operands, StringRef Name) { |
2740 | 2746 | if ((BaseReg || IndexReg || RegNo || DefaultBaseReg)) |
2741 | 2747 | Operands.push_back(X86Operand::CreateMem( |
2742 | 2748 | getPointerWidth(), RegNo, Disp, BaseReg, IndexReg, Scale, Start, End, |
2743 | | - Size, DefaultBaseReg, /*SymName=*/StringRef(), /*OpDecl=*/nullptr, |
| 2749 | + Size, DefaultBaseReg, /*SymName=*/SM.getSymName(), /*OpDecl=*/nullptr, |
2744 | 2750 | /*FrontendSize=*/0, /*UseUpRegs=*/false, MaybeDirectBranchDest)); |
2745 | 2751 | else |
2746 | 2752 | Operands.push_back(X86Operand::CreateMem( |
2747 | | - getPointerWidth(), Disp, Start, End, Size, /*SymName=*/StringRef(), |
| 2753 | + getPointerWidth(), Disp, Start, End, Size, /*SymName=*/SM.getSymName(), |
2748 | 2754 | /*OpDecl=*/nullptr, /*FrontendSize=*/0, /*UseUpRegs=*/false, |
2749 | 2755 | MaybeDirectBranchDest)); |
2750 | 2756 | return false; |
@@ -3442,6 +3448,14 @@ bool X86AsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name, |
3442 | 3448 | } |
3443 | 3449 | } |
3444 | 3450 |
|
| 3451 | + if (Parser.isParsingMasm() && !is64BitMode()) { |
| 3452 | + // MASM implicitly converts "ret" to "retf" in far procedures; this is |
| 3453 | + // reflected in the default return type in the MCContext. |
| 3454 | + if (PatchedName == "ret" && |
| 3455 | + getContext().getDefaultRetType() == MCContext::IsFar) |
| 3456 | + PatchedName = "retf"; |
| 3457 | + } |
| 3458 | + |
3445 | 3459 | // Determine whether this is an instruction prefix. |
3446 | 3460 | // FIXME: |
3447 | 3461 | // Enhance prefixes integrity robustness. for example, following forms |
@@ -4130,6 +4144,11 @@ bool X86AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
4130 | 4144 | // First, handle aliases that expand to multiple instructions. |
4131 | 4145 | MatchFPUWaitAlias(IDLoc, static_cast<X86Operand &>(*Operands[0]), Operands, |
4132 | 4146 | Out, MatchingInlineAsm); |
| 4147 | + if (getParser().isParsingMasm() && !is64BitMode()) { |
| 4148 | + MatchMASMFarCallToNear(IDLoc, static_cast<X86Operand &>(*Operands[0]), |
| 4149 | + Operands, Out, MatchingInlineAsm); |
| 4150 | + } |
| 4151 | + |
4133 | 4152 | unsigned Prefixes = getPrefixes(Operands); |
4134 | 4153 |
|
4135 | 4154 | MCInst Inst; |
@@ -4191,6 +4210,37 @@ void X86AsmParser::MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, |
4191 | 4210 | } |
4192 | 4211 | } |
4193 | 4212 |
|
| 4213 | +void X86AsmParser::MatchMASMFarCallToNear(SMLoc IDLoc, X86Operand &Op, |
| 4214 | + OperandVector &Operands, |
| 4215 | + MCStreamer &Out, |
| 4216 | + bool MatchingInlineAsm) { |
| 4217 | + // FIXME: This should be replaced with a real .td file alias mechanism. |
| 4218 | + // Also, MatchInstructionImpl should actually *do* the EmitInstruction |
| 4219 | + // call. |
| 4220 | + if (Op.getToken() != "call") |
| 4221 | + return; |
| 4222 | + // This is a call instruction... |
| 4223 | + |
| 4224 | + X86Operand &Operand = static_cast<X86Operand &>(*Operands[1]); |
| 4225 | + MCSymbol *Sym = getContext().lookupSymbol(Operand.getSymName()); |
| 4226 | + if (Sym == nullptr || !Sym->isInSection() || !Sym->isCOFF() || |
| 4227 | + !dyn_cast<MCSymbolCOFF>(Sym)->isFarProc()) |
| 4228 | + return; |
| 4229 | + // Sym is a reference to a far proc in a code section.... |
| 4230 | + |
| 4231 | + if (Out.getCurrentSectionOnly() == &Sym->getSection()) { |
| 4232 | + // This is a call to a symbol declared as a far proc, and will be emitted as |
| 4233 | + // a near call... so we need to explicitly push the code section register |
| 4234 | + // before the call. |
| 4235 | + MCInst Inst; |
| 4236 | + Inst.setOpcode(X86::PUSH32r); |
| 4237 | + Inst.addOperand(MCOperand::createReg(MCRegister(X86::CS))); |
| 4238 | + Inst.setLoc(IDLoc); |
| 4239 | + if (!MatchingInlineAsm) |
| 4240 | + emitInstruction(Inst, Operands, Out); |
| 4241 | + } |
| 4242 | +} |
| 4243 | + |
4194 | 4244 | bool X86AsmParser::ErrorMissingFeature(SMLoc IDLoc, |
4195 | 4245 | const FeatureBitset &MissingFeatures, |
4196 | 4246 | bool MatchingInlineAsm) { |
|
0 commit comments