summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
diff options
context:
space:
mode:
authorAndrew V. Tischenko <andrew.v.tischenko@gmail.com>2017-10-16 11:14:29 +0000
committerAndrew V. Tischenko <andrew.v.tischenko@gmail.com>2017-10-16 11:14:29 +0000
commitbfc9061593307bf6b09106216445eacb1c5215d1 (patch)
treeb27f6f29da414fb794f53873cfb572758b7a2891 /llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
parent6f60ff84cd2b27f801df4809099f211ee04399b1 (diff)
downloadbcm5719-llvm-bfc9061593307bf6b09106216445eacb1c5215d1.tar.gz
bcm5719-llvm-bfc9061593307bf6b09106216445eacb1c5215d1.zip
This patch is a result of D37262: The issues with X86 prefixes. It closes PR7709, PR17697, PR19251, PR32809 and PR21640. There could be other bugs closed by this patch.
llvm-svn: 315899
Diffstat (limited to 'llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp')
-rw-r--r--llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp66
1 files changed, 56 insertions, 10 deletions
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 385bbbe60a2..6985d356af6 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -2330,7 +2330,6 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
}
}
- Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
// Determine whether this is an instruction prefix.
// FIXME:
@@ -2340,22 +2339,48 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
// lock addq %rax, %rbx ; Destination operand must be of memory type
// xacquire <insn> ; xacquire must be accompanied by 'lock'
bool isPrefix = StringSwitch<bool>(Name)
- .Cases("lock",
- "rep", "repe",
- "repz", "repne",
- "repnz", "rex64",
- "data32", "data16", true)
- .Cases("xacquire", "xrelease", true)
- .Cases("acquire", "release", isParsingIntelSyntax())
- .Default(false);
+ .Cases("rex64", "data32", "data16", true)
+ .Cases("xacquire", "xrelease", true)
+ .Cases("acquire", "release", isParsingIntelSyntax())
+ .Default(false);
+
+ auto isLockRepeatPrefix = [](StringRef N) {
+ return StringSwitch<bool>(N)
+ .Cases("lock", "rep", "repe", "repz", "repne", "repnz", true)
+ .Default(false);
+ };
bool CurlyAsEndOfStatement = false;
+
+ unsigned Flags = X86::IP_NO_PREFIX;
+ while (isLockRepeatPrefix(Name.lower())) {
+ unsigned Prefix =
+ StringSwitch<unsigned>(Name)
+ .Cases("lock", "lock", X86::IP_HAS_LOCK)
+ .Cases("rep", "repe", "repz", X86::IP_HAS_REPEAT)
+ .Cases("repne", "repnz", X86::IP_HAS_REPEAT_NE)
+ .Default(X86::IP_NO_PREFIX); // Invalid prefix (impossible)
+ Flags |= Prefix;
+ Name = Parser.getTok().getString();
+ Parser.Lex(); // eat the prefix
+ // Hack: we could have something like
+ // "lock; cmpxchg16b $1" or "lock\0A\09incl" or "lock/incl"
+ while (Name.startswith(";") || Name.startswith("\n") ||
+ Name.startswith("\t") or Name.startswith("/")) {
+ Name = Parser.getTok().getString();
+ Parser.Lex(); // go to next prefix or instr
+ }
+ }
+
+ if (Flags)
+ PatchedName = Name;
+ Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
+
// This does the actual operand parsing. Don't parse any more if we have a
// prefix juxtaposed with an operation like "lock incl 4(%rax)", because we
// just want to parse the "lock" as the first instruction and the "incl" as
// the next one.
if (getLexer().isNot(AsmToken::EndOfStatement) && !isPrefix) {
-
// Parse '*' modifier.
if (getLexer().is(AsmToken::Star))
Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
@@ -2593,6 +2618,8 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
}
}
+ if (Flags)
+ Operands.push_back(X86Operand::CreatePrefix(Flags, NameLoc, NameLoc));
return false;
}
@@ -2660,6 +2687,16 @@ bool X86AsmParser::ErrorMissingFeature(SMLoc IDLoc, uint64_t ErrorInfo,
return Error(IDLoc, OS.str(), SMRange(), MatchingInlineAsm);
}
+static unsigned getPrefixes(OperandVector &Operands) {
+ unsigned Result = 0;
+ X86Operand &Prefix = static_cast<X86Operand &>(*Operands.back());
+ if (Prefix.isPrefix()) {
+ Result = Prefix.getPrefix();
+ Operands.pop_back();
+ }
+ return Result;
+}
+
bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out,
@@ -2674,8 +2711,13 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
MatchFPUWaitAlias(IDLoc, Op, Operands, Out, MatchingInlineAsm);
bool WasOriginallyInvalidOperand = false;
+ unsigned Prefixes = getPrefixes(Operands);
+
MCInst Inst;
+ if (Prefixes)
+ Inst.setFlags(Prefixes);
+
// First, try a direct match.
switch (MatchInstruction(Operands, Inst, ErrorInfo, MatchingInlineAsm,
isParsingIntelSyntax())) {
@@ -2840,12 +2882,16 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
StringRef Mnemonic = Op.getToken();
SMRange EmptyRange = None;
StringRef Base = Op.getToken();
+ unsigned Prefixes = getPrefixes(Operands);
// First, handle aliases that expand to multiple instructions.
MatchFPUWaitAlias(IDLoc, Op, Operands, Out, MatchingInlineAsm);
MCInst Inst;
+ if (Prefixes)
+ Inst.setFlags(Prefixes);
+
// Find one unsized memory operand, if present.
X86Operand *UnsizedMemOp = nullptr;
for (const auto &Op : Operands) {
OpenPOWER on IntegriCloud