1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

[X86][AsmParser] Rework the in/out (%dx) hack one more time.

This patch adds a new token type specifically for (%dx). We will now always create this token when we parse (%dx). After all operands have been parsed, if the mnemonic is in/out we'll morph this token to a regular register token. Otherwise we keep it as the special DX token which won't match any instructions.

This removes the need for passing Mnemonic through the parsing functions. It also seems closer to gas where when its used on the wrong instruction it just gets diagnosed as an invalid operand rather than a bad memory address.

llvm-svn: 336218
This commit is contained in:
Craig Topper 2018-07-03 18:07:30 +00:00
parent 3f59f2298f
commit 3716ebae8b
2 changed files with 45 additions and 24 deletions

View File

@ -819,8 +819,8 @@ private:
std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst);
bool VerifyAndAdjustOperands(OperandVector &OrigOperands,
OperandVector &FinalOperands);
std::unique_ptr<X86Operand> ParseOperand(StringRef Mnemonic);
std::unique_ptr<X86Operand> ParseATTOperand(StringRef Mnemonic);
std::unique_ptr<X86Operand> ParseOperand();
std::unique_ptr<X86Operand> ParseATTOperand();
std::unique_ptr<X86Operand> ParseIntelOperand();
std::unique_ptr<X86Operand> ParseIntelOffsetOfOperator();
bool ParseIntelDotOperator(IntelExprStateMachine &SM, SMLoc &End);
@ -835,8 +835,7 @@ private:
InlineAsmIdentifierInfo &Info,
bool IsUnevaluatedOperand, SMLoc &End);
std::unique_ptr<X86Operand> ParseMemOperand(unsigned SegReg, SMLoc StartLoc,
StringRef Mnemonic);
std::unique_ptr<X86Operand> ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
bool ParseIntelMemoryOperandSize(unsigned &Size);
std::unique_ptr<X86Operand>
@ -1011,7 +1010,8 @@ static bool CheckBaseRegAndIndexRegAndScale(unsigned BaseReg, unsigned IndexReg,
// and then only in non-64-bit modes.
if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
(Is64BitMode || (BaseReg != X86::BX && BaseReg != X86::BP &&
BaseReg != X86::SI && BaseReg != X86::DI))) {
BaseReg != X86::SI && BaseReg != X86::DI)) &&
BaseReg != X86::DX) {
ErrMsg = "invalid 16-bit base register";
return true;
}
@ -1332,10 +1332,10 @@ bool X86AsmParser::VerifyAndAdjustOperands(OperandVector &OrigOperands,
return false;
}
std::unique_ptr<X86Operand> X86AsmParser::ParseOperand(StringRef Mnemonic) {
std::unique_ptr<X86Operand> X86AsmParser::ParseOperand() {
if (isParsingIntelSyntax())
return ParseIntelOperand();
return ParseATTOperand(Mnemonic);
return ParseATTOperand();
}
std::unique_ptr<X86Operand> X86AsmParser::CreateMemForInlineAsm(
@ -1932,12 +1932,12 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() {
BaseReg, IndexReg, Scale, Start, End, Size);
}
std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand(StringRef Mnemonic) {
std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() {
MCAsmParser &Parser = getParser();
switch (getLexer().getKind()) {
default:
// Parse a memory operand with no segment register.
return ParseMemOperand(0, Parser.getTok().getLoc(), Mnemonic);
return ParseMemOperand(0, Parser.getTok().getLoc());
case AsmToken::Percent: {
// Read the register.
unsigned RegNo;
@ -1963,7 +1963,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand(StringRef Mnemonic) {
return ErrorOperand(Start, "invalid segment register");
getParser().Lex(); // Eat the colon.
return ParseMemOperand(RegNo, Start, Mnemonic);
return ParseMemOperand(RegNo, Start);
}
case AsmToken::Dollar: {
// $42 -> immediate.
@ -2089,8 +2089,7 @@ bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands,
/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
/// has already been parsed if present.
std::unique_ptr<X86Operand> X86AsmParser::ParseMemOperand(unsigned SegReg,
SMLoc MemStart,
StringRef Mnemonic) {
SMLoc MemStart) {
MCAsmParser &Parser = getParser();
// We have to disambiguate a parenthesized expression "(4+5)" from the start
@ -2245,16 +2244,8 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseMemOperand(unsigned SegReg,
// documented form in various unofficial manuals, so a lot of code uses it.
if (BaseReg == X86::DX && IndexReg == 0 && Scale == 1 &&
SegReg == 0 && isa<MCConstantExpr>(Disp) &&
cast<MCConstantExpr>(Disp)->getValue() == 0 &&
(Mnemonic == "outb" || Mnemonic == "outsb" ||
Mnemonic == "outw" || Mnemonic == "outsw" ||
Mnemonic == "outl" || Mnemonic == "outsl" ||
Mnemonic == "out" || Mnemonic == "outs" ||
Mnemonic == "inb" || Mnemonic == "insb" ||
Mnemonic == "inw" || Mnemonic == "insw" ||
Mnemonic == "inl" || Mnemonic == "insl" ||
Mnemonic == "in" || Mnemonic == "ins"))
return X86Operand::CreateReg(BaseReg, BaseLoc, BaseLoc);
cast<MCConstantExpr>(Disp)->getValue() == 0)
return X86Operand::CreateDXReg(BaseLoc, BaseLoc);
StringRef ErrMsg;
if (CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),
@ -2517,7 +2508,7 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
// Read the operands.
while(1) {
if (std::unique_ptr<X86Operand> Op = ParseOperand(Name)) {
if (std::unique_ptr<X86Operand> Op = ParseOperand()) {
Operands.push_back(std::move(Op));
if (HandleAVX512Operand(Operands, *Operands.back()))
return true;
@ -2587,6 +2578,27 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
}
}
// This is a terrible hack to handle "out[s]?[bwl]? %al, (%dx)" ->
// "outb %al, %dx". Out doesn't take a memory form, but this is a widely
// documented form in various unofficial manuals, so a lot of code uses it.
if ((Name == "outb" || Name == "outsb" || Name == "outw" || Name == "outsw" ||
Name == "outl" || Name == "outsl" || Name == "out" || Name == "outs") &&
Operands.size() == 3) {
X86Operand &Op = (X86Operand &)*Operands.back();
if (Op.isDXReg())
Operands.back() = X86Operand::CreateReg(X86::DX, Op.getStartLoc(),
Op.getEndLoc());
}
// Same hack for "in[s]?[bwl]? (%dx), %al" -> "inb %dx, %al".
if ((Name == "inb" || Name == "insb" || Name == "inw" || Name == "insw" ||
Name == "inl" || Name == "insl" || Name == "in" || Name == "ins") &&
Operands.size() == 3) {
X86Operand &Op = (X86Operand &)*Operands[1];
if (Op.isDXReg())
Operands[1] = X86Operand::CreateReg(X86::DX, Op.getStartLoc(),
Op.getEndLoc());
}
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 2> TmpOperands;
bool HadVerifyError = false;

View File

@ -30,7 +30,7 @@ namespace llvm {
/// X86Operand - Instances of this class represent a parsed X86 machine
/// instruction.
struct X86Operand final : public MCParsedAsmOperand {
enum KindTy { Token, Register, Immediate, Memory, Prefix } Kind;
enum KindTy { Token, Register, Immediate, Memory, Prefix, DXRegister } Kind;
SMLoc StartLoc, EndLoc;
SMLoc OffsetOfLoc;
@ -118,6 +118,9 @@ struct X86Operand final : public MCParsedAsmOperand {
case Register:
OS << "Reg:" << X86IntelInstPrinter::getRegisterName(Reg.RegNo);
break;
case DXRegister:
OS << "DXReg";
break;
case Immediate:
PrintImmValue(Imm.Val, "Imm:");
break;
@ -441,6 +444,7 @@ struct X86Operand final : public MCParsedAsmOperand {
bool isPrefix() const { return Kind == Prefix; }
bool isReg() const override { return Kind == Register; }
bool isDXReg() const { return Kind == DXRegister; }
bool isGR32orGR64() const {
return Kind == Register &&
@ -539,6 +543,11 @@ struct X86Operand final : public MCParsedAsmOperand {
return Res;
}
static std::unique_ptr<X86Operand>
CreateDXReg(SMLoc StartLoc, SMLoc EndLoc) {
return llvm::make_unique<X86Operand>(DXRegister, StartLoc, EndLoc);
}
static std::unique_ptr<X86Operand>
CreatePrefix(unsigned Prefixes, SMLoc StartLoc, SMLoc EndLoc) {
auto Res = llvm::make_unique<X86Operand>(Prefix, StartLoc, EndLoc);