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

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 3 11:07:30 PDT 2018


Author: ctopper
Date: Tue Jul  3 11:07:30 2018
New Revision: 336218

URL: http://llvm.org/viewvc/llvm-project?rev=336218&view=rev
Log:
[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.

Modified:
    llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp
    llvm/trunk/lib/Target/X86/AsmParser/X86Operand.h

Modified: llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp?rev=336218&r1=336217&r2=336218&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp (original)
+++ llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp Tue Jul  3 11:07:30 2018
@@ -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 CheckBaseRegAndIndexRegAndSc
   // 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::VerifyAndAdjustOperan
   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
                                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
       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(O
 /// 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
   // 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(Pars
 
     // 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(Pars
     }
   }
 
+  // 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;
 

Modified: llvm/trunk/lib/Target/X86/AsmParser/X86Operand.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/AsmParser/X86Operand.h?rev=336218&r1=336217&r2=336218&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/AsmParser/X86Operand.h (original)
+++ llvm/trunk/lib/Target/X86/AsmParser/X86Operand.h Tue Jul  3 11:07:30 2018
@@ -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 MCParse
     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 MCParse
 
   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 &&
@@ -540,6 +544,11 @@ struct X86Operand final : public MCParse
   }
 
   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);
     Res->Pref.Prefixes = Prefixes;




More information about the llvm-commits mailing list