forked from OSchip/llvm-project
[X86] Teach the assembler parser to handle a '*' between segment register and base/index/displacement part of an address
A '*' after the segment is equivalent to a '*' before the segment register. To make the AsmMatcher table work we need to place the '*' token into the operand vector before the full memory operand. To accomplish this I've modified some portions of operand parsing to expose the operand vector to ParseATTOperand so that the token can be pushed to the vector after parsing the segment register and before creating the memory operand using that segment register. Fixes PR46879 Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D84895
This commit is contained in:
parent
f71deb43ab
commit
9611ee5f40
|
@ -906,8 +906,8 @@ private:
|
|||
std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst);
|
||||
bool VerifyAndAdjustOperands(OperandVector &OrigOperands,
|
||||
OperandVector &FinalOperands);
|
||||
std::unique_ptr<X86Operand> ParseOperand();
|
||||
std::unique_ptr<X86Operand> ParseATTOperand();
|
||||
bool ParseOperand(OperandVector &Operands);
|
||||
bool ParseATTOperand(OperandVector &Operands);
|
||||
std::unique_ptr<X86Operand> ParseIntelOperand();
|
||||
bool ParseIntelOffsetOperator(const MCExpr *&Val, StringRef &ID,
|
||||
InlineAsmIdentifierInfo &Info, SMLoc &End);
|
||||
|
@ -1531,10 +1531,16 @@ bool X86AsmParser::VerifyAndAdjustOperands(OperandVector &OrigOperands,
|
|||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<X86Operand> X86AsmParser::ParseOperand() {
|
||||
if (isParsingIntelSyntax())
|
||||
return ParseIntelOperand();
|
||||
return ParseATTOperand();
|
||||
bool X86AsmParser::ParseOperand(OperandVector &Operands) {
|
||||
if (isParsingIntelSyntax()) {
|
||||
if (std::unique_ptr<X86Operand> Op = ParseIntelOperand()) {
|
||||
Operands.push_back(std::move(Op));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return ParseATTOperand(Operands);
|
||||
}
|
||||
|
||||
std::unique_ptr<X86Operand> X86AsmParser::CreateMemForMSInlineAsm(
|
||||
|
@ -2206,7 +2212,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() {
|
|||
BaseReg, IndexReg, Scale, Start, End, Size);
|
||||
}
|
||||
|
||||
std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() {
|
||||
bool X86AsmParser::ParseATTOperand(OperandVector &Operands) {
|
||||
MCAsmParser &Parser = getParser();
|
||||
switch (getLexer().getKind()) {
|
||||
case AsmToken::Dollar: {
|
||||
|
@ -2221,12 +2227,17 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() {
|
|||
"expected immediate expression") ||
|
||||
getParser().parseExpression(Val, End) ||
|
||||
check(isa<X86MCExpr>(Val), L, "expected immediate expression"))
|
||||
return nullptr;
|
||||
return X86Operand::CreateImm(Val, Start, End);
|
||||
return true;
|
||||
Operands.push_back(X86Operand::CreateImm(Val, Start, End));
|
||||
return false;
|
||||
}
|
||||
case AsmToken::LCurly: {
|
||||
SMLoc Start = Parser.getTok().getLoc();
|
||||
return ParseRoundingModeOp(Start);
|
||||
if (std::unique_ptr<X86Operand> Op = ParseRoundingModeOp(Start)) {
|
||||
Operands.push_back(std::move(Op));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
// This a memory operand or a register. We have some parsing complications
|
||||
|
@ -2240,7 +2251,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() {
|
|||
if (getLexer().isNot(AsmToken::LParen)) {
|
||||
// No '(' so this is either a displacement expression or a register.
|
||||
if (Parser.parseExpression(Expr, EndLoc))
|
||||
return nullptr;
|
||||
return true;
|
||||
if (auto *RE = dyn_cast<X86MCExpr>(Expr)) {
|
||||
// Segment Register. Reset Expr and copy value to register.
|
||||
Expr = nullptr;
|
||||
|
@ -2248,21 +2259,31 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() {
|
|||
|
||||
// Sanity check register.
|
||||
if (Reg == X86::EIZ || Reg == X86::RIZ)
|
||||
return ErrorOperand(
|
||||
return Error(
|
||||
Loc, "%eiz and %riz can only be used as index registers",
|
||||
SMRange(Loc, EndLoc));
|
||||
if (Reg == X86::RIP)
|
||||
return ErrorOperand(Loc, "%rip can only be used as a base register",
|
||||
SMRange(Loc, EndLoc));
|
||||
return Error(Loc, "%rip can only be used as a base register",
|
||||
SMRange(Loc, EndLoc));
|
||||
// Return register that are not segment prefixes immediately.
|
||||
if (!Parser.parseOptionalToken(AsmToken::Colon))
|
||||
return X86Operand::CreateReg(Reg, Loc, EndLoc);
|
||||
if (!Parser.parseOptionalToken(AsmToken::Colon)) {
|
||||
Operands.push_back(X86Operand::CreateReg(Reg, Loc, EndLoc));
|
||||
return false;
|
||||
}
|
||||
if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(Reg))
|
||||
return ErrorOperand(Loc, "invalid segment register");
|
||||
return Error(Loc, "invalid segment register");
|
||||
// Accept a '*' absolute memory reference after the segment. Place it
|
||||
// before the full memory operand.
|
||||
if (getLexer().is(AsmToken::Star))
|
||||
Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
|
||||
}
|
||||
}
|
||||
// This is a Memory operand.
|
||||
return ParseMemOperand(Reg, Expr, Loc, EndLoc);
|
||||
if (std::unique_ptr<X86Operand> Op = ParseMemOperand(Reg, Expr, Loc, EndLoc)) {
|
||||
Operands.push_back(std::move(Op));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2889,13 +2910,11 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
|||
|
||||
// Read the operands.
|
||||
while(1) {
|
||||
if (std::unique_ptr<X86Operand> Op = ParseOperand()) {
|
||||
Operands.push_back(std::move(Op));
|
||||
if (HandleAVX512Operand(Operands))
|
||||
return true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
if (ParseOperand(Operands))
|
||||
return true;
|
||||
if (HandleAVX512Operand(Operands))
|
||||
return true;
|
||||
|
||||
// check for comma and eat it
|
||||
if (getLexer().is(AsmToken::Comma))
|
||||
Parser.Lex();
|
||||
|
|
|
@ -1120,3 +1120,7 @@ foo:
|
|||
// CHECK: encoding: [0x0f,0x84,A,A,A,A]
|
||||
// CHECK: fixup A - offset: 2, value: foo-4, kind: FK_PCRel_4
|
||||
{disp32} je foo
|
||||
|
||||
// CHECK: ljmpl *%cs:305419896
|
||||
// CHECK: encoding: [0x2e,0xff,0x2d,0x78,0x56,0x34,0x12]
|
||||
ljmp %cs:*0x12345678
|
||||
|
|
|
@ -399,6 +399,10 @@ ljmp *0xbadeface
|
|||
lcall *(%rax)
|
||||
ljmpl *(%rax)
|
||||
|
||||
// CHECK: ljmpl *%cs:305419896
|
||||
// CHECK: encoding: [0x2e,0xff,0x2c,0x25,0x78,0x56,0x34,0x12]
|
||||
ljmp %cs:*0x12345678
|
||||
|
||||
// rdar://8444631
|
||||
// CHECK: enter $31438, $0
|
||||
// CHECK: encoding: [0xc8,0xce,0x7a,0x00]
|
||||
|
|
Loading…
Reference in New Issue