diff options
-rw-r--r-- | lib/Target/X86/AsmParser/X86AsmParser.cpp | 65 | ||||
-rw-r--r-- | lib/Target/X86/X86.td | 5 | ||||
-rw-r--r-- | test/MC/AsmParser/X86/x86_64-suffix-matching.s | 8 |
3 files changed, 74 insertions, 4 deletions
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index da01350..aaa1c06 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -51,11 +51,14 @@ private: void InstructionCleanup(MCInst &Inst); /// @name Auto-generated Match Functions - /// { + /// { bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst); + bool MatchInstructionImpl( + const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst); + /// } public: @@ -132,7 +135,7 @@ struct X86Operand : public MCParsedAsmOperand { X86Operand(KindTy K, SMLoc Start, SMLoc End) : Kind(K), StartLoc(Start), EndLoc(End) {} - + /// getStartLoc - Get the location of the first token of this operand. SMLoc getStartLoc() const { return StartLoc; } /// getEndLoc - Get the location of the last token of this operand. @@ -142,6 +145,11 @@ struct X86Operand : public MCParsedAsmOperand { assert(Kind == Token && "Invalid access!"); return StringRef(Tok.Data, Tok.Length); } + void setTokenValue(StringRef Value) { + assert(Kind == Token && "Invalid access!"); + Tok.Data = Value.data(); + Tok.Length = Value.size(); + } unsigned getReg() const { assert(Kind == Register && "Invalid access!"); @@ -632,6 +640,59 @@ void X86ATTAsmParser::InstructionCleanup(MCInst &Inst) { } } +bool +X86ATTAsmParser::MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> + &Operands, + MCInst &Inst) { + // First, try a direct match. + if (!MatchInstructionImpl(Operands, Inst)) + return false; + + // Ignore anything which is obviously not a suffix match. + if (Operands.size() == 0) + return true; + X86Operand *Op = static_cast<X86Operand*>(Operands[0]); + if (!Op->isToken() || Op->getToken().size() > 15) + return true; + + // FIXME: Ideally, we would only attempt suffix matches for things which are + // valid prefixes, and we could just infer the right unambiguous + // type. However, that requires substantially more matcher support than the + // following hack. + + // Change the operand to point to a temporary token. + char Tmp[16]; + StringRef Base = Op->getToken(); + memcpy(Tmp, Base.data(), Base.size()); + Op->setTokenValue(StringRef(Tmp, Base.size() + 1)); + + // Check for the various suffix matches. + Tmp[Base.size()] = 'b'; + bool MatchB = MatchInstructionImpl(Operands, Inst); + Tmp[Base.size()] = 'w'; + bool MatchW = MatchInstructionImpl(Operands, Inst); + Tmp[Base.size()] = 'l'; + bool MatchL = MatchInstructionImpl(Operands, Inst); + + // Restore the old token. + Op->setTokenValue(Base); + + // If exactly one matched, then we treat that as a successful match (and the + // instruction will already have been filled in correctly, since the failing + // matches won't have modified it). + if (MatchB + MatchW + MatchL == 2) + return false; + + // Similarly, if all three matched then we assume this is a generic operation + // involving memory, and take the 'l' form (to match 'gas'). + if (MatchB + MatchW + MatchL == 0) + return false; + + // Otherwise, the match failed. + return true; +} + + extern "C" void LLVMInitializeX86AsmLexer(); // Force static initialization. diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index ec86fc2..a53f973 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -179,8 +179,9 @@ include "X86CallingConv.td" // Currently the X86 assembly parser only supports ATT syntax. def ATTAsmParser : AsmParser { - string AsmParserClassName = "ATTAsmParser"; - string AsmParserInstCleanup = "InstructionCleanup"; + string AsmParserClassName = "ATTAsmParser"; + string AsmParserInstCleanup = "InstructionCleanup"; + string MatchInstructionName = "MatchInstructionImpl"; int Variant = 0; // Discard comments in assembly strings. diff --git a/test/MC/AsmParser/X86/x86_64-suffix-matching.s b/test/MC/AsmParser/X86/x86_64-suffix-matching.s new file mode 100644 index 0000000..9a38e1b --- /dev/null +++ b/test/MC/AsmParser/X86/x86_64-suffix-matching.s @@ -0,0 +1,8 @@ +// RUN: llvm-mc -triple x86_64 -o - %s | FileCheck %s + +// CHECK: addl $0, %eax + add $0, %eax +// CHECK: addb $255, %al + add $0xFF, %al +// CHECK: addl $0, (%rax) + add $0, 0(%rax) |