[llvm] r350966 - [X86] Fix incomplete handling of register-assigned variables in parsing.
Nirav Dave via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 11 12:17:37 PST 2019
Author: niravd
Date: Fri Jan 11 12:17:36 2019
New Revision: 350966
URL: http://llvm.org/viewvc/llvm-project?rev=350966&view=rev
Log:
[X86] Fix incomplete handling of register-assigned variables in parsing.
Teach x86 assembly operand parsing to distinguish between assembler
variable assigned to named registers and those assigned to immediate
values.
Reviewers: rnk, nickdesaulniers, void
Subscribers: hiraditya, jyknight, llvm-commits
Differential Revision: https://reviews.llvm.org/D56287
Modified:
llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp
llvm/trunk/test/MC/AsmParser/negativ_altmacro_expression.s
llvm/trunk/test/MC/X86/x86_errors.s
llvm/trunk/test/MC/X86/x86_operands.s
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=350966&r1=350965&r2=350966&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp (original)
+++ llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp Fri Jan 11 12:17:36 2019
@@ -804,8 +804,8 @@ private:
return Parser.Error(L, Msg, Range);
}
- std::nullptr_t ErrorOperand(SMLoc Loc, StringRef Msg) {
- Error(Loc, Msg);
+ std::nullptr_t ErrorOperand(SMLoc Loc, StringRef Msg, SMRange R = SMRange()) {
+ Error(Loc, Msg, R);
return nullptr;
}
@@ -835,7 +835,10 @@ private:
InlineAsmIdentifierInfo &Info,
bool IsUnevaluatedOperand, SMLoc &End);
- std::unique_ptr<X86Operand> ParseMemOperand(unsigned SegReg, SMLoc MemStart);
+ std::unique_ptr<X86Operand> ParseMemOperand(unsigned SegReg,
+ const MCExpr *&Disp,
+ const SMLoc &StartLoc,
+ SMLoc &EndLoc);
bool ParseIntelMemoryOperandSize(unsigned &Size);
std::unique_ptr<X86Operand>
@@ -1102,10 +1105,13 @@ bool X86AsmParser::ParseRegister(unsigne
if (RegNo == X86::RIZ || RegNo == X86::RIP ||
X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo) ||
X86II::isX86_64NonExtLowByteReg(RegNo) ||
- X86II::isX86_64ExtendedReg(RegNo))
- return Error(StartLoc, "register %"
- + Tok.getString() + " is only available in 64-bit mode",
+ X86II::isX86_64ExtendedReg(RegNo)) {
+ StringRef RegName = Tok.getString();
+ Parser.Lex(); // Eat register name.
+ return Error(StartLoc,
+ "register %" + RegName + " is only available in 64-bit mode",
SMRange(StartLoc, EndLoc));
+ }
}
// Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens.
@@ -1935,49 +1941,61 @@ std::unique_ptr<X86Operand> X86AsmParser
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());
- case AsmToken::Percent: {
- // Read the register.
- unsigned RegNo;
- SMLoc Start, End;
- if (ParseRegister(RegNo, Start, End)) return nullptr;
- if (RegNo == X86::EIZ || RegNo == X86::RIZ) {
- Error(Start, "%eiz and %riz can only be used as index registers",
- SMRange(Start, End));
- return nullptr;
- }
- if (RegNo == X86::RIP) {
- Error(Start, "%rip can only be used as a base register",
- SMRange(Start, End));
- return nullptr;
- }
-
- // If this is a segment register followed by a ':', then this is the start
- // of a memory reference, otherwise this is a normal register reference.
- if (getLexer().isNot(AsmToken::Colon))
- return X86Operand::CreateReg(RegNo, Start, End);
-
- if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo))
- return ErrorOperand(Start, "invalid segment register");
-
- getParser().Lex(); // Eat the colon.
- return ParseMemOperand(RegNo, Start);
- }
case AsmToken::Dollar: {
- // $42 -> immediate.
+ // $42 or $ID -> immediate.
SMLoc Start = Parser.getTok().getLoc(), End;
Parser.Lex();
const MCExpr *Val;
- if (getParser().parseExpression(Val, End))
+ // This is an immediate, so we should not parse a register. Do a precheck
+ // for '%' to supercede intra-register parse errors.
+ SMLoc L = Parser.getTok().getLoc();
+ if (check(getLexer().is(AsmToken::Percent), L,
+ "expected immediate expression") ||
+ getParser().parseExpression(Val, End) ||
+ check(isa<X86MCExpr>(Val), L, "expected immediate expression"))
return nullptr;
return X86Operand::CreateImm(Val, Start, End);
}
- case AsmToken::LCurly:{
+ case AsmToken::LCurly: {
SMLoc Start = Parser.getTok().getLoc();
return ParseRoundingModeOp(Start);
}
+ default: {
+ // This a memory operand or a register. We have some parsing complications
+ // as a '(' may be part of an immediate expression or the addressing mode
+ // block. This is complicated by the fact that an assembler-level variable
+ // may refer either to a register or an immediate expression.
+
+ SMLoc Loc = Parser.getTok().getLoc(), EndLoc;
+ const MCExpr *Expr = nullptr;
+ unsigned Reg = 0;
+ if (getLexer().isNot(AsmToken::LParen)) {
+ // No '(' so this is either a displacement expression or a register.
+ if (Parser.parseExpression(Expr, EndLoc))
+ return nullptr;
+ if (auto *RE = dyn_cast<X86MCExpr>(Expr)) {
+ // Segment Register. Reset Expr and copy value to register.
+ Expr = nullptr;
+ Reg = RE->getRegNo();
+
+ // Sanity check register.
+ if (Reg == X86::EIZ || Reg == X86::RIZ)
+ return ErrorOperand(
+ 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 register that are not segment prefixes immediately.
+ if (!Parser.parseOptionalToken(AsmToken::Colon))
+ return X86Operand::CreateReg(Reg, Loc, EndLoc);
+ if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(Reg))
+ return ErrorOperand(Loc, "invalid segment register");
+ }
+ }
+ // This is a Memory operand.
+ return ParseMemOperand(Reg, Expr, Loc, EndLoc);
+ }
}
}
@@ -2086,199 +2104,201 @@ bool X86AsmParser::HandleAVX512Operand(O
return false;
}
-/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
-/// has already been parsed if present.
+/// ParseMemOperand: 'seg : disp(basereg, indexreg, scale)'. The '%ds:' prefix
+/// has already been parsed if present. disp may be provided as well.
std::unique_ptr<X86Operand> X86AsmParser::ParseMemOperand(unsigned SegReg,
- SMLoc MemStart) {
-
+ const MCExpr *&Disp,
+ const SMLoc &StartLoc,
+ SMLoc &EndLoc) {
MCAsmParser &Parser = getParser();
- // We have to disambiguate a parenthesized expression "(4+5)" from the start
- // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
- // only way to do this without lookahead is to eat the '(' and see what is
- // after it.
- const MCExpr *Disp = MCConstantExpr::create(0, getParser().getContext());
- if (getLexer().isNot(AsmToken::LParen)) {
- SMLoc ExprEnd;
- if (getParser().parseExpression(Disp, ExprEnd)) return nullptr;
- // Disp may be a variable, handle register values.
- if (auto *RE = dyn_cast<X86MCExpr>(Disp))
- return X86Operand::CreateReg(RE->getRegNo(), MemStart, ExprEnd);
-
- // After parsing the base expression we could either have a parenthesized
- // memory address or not. If not, return now. If so, eat the (.
- if (getLexer().isNot(AsmToken::LParen)) {
- // Unless we have a segment register, treat this as an immediate.
- if (SegReg == 0)
- return X86Operand::CreateMem(getPointerWidth(), Disp, MemStart, ExprEnd);
- return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, 0, 0, 1,
- MemStart, ExprEnd);
+ SMLoc Loc;
+ // Based on the initial passed values, we may be in any of these cases, we are
+ // in one of these cases (with current position (*)):
+
+ // 1. seg : * disp (base-index-scale-expr)
+ // 2. seg : *(disp) (base-index-scale-expr)
+ // 3. seg : *(base-index-scale-expr)
+ // 4. disp *(base-index-scale-expr)
+ // 5. *(disp) (base-index-scale-expr)
+ // 6. *(base-index-scale-expr)
+ // 7. disp *
+ // 8. *(disp)
+
+ // If we do not have an displacement yet, check if we're in cases 4 or 6 by
+ // checking if the first object after the parenthesis is a register (or an
+ // identifier referring to a register) and parse the displacement or default
+ // to 0 as appropriate.
+ auto isAtMemOperand = [this]() {
+ if (this->getLexer().isNot(AsmToken::LParen))
+ return false;
+ AsmToken Buf[2];
+ StringRef Id;
+ auto TokCount = this->getLexer().peekTokens(Buf, true);
+ if (TokCount == 0)
+ return false;
+ switch (Buf[0].getKind()) {
+ case AsmToken::Percent:
+ case AsmToken::Comma:
+ return true;
+ // These lower cases are doing a peekIdentifier.
+ case AsmToken::At:
+ case AsmToken::Dollar:
+ if ((TokCount > 1) &&
+ (Buf[1].is(AsmToken::Identifier) || Buf[1].is(AsmToken::String)) &&
+ (Buf[0].getLoc().getPointer() + 1 == Buf[1].getLoc().getPointer()))
+ Id = StringRef(Buf[0].getLoc().getPointer(),
+ Buf[1].getIdentifier().size() + 1);
+ break;
+ case AsmToken::Identifier:
+ case AsmToken::String:
+ Id = Buf[0].getIdentifier();
+ break;
+ default:
+ return false;
}
+ // We have an ID. Check if it is bound to a register.
+ if (!Id.empty()) {
+ MCSymbol *Sym = this->getContext().getOrCreateSymbol(Id);
+ if (Sym->isVariable()) {
+ auto V = Sym->getVariableValue(/*SetUsed*/ false);
+ return isa<X86MCExpr>(V);
+ }
+ }
+ return false;
+ };
- // Eat the '('.
- Parser.Lex();
- } else {
- // Okay, we have a '('. We don't know if this is an expression or not, but
- // so we have to eat the ( to see beyond it.
- SMLoc LParenLoc = Parser.getTok().getLoc();
- Parser.Lex(); // Eat the '('.
-
- if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
- // Nothing to do here, fall into the code below with the '(' part of the
- // memory operand consumed.
- } else {
- SMLoc ExprEnd;
- getLexer().UnLex(AsmToken(AsmToken::LParen, "("));
-
- // It must be either an parenthesized expression, or an expression that
- // begins from a parenthesized expression, parse it now. Example: (1+2) or
- // (1+2)+3
- if (getParser().parseExpression(Disp, ExprEnd))
+ if (!Disp) {
+ // Parse immediate if we're not at a mem operand yet.
+ if (!isAtMemOperand()) {
+ if (Parser.parseTokenLoc(Loc) || Parser.parseExpression(Disp, EndLoc))
return nullptr;
+ assert(!isa<X86MCExpr>(Disp) && "Expected non-register here.");
+ } else {
+ // Disp is implicitly zero if we haven't parsed it yet.
+ Disp = MCConstantExpr::create(0, Parser.getContext());
+ }
+ }
- // After parsing the base expression we could either have a parenthesized
- // memory address or not. If not, return now. If so, eat the (.
- if (getLexer().isNot(AsmToken::LParen)) {
- // Unless we have a segment register, treat this as an immediate.
- if (SegReg == 0)
- return X86Operand::CreateMem(getPointerWidth(), Disp, LParenLoc,
- ExprEnd);
- return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, 0, 0, 1,
- MemStart, ExprEnd);
- }
+ // We are now either at the end of the operand or at the '(' at the start of a
+ // base-index-scale-expr.
- // Eat the '('.
- Parser.Lex();
- }
+ if (!parseOptionalToken(AsmToken::LParen)) {
+ if (SegReg == 0)
+ return X86Operand::CreateMem(getPointerWidth(), Disp, StartLoc, EndLoc);
+ return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, 0, 0, 1,
+ StartLoc, EndLoc);
}
- // If we reached here, then we just ate the ( of the memory operand. Process
+ // If we reached here, then eat the '(' and Process
// the rest of the memory operand.
unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
- SMLoc IndexLoc, BaseLoc;
+ SMLoc BaseLoc = getLexer().getLoc();
+ const MCExpr *E;
+ StringRef ErrMsg;
- if (getLexer().is(AsmToken::Percent)) {
- SMLoc StartLoc, EndLoc;
- BaseLoc = Parser.getTok().getLoc();
- if (ParseRegister(BaseReg, StartLoc, EndLoc)) return nullptr;
- if (BaseReg == X86::EIZ || BaseReg == X86::RIZ) {
- Error(StartLoc, "eiz and riz can only be used as index registers",
- SMRange(StartLoc, EndLoc));
+ // Parse BaseReg if one is provided.
+ if (getLexer().isNot(AsmToken::Comma) && getLexer().isNot(AsmToken::RParen)) {
+ if (Parser.parseExpression(E, EndLoc) ||
+ check(!isa<X86MCExpr>(E), BaseLoc, "expected register here"))
return nullptr;
- }
- }
- if (getLexer().is(AsmToken::Comma)) {
- Parser.Lex(); // Eat the comma.
- IndexLoc = Parser.getTok().getLoc();
+ // Sanity check register.
+ BaseReg = cast<X86MCExpr>(E)->getRegNo();
+ if (BaseReg == X86::EIZ || BaseReg == X86::RIZ)
+ return ErrorOperand(BaseLoc,
+ "eiz and riz can only be used as index registers",
+ SMRange(BaseLoc, EndLoc));
+ }
+ if (parseOptionalToken(AsmToken::Comma)) {
// Following the comma we should have either an index register, or a scale
// value. We don't support the later form, but we want to parse it
// correctly.
//
- // Not that even though it would be completely consistent to support syntax
- // like "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.
- if (getLexer().is(AsmToken::Percent)) {
- SMLoc L;
- if (ParseRegister(IndexReg, L, L))
- return nullptr;
- if (BaseReg == X86::RIP) {
- Error(IndexLoc, "%rip as base register can not have an index register");
+ // Even though it would be completely consistent to support syntax like
+ // "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.
+ if (getLexer().isNot(AsmToken::RParen)) {
+ if (Parser.parseTokenLoc(Loc) || Parser.parseExpression(E, EndLoc))
return nullptr;
- }
- if (IndexReg == X86::RIP) {
- Error(IndexLoc, "%rip is not allowed as an index register");
- return nullptr;
- }
-
- if (getLexer().isNot(AsmToken::RParen)) {
- // Parse the scale amount:
- // ::= ',' [scale-expression]
- if (parseToken(AsmToken::Comma, "expected comma in scale expression"))
- return nullptr;
-
- if (getLexer().isNot(AsmToken::RParen)) {
- SMLoc Loc = Parser.getTok().getLoc();
-
- int64_t ScaleVal;
- if (getParser().parseAbsoluteExpression(ScaleVal)){
- Error(Loc, "expected scale expression");
- return nullptr;
- }
- // Validate the scale amount.
- if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
- ScaleVal != 1) {
- Error(Loc, "scale factor in 16-bit address must be 1");
- return nullptr;
- }
- if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 &&
- ScaleVal != 8) {
- Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
- return nullptr;
+ if (!isa<X86MCExpr>(E)) {
+ // We've parsed an unexpected Scale Value instead of an index
+ // register. Interpret it as an absolute.
+ int64_t ScaleVal;
+ if (!E->evaluateAsAbsolute(ScaleVal, getStreamer().getAssemblerPtr()))
+ return ErrorOperand(Loc, "expected absolute expression");
+ if (ScaleVal != 1)
+ Warning(Loc, "scale factor without index register is ignored");
+ Scale = 1;
+ } else { // IndexReg Found.
+ IndexReg = cast<X86MCExpr>(E)->getRegNo();
+
+ if (BaseReg == X86::RIP)
+ return ErrorOperand(
+ Loc, "%rip as base register can not have an index register");
+ if (IndexReg == X86::RIP)
+ return ErrorOperand(Loc, "%rip is not allowed as an index register");
+
+ if (parseOptionalToken(AsmToken::Comma)) {
+ // Parse the scale amount:
+ // ::= ',' [scale-expression]
+
+ // A scale amount without an index is ignored.
+ if (getLexer().isNot(AsmToken::RParen)) {
+ int64_t ScaleVal;
+ if (Parser.parseTokenLoc(Loc) ||
+ Parser.parseAbsoluteExpression(ScaleVal))
+ return ErrorOperand(Loc, "expected scale expression");
+ Scale = (unsigned)ScaleVal;
+ // Validate the scale amount.
+ if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
+ Scale != 1)
+ return ErrorOperand(Loc,
+ "scale factor in 16-bit address must be 1");
+ if (checkScale(Scale, ErrMsg))
+ return ErrorOperand(Loc, ErrMsg);
}
- Scale = (unsigned)ScaleVal;
}
}
- } else if (getLexer().isNot(AsmToken::RParen)) {
- // A scale amount without an index is ignored.
- // index.
- SMLoc Loc = Parser.getTok().getLoc();
-
- int64_t Value;
- if (getParser().parseAbsoluteExpression(Value))
- return nullptr;
-
- if (Value != 1)
- Warning(Loc, "scale factor without index register is ignored");
- Scale = 1;
}
}
// Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
- SMLoc MemEnd = Parser.getTok().getEndLoc();
if (parseToken(AsmToken::RParen, "unexpected token in memory operand"))
return nullptr;
- // 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 (BaseReg == X86::DX && IndexReg == 0 && Scale == 1 &&
- SegReg == 0 && isa<MCConstantExpr>(Disp) &&
- cast<MCConstantExpr>(Disp)->getValue() == 0)
+ // This is to support otherwise illegal operand (%dx) found in various
+ // unofficial manuals examples (e.g. "out[s]?[bwl]? %al, (%dx)") and must now
+ // be supported. Mark such DX variants separately fix only in special cases.
+ if (BaseReg == X86::DX && IndexReg == 0 && Scale == 1 && SegReg == 0 &&
+ isa<MCConstantExpr>(Disp) && cast<MCConstantExpr>(Disp)->getValue() == 0)
return X86Operand::CreateDXReg(BaseLoc, BaseLoc);
- StringRef ErrMsg;
if (CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),
- ErrMsg)) {
- Error(BaseLoc, ErrMsg);
- return nullptr;
- }
+ ErrMsg))
+ return ErrorOperand(BaseLoc, ErrMsg);
if (SegReg || BaseReg || IndexReg)
return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg,
- IndexReg, Scale, MemStart, MemEnd);
- return X86Operand::CreateMem(getPointerWidth(), Disp, MemStart, MemEnd);
+ IndexReg, Scale, StartLoc, EndLoc);
+ return X86Operand::CreateMem(getPointerWidth(), Disp, StartLoc, EndLoc);
}
// Parse either a standard primary expression or a register.
bool X86AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
MCAsmParser &Parser = getParser();
- if (Parser.parsePrimaryExpr(Res, EndLoc)) {
+ // See if this is a register first.
+ if (getTok().is(AsmToken::Percent) ||
+ (isParsingIntelSyntax() && getTok().is(AsmToken::Identifier) &&
+ MatchRegisterName(Parser.getTok().getString()))) {
SMLoc StartLoc = Parser.getTok().getLoc();
- // Normal Expression parse fails, check if it could be a register.
unsigned RegNo;
- bool TryRegParse =
- getTok().is(AsmToken::Percent) ||
- (isParsingIntelSyntax() && getTok().is(AsmToken::Identifier));
- if (!TryRegParse || ParseRegister(RegNo, StartLoc, EndLoc))
+ if (ParseRegister(RegNo, StartLoc, EndLoc))
return true;
- // Clear previous parse error and return correct expression.
- Parser.clearPendingErrors();
Res = X86MCExpr::create(RegNo, Parser.getContext());
return false;
}
-
- return false;
+ return Parser.parsePrimaryExpr(Res, EndLoc);
}
bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
Modified: llvm/trunk/test/MC/AsmParser/negativ_altmacro_expression.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AsmParser/negativ_altmacro_expression.s?rev=350966&r1=350965&r2=350966&view=diff
==============================================================================
--- llvm/trunk/test/MC/AsmParser/negativ_altmacro_expression.s (original)
+++ llvm/trunk/test/MC/AsmParser/negativ_altmacro_expression.s Fri Jan 11 12:17:36 2019
@@ -6,7 +6,7 @@
# .noaltmacro returns the format into a regular macro handling.
# The default mode is ".noaltmacro" as first test checks.
-# CHECK: error: unknown token in expression
+# CHECK: error: expected immediate expression
# CHECK-NEXT: addl $%(1%4), %eax
.macro inner_percent arg
addl $\arg, %eax
@@ -18,12 +18,12 @@ inner_percent %(1%4)
.noaltmacro
# CHECK: multi_args_macro %(1+4-5) 1 %2+1
-# CHECK: error: unknown token in expression
+# CHECK: error: expected immediate expression
# CHECK-NEXT: addl $%(1+4-5), %eax
# CHECK: multi_args_macro %(1+4-5),1,%4%10
-# CHECK: error: unknown token in expression
+# CHECK: error: expected immediate expression
# CHECK-NEXT: addl $%(1+4-5), %eax
.macro multi_args_macro arg1 arg2 arg3
label\arg1\arg2\arg3:
Modified: llvm/trunk/test/MC/X86/x86_errors.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/x86_errors.s?rev=350966&r1=350965&r2=350966&view=diff
==============================================================================
--- llvm/trunk/test/MC/X86/x86_errors.s (original)
+++ llvm/trunk/test/MC/X86/x86_errors.s Fri Jan 11 12:17:36 2019
@@ -118,3 +118,39 @@ mov (%rax,%eiz), %ebx
// 32: error: register %riz is only available in 64-bit mode
// 64: error: base register is 32-bit, but index register is not
mov (%eax,%riz), %ebx
+
+
+// Parse errors from assembler parsing.
+
+v_ecx = %ecx
+v_eax = %eax
+v_gs = %gs
+v_imm = 4
+$test = %ebx
+
+// 32: 7: error: expected register here
+// 64: 7: error: expected register here
+mov 4(4), %eax
+
+// 32: 7: error: expected register here
+// 64: 7: error: expected register here
+mov 5(v_imm), %eax
+
+// 32: 7: error: invalid register name
+// 64: 7: error: invalid register name
+mov 6(%v_imm), %eax
+
+// 32: 8: warning: scale factor without index register is ignored
+// 64: 8: warning: scale factor without index register is ignored
+mov 7(,v_imm), %eax
+
+// 64: 6: error: expected immediate expression
+mov $%eax, %ecx
+
+// 32: 6: error: expected immediate expression
+// 64: 6: error: expected immediate expression
+mov $v_eax, %ecx
+
+// 32: error: unexpected token in argument list
+// 64: error: unexpected token in argument list
+mov v_ecx(%eax), %ecx
Modified: llvm/trunk/test/MC/X86/x86_operands.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/x86_operands.s?rev=350966&r1=350965&r2=350966&view=diff
==============================================================================
--- llvm/trunk/test/MC/X86/x86_operands.s (original)
+++ llvm/trunk/test/MC/X86/x86_operands.s Fri Jan 11 12:17:36 2019
@@ -61,3 +61,406 @@ foo:
# CHECK: movl %gs:8, %eax
movl %gs:8, %eax
+# Make sure we handle parsing uses of variables assigned
+# to registers in operands.
+
+v_ecx = %ecx
+v_eax = %eax
+v_gs = %gs
+v_imm = 4
+
+#CHECK: movl %eax, %ecx
+ movl %eax, v_ecx
+
+#CHECK: movl $1, %gs:0
+ movl $1, v_gs:(,)
+#CHECK: movl $1, %gs:(,%eax)
+ movl $1, v_gs:(,%eax)
+#CHECK: movl $1, %gs:(,%eax,2)
+ movl $1, v_gs:(,%eax,2)
+#CHECK: movl $1, %gs:(,%eax,4)
+ movl $1, v_gs:(,%eax,v_imm)
+#CHECK: movl $1, %gs:(,%eax)
+ movl $1, v_gs:(,v_eax)
+#CHECK: movl $1, %gs:(,%eax,2)
+ movl $1, v_gs:(,v_eax,2)
+#CHECK: movl $1, %gs:(,%eax,4)
+ movl $1, v_gs:(,v_eax,v_imm)
+#CHECK: movl $1, %gs:(%ecx)
+ movl $1, v_gs:(%ecx)
+#CHECK: movl $1, %gs:(%ecx)
+ movl $1, v_gs:(%ecx,)
+#CHECK: movl $1, %gs:(%ecx,%eax)
+ movl $1, v_gs:(%ecx,%eax)
+#CHECK: movl $1, %gs:(%ecx,%eax,2)
+ movl $1, v_gs:(%ecx,%eax,2)
+#CHECK: movl $1, %gs:(%ecx,%eax,4)
+ movl $1, v_gs:(%ecx,%eax,v_imm)
+#CHECK: movl $1, %gs:(%ecx,%eax)
+ movl $1, v_gs:(%ecx,v_eax)
+#CHECK: movl $1, %gs:(%ecx,%eax,2)
+ movl $1, v_gs:(%ecx,v_eax,2)
+#CHECK: movl $1, %gs:(%ecx,%eax,4)
+ movl $1, v_gs:(%ecx,v_eax,v_imm)
+#CHECK: movl $1, %gs:(%ecx)
+ movl $1, v_gs:(v_ecx)
+#CHECK: movl $1, %gs:(%ecx)
+ movl $1, v_gs:(v_ecx,)
+#CHECK: movl $1, %gs:(%ecx,%eax)
+ movl $1, v_gs:(v_ecx,%eax)
+#CHECK: movl $1, %gs:(%ecx,%eax,2)
+ movl $1, v_gs:(v_ecx,%eax,2)
+#CHECK: movl $1, %gs:(%ecx,%eax,4)
+ movl $1, v_gs:(v_ecx,%eax,v_imm)
+#CHECK: movl $1, %gs:(%ecx,%eax)
+ movl $1, v_gs:(v_ecx,v_eax)
+#CHECK: movl $1, %gs:(%ecx,%eax,2)
+ movl $1, v_gs:(v_ecx,v_eax,2)
+#CHECK: movl $1, %gs:(%ecx,%eax,4)
+ movl $1, v_gs:(v_ecx,v_eax,v_imm)
+#CHECK: movl $1, %gs:4
+ movl $1, v_gs:4
+#CHECK: movl $1, %gs:4
+ movl $1, v_gs:4()
+#CHECK: movl $1, %gs:4
+ movl $1, v_gs:4(,)
+#CHECK: movl $1, %gs:4(,%eax)
+ movl $1, v_gs:4(,%eax)
+#CHECK: movl $1, %gs:4(,%eax,2)
+ movl $1, v_gs:4(,%eax,2)
+#CHECK: movl $1, %gs:4(,%eax,4)
+ movl $1, v_gs:4(,%eax,v_imm)
+#CHECK: movl $1, %gs:4(,%eax)
+ movl $1, v_gs:4(,v_eax)
+#CHECK: movl $1, %gs:4(,%eax,2)
+ movl $1, v_gs:4(,v_eax,2)
+#CHECK: movl $1, %gs:4(,%eax,4)
+ movl $1, v_gs:4(,v_eax,v_imm)
+#CHECK: movl $1, %gs:4(%ecx)
+ movl $1, v_gs:4(%ecx)
+#CHECK: movl $1, %gs:4(%ecx)
+ movl $1, v_gs:4(%ecx,)
+#CHECK: movl $1, %gs:4(%ecx,%eax)
+ movl $1, v_gs:4(%ecx,%eax)
+#CHECK: movl $1, %gs:4(%ecx,%eax,2)
+ movl $1, v_gs:4(%ecx,%eax,2)
+#CHECK: movl $1, %gs:4(%ecx,%eax,4)
+ movl $1, v_gs:4(%ecx,%eax,v_imm)
+#CHECK: movl $1, %gs:4(%ecx,%eax)
+ movl $1, v_gs:4(%ecx,v_eax)
+#CHECK: movl $1, %gs:4(%ecx,%eax,2)
+ movl $1, v_gs:4(%ecx,v_eax,2)
+#CHECK: movl $1, %gs:4(%ecx,%eax,4)
+ movl $1, v_gs:4(%ecx,v_eax,v_imm)
+#CHECK: movl $1, %gs:4(%ecx)
+ movl $1, v_gs:4(v_ecx)
+#CHECK: movl $1, %gs:4(%ecx)
+ movl $1, v_gs:4(v_ecx,)
+#CHECK: movl $1, %gs:4(%ecx,%eax)
+ movl $1, v_gs:4(v_ecx,%eax)
+#CHECK: movl $1, %gs:4(%ecx,%eax,2)
+ movl $1, v_gs:4(v_ecx,%eax,2)
+#CHECK: movl $1, %gs:4(%ecx,%eax,4)
+ movl $1, v_gs:4(v_ecx,%eax,v_imm)
+#CHECK: movl $1, %gs:4(%ecx,%eax)
+ movl $1, v_gs:4(v_ecx,v_eax)
+#CHECK: movl $1, %gs:4(%ecx,%eax,2)
+ movl $1, v_gs:4(v_ecx,v_eax,2)
+#CHECK: movl $1, %gs:4(%ecx,%eax,4)
+ movl $1, v_gs:4(v_ecx,v_eax,v_imm)
+#CHECK: movl $1, %gs:4
+ movl $1, v_gs:v_imm
+#CHECK: movl $1, %gs:4
+ movl $1, v_gs:v_imm()
+#CHECK: movl $1, %gs:4
+ movl $1, v_gs:v_imm(,)
+#CHECK: movl $1, %gs:4(,%eax)
+ movl $1, v_gs:v_imm(,%eax)
+#CHECK: movl $1, %gs:4(,%eax,2)
+ movl $1, v_gs:v_imm(,%eax,2)
+#CHECK: movl $1, %gs:4(,%eax,4)
+ movl $1, v_gs:v_imm(,%eax,v_imm)
+#CHECK: movl $1, %gs:4(,%eax)
+ movl $1, v_gs:v_imm(,v_eax)
+#CHECK: movl $1, %gs:4(,%eax,2)
+ movl $1, v_gs:v_imm(,v_eax,2)
+#CHECK: movl $1, %gs:4(,%eax,4)
+ movl $1, v_gs:v_imm(,v_eax,v_imm)
+#CHECK: movl $1, %gs:4(%ecx)
+ movl $1, v_gs:v_imm(%ecx)
+#CHECK: movl $1, %gs:4(%ecx)
+ movl $1, v_gs:v_imm(%ecx,)
+#CHECK: movl $1, %gs:4(%ecx,%eax)
+ movl $1, v_gs:v_imm(%ecx,%eax)
+#CHECK: movl $1, %gs:4(%ecx,%eax,2)
+ movl $1, v_gs:v_imm(%ecx,%eax,2)
+#CHECK: movl $1, %gs:4(%ecx,%eax,4)
+ movl $1, v_gs:v_imm(%ecx,%eax,v_imm)
+#CHECK: movl $1, %gs:4(%ecx,%eax)
+ movl $1, v_gs:v_imm(%ecx,v_eax)
+#CHECK: movl $1, %gs:4(%ecx,%eax,2)
+ movl $1, v_gs:v_imm(%ecx,v_eax,2)
+#CHECK: movl $1, %gs:4(%ecx,%eax,4)
+ movl $1, v_gs:v_imm(%ecx,v_eax,v_imm)
+#CHECK: movl $1, %gs:4(%ecx)
+ movl $1, v_gs:v_imm(v_ecx)
+#CHECK: movl $1, %gs:4(%ecx)
+ movl $1, v_gs:v_imm(v_ecx,)
+#CHECK: movl $1, %gs:4(%ecx,%eax)
+ movl $1, v_gs:v_imm(v_ecx,%eax)
+#CHECK: movl $1, %gs:4(%ecx,%eax,2)
+ movl $1, v_gs:v_imm(v_ecx,%eax,2)
+#CHECK: movl $1, %gs:4(%ecx,%eax,4)
+ movl $1, v_gs:v_imm(v_ecx,%eax,v_imm)
+#CHECK: movl $1, %gs:4(%ecx,%eax)
+ movl $1, v_gs:v_imm(v_ecx,v_eax)
+#CHECK: movl $1, %gs:4(%ecx,%eax,2)
+ movl $1, v_gs:v_imm(v_ecx,v_eax,2)
+#CHECK: movl $1, %gs:4(%ecx,%eax,4)
+ movl $1, v_gs:v_imm(v_ecx,v_eax,v_imm)
+#CHECK: movl $1, %gs:8
+ movl $1, v_gs:(v_imm+4)
+#CHECK: movl $1, %gs:8
+ movl $1, v_gs:(v_imm+4)()
+#CHECK: movl $1, %gs:8
+ movl $1, v_gs:(v_imm+4)(,)
+#CHECK: movl $1, %gs:8(,%eax)
+ movl $1, v_gs:(v_imm+4)(,%eax)
+#CHECK: movl $1, %gs:8(,%eax,2)
+ movl $1, v_gs:(v_imm+4)(,%eax,2)
+#CHECK: movl $1, %gs:8(,%eax,4)
+ movl $1, v_gs:(v_imm+4)(,%eax,v_imm)
+#CHECK: movl $1, %gs:8(,%eax)
+ movl $1, v_gs:(v_imm+4)(,v_eax)
+#CHECK: movl $1, %gs:8(,%eax,2)
+ movl $1, v_gs:(v_imm+4)(,v_eax,2)
+#CHECK: movl $1, %gs:8(,%eax,4)
+ movl $1, v_gs:(v_imm+4)(,v_eax,v_imm)
+#CHECK: movl $1, %gs:8(%ecx)
+ movl $1, v_gs:(v_imm+4)(%ecx)
+#CHECK: movl $1, %gs:8(%ecx)
+ movl $1, v_gs:(v_imm+4)(%ecx,)
+#CHECK: movl $1, %gs:8(%ecx,%eax)
+ movl $1, v_gs:(v_imm+4)(%ecx,%eax)
+#CHECK: movl $1, %gs:8(%ecx,%eax,2)
+ movl $1, v_gs:(v_imm+4)(%ecx,%eax,2)
+#CHECK: movl $1, %gs:8(%ecx,%eax,4)
+ movl $1, v_gs:(v_imm+4)(%ecx,%eax,v_imm)
+#CHECK: movl $1, %gs:8(%ecx,%eax)
+ movl $1, v_gs:(v_imm+4)(%ecx,v_eax)
+#CHECK: movl $1, %gs:8(%ecx,%eax,2)
+ movl $1, v_gs:(v_imm+4)(%ecx,v_eax,2)
+#CHECK: movl $1, %gs:8(%ecx,%eax,4)
+ movl $1, v_gs:(v_imm+4)(%ecx,v_eax,v_imm)
+#CHECK: movl $1, %gs:8(%ecx)
+ movl $1, v_gs:(v_imm+4)(v_ecx)
+#CHECK: movl $1, %gs:8(%ecx)
+ movl $1, v_gs:(v_imm+4)(v_ecx,)
+#CHECK: movl $1, %gs:8(%ecx,%eax)
+ movl $1, v_gs:(v_imm+4)(v_ecx,%eax)
+#CHECK: movl $1, %gs:8(%ecx,%eax,2)
+ movl $1, v_gs:(v_imm+4)(v_ecx,%eax,2)
+#CHECK: movl $1, %gs:8(%ecx,%eax,4)
+ movl $1, v_gs:(v_imm+4)(v_ecx,%eax,v_imm)
+#CHECK: movl $1, %gs:8(%ecx,%eax)
+ movl $1, v_gs:(v_imm+4)(v_ecx,v_eax)
+#CHECK: movl $1, %gs:8(%ecx,%eax,2)
+ movl $1, v_gs:(v_imm+4)(v_ecx,v_eax,2)
+#CHECK: movl $1, %gs:8(%ecx,%eax,4)
+ movl $1, v_gs:(v_imm+4)(v_ecx,v_eax,v_imm)
+#CHECK: movl $1, %fs:0
+ movl $1, %fs:(,)
+#CHECK: movl $1, %fs:(,%eax)
+ movl $1, %fs:(,%eax)
+#CHECK: movl $1, %fs:(,%eax,2)
+ movl $1, %fs:(,%eax,2)
+#CHECK: movl $1, %fs:(,%eax,4)
+ movl $1, %fs:(,%eax,v_imm)
+#CHECK: movl $1, %fs:(,%eax)
+ movl $1, %fs:(,v_eax)
+#CHECK: movl $1, %fs:(,%eax,2)
+ movl $1, %fs:(,v_eax,2)
+#CHECK: movl $1, %fs:(,%eax,4)
+ movl $1, %fs:(,v_eax,v_imm)
+#CHECK: movl $1, %fs:(%ecx)
+ movl $1, %fs:(%ecx)
+#CHECK: movl $1, %fs:(%ecx)
+ movl $1, %fs:(%ecx,)
+#CHECK: movl $1, %fs:(%ecx,%eax)
+ movl $1, %fs:(%ecx,%eax)
+#CHECK: movl $1, %fs:(%ecx,%eax,2)
+ movl $1, %fs:(%ecx,%eax,2)
+#CHECK: movl $1, %fs:(%ecx,%eax,4)
+ movl $1, %fs:(%ecx,%eax,v_imm)
+#CHECK: movl $1, %fs:(%ecx,%eax)
+ movl $1, %fs:(%ecx,v_eax)
+#CHECK: movl $1, %fs:(%ecx,%eax,2)
+ movl $1, %fs:(%ecx,v_eax,2)
+#CHECK: movl $1, %fs:(%ecx,%eax,4)
+ movl $1, %fs:(%ecx,v_eax,v_imm)
+#CHECK: movl $1, %fs:(%ecx)
+ movl $1, %fs:(v_ecx)
+#CHECK: movl $1, %fs:(%ecx)
+ movl $1, %fs:(v_ecx,)
+#CHECK: movl $1, %fs:(%ecx,%eax)
+ movl $1, %fs:(v_ecx,%eax)
+#CHECK: movl $1, %fs:(%ecx,%eax,2)
+ movl $1, %fs:(v_ecx,%eax,2)
+#CHECK: movl $1, %fs:(%ecx,%eax,4)
+ movl $1, %fs:(v_ecx,%eax,v_imm)
+#CHECK: movl $1, %fs:(%ecx,%eax)
+ movl $1, %fs:(v_ecx,v_eax)
+#CHECK: movl $1, %fs:(%ecx,%eax,2)
+ movl $1, %fs:(v_ecx,v_eax,2)
+#CHECK: movl $1, %fs:(%ecx,%eax,4)
+ movl $1, %fs:(v_ecx,v_eax,v_imm)
+#CHECK: movl $1, %fs:4
+ movl $1, %fs:4
+#CHECK: movl $1, %fs:4
+ movl $1, %fs:4()
+#CHECK: movl $1, %fs:4
+ movl $1, %fs:4(,)
+#CHECK: movl $1, %fs:4(,%eax)
+ movl $1, %fs:4(,%eax)
+#CHECK: movl $1, %fs:4(,%eax,2)
+ movl $1, %fs:4(,%eax,2)
+#CHECK: movl $1, %fs:4(,%eax,4)
+ movl $1, %fs:4(,%eax,v_imm)
+#CHECK: movl $1, %fs:4(,%eax)
+ movl $1, %fs:4(,v_eax)
+#CHECK: movl $1, %fs:4(,%eax,2)
+ movl $1, %fs:4(,v_eax,2)
+#CHECK: movl $1, %fs:4(,%eax,4)
+ movl $1, %fs:4(,v_eax,v_imm)
+#CHECK: movl $1, %fs:4(%ecx)
+ movl $1, %fs:4(%ecx)
+#CHECK: movl $1, %fs:4(%ecx)
+ movl $1, %fs:4(%ecx,)
+#CHECK: movl $1, %fs:4(%ecx,%eax)
+ movl $1, %fs:4(%ecx,%eax)
+#CHECK: movl $1, %fs:4(%ecx,%eax,2)
+ movl $1, %fs:4(%ecx,%eax,2)
+#CHECK: movl $1, %fs:4(%ecx,%eax,4)
+ movl $1, %fs:4(%ecx,%eax,v_imm)
+#CHECK: movl $1, %fs:4(%ecx,%eax)
+ movl $1, %fs:4(%ecx,v_eax)
+#CHECK: movl $1, %fs:4(%ecx,%eax,2)
+ movl $1, %fs:4(%ecx,v_eax,2)
+#CHECK: movl $1, %fs:4(%ecx,%eax,4)
+ movl $1, %fs:4(%ecx,v_eax,v_imm)
+#CHECK: movl $1, %fs:4(%ecx)
+ movl $1, %fs:4(v_ecx)
+#CHECK: movl $1, %fs:4(%ecx)
+ movl $1, %fs:4(v_ecx,)
+#CHECK: movl $1, %fs:4(%ecx,%eax)
+ movl $1, %fs:4(v_ecx,%eax)
+#CHECK: movl $1, %fs:4(%ecx,%eax,2)
+ movl $1, %fs:4(v_ecx,%eax,2)
+#CHECK: movl $1, %fs:4(%ecx,%eax,4)
+ movl $1, %fs:4(v_ecx,%eax,v_imm)
+#CHECK: movl $1, %fs:4(%ecx,%eax)
+ movl $1, %fs:4(v_ecx,v_eax)
+#CHECK: movl $1, %fs:4(%ecx,%eax,2)
+ movl $1, %fs:4(v_ecx,v_eax,2)
+#CHECK: movl $1, %fs:4(%ecx,%eax,4)
+ movl $1, %fs:4(v_ecx,v_eax,v_imm)
+#CHECK: movl $1, %fs:4
+ movl $1, %fs:v_imm
+#CHECK: movl $1, %fs:4
+ movl $1, %fs:v_imm()
+#CHECK: movl $1, %fs:4
+ movl $1, %fs:v_imm(,)
+#CHECK: movl $1, %fs:4(,%eax)
+ movl $1, %fs:v_imm(,%eax)
+#CHECK: movl $1, %fs:4(,%eax,2)
+ movl $1, %fs:v_imm(,%eax,2)
+#CHECK: movl $1, %fs:4(,%eax,4)
+ movl $1, %fs:v_imm(,%eax,v_imm)
+#CHECK: movl $1, %fs:4(,%eax)
+ movl $1, %fs:v_imm(,v_eax)
+#CHECK: movl $1, %fs:4(,%eax,2)
+ movl $1, %fs:v_imm(,v_eax,2)
+#CHECK: movl $1, %fs:4(,%eax,4)
+ movl $1, %fs:v_imm(,v_eax,v_imm)
+#CHECK: movl $1, %fs:4(%ecx)
+ movl $1, %fs:v_imm(%ecx)
+#CHECK: movl $1, %fs:4(%ecx)
+ movl $1, %fs:v_imm(%ecx,)
+#CHECK: movl $1, %fs:4(%ecx,%eax)
+ movl $1, %fs:v_imm(%ecx,%eax)
+#CHECK: movl $1, %fs:4(%ecx,%eax,2)
+ movl $1, %fs:v_imm(%ecx,%eax,2)
+#CHECK: movl $1, %fs:4(%ecx,%eax,4)
+ movl $1, %fs:v_imm(%ecx,%eax,v_imm)
+#CHECK: movl $1, %fs:4(%ecx,%eax)
+ movl $1, %fs:v_imm(%ecx,v_eax)
+#CHECK: movl $1, %fs:4(%ecx,%eax,2)
+ movl $1, %fs:v_imm(%ecx,v_eax,2)
+#CHECK: movl $1, %fs:4(%ecx,%eax,4)
+ movl $1, %fs:v_imm(%ecx,v_eax,v_imm)
+#CHECK: movl $1, %fs:4(%ecx)
+ movl $1, %fs:v_imm(v_ecx)
+#CHECK: movl $1, %fs:4(%ecx)
+ movl $1, %fs:v_imm(v_ecx,)
+#CHECK: movl $1, %fs:4(%ecx,%eax)
+ movl $1, %fs:v_imm(v_ecx,%eax)
+#CHECK: movl $1, %fs:4(%ecx,%eax,2)
+ movl $1, %fs:v_imm(v_ecx,%eax,2)
+#CHECK: movl $1, %fs:4(%ecx,%eax,4)
+ movl $1, %fs:v_imm(v_ecx,%eax,v_imm)
+#CHECK: movl $1, %fs:4(%ecx,%eax)
+ movl $1, %fs:v_imm(v_ecx,v_eax)
+#CHECK: movl $1, %fs:4(%ecx,%eax,2)
+ movl $1, %fs:v_imm(v_ecx,v_eax,2)
+#CHECK: movl $1, %fs:4(%ecx,%eax,4)
+ movl $1, %fs:v_imm(v_ecx,v_eax,v_imm)
+#CHECK: movl $1, %fs:8
+ movl $1, %fs:(v_imm+4)
+#CHECK: movl $1, %fs:8
+ movl $1, %fs:(v_imm+4)()
+#CHECK: movl $1, %fs:8
+ movl $1, %fs:(v_imm+4)(,)
+#CHECK: movl $1, %fs:8(,%eax)
+ movl $1, %fs:(v_imm+4)(,%eax)
+#CHECK: movl $1, %fs:8(,%eax,2)
+ movl $1, %fs:(v_imm+4)(,%eax,2)
+#CHECK: movl $1, %fs:8(,%eax,4)
+ movl $1, %fs:(v_imm+4)(,%eax,v_imm)
+#CHECK: movl $1, %fs:8(,%eax)
+ movl $1, %fs:(v_imm+4)(,v_eax)
+#CHECK: movl $1, %fs:8(,%eax,2)
+ movl $1, %fs:(v_imm+4)(,v_eax,2)
+#CHECK: movl $1, %fs:8(,%eax,4)
+ movl $1, %fs:(v_imm+4)(,v_eax,v_imm)
+#CHECK: movl $1, %fs:8(%ecx)
+ movl $1, %fs:(v_imm+4)(%ecx)
+#CHECK: movl $1, %fs:8(%ecx)
+ movl $1, %fs:(v_imm+4)(%ecx,)
+#CHECK: movl $1, %fs:8(%ecx,%eax)
+ movl $1, %fs:(v_imm+4)(%ecx,%eax)
+#CHECK: movl $1, %fs:8(%ecx,%eax,2)
+ movl $1, %fs:(v_imm+4)(%ecx,%eax,2)
+#CHECK: movl $1, %fs:8(%ecx,%eax,4)
+ movl $1, %fs:(v_imm+4)(%ecx,%eax,v_imm)
+#CHECK: movl $1, %fs:8(%ecx,%eax)
+ movl $1, %fs:(v_imm+4)(%ecx,v_eax)
+#CHECK: movl $1, %fs:8(%ecx,%eax,2)
+ movl $1, %fs:(v_imm+4)(%ecx,v_eax,2)
+#CHECK: movl $1, %fs:8(%ecx,%eax,4)
+ movl $1, %fs:(v_imm+4)(%ecx,v_eax,v_imm)
+#CHECK: movl $1, %fs:8(%ecx)
+ movl $1, %fs:(v_imm+4)(v_ecx)
+#CHECK: movl $1, %fs:8(%ecx)
+ movl $1, %fs:(v_imm+4)(v_ecx,)
+#CHECK: movl $1, %fs:8(%ecx,%eax)
+ movl $1, %fs:(v_imm+4)(v_ecx,%eax)
+#CHECK: movl $1, %fs:8(%ecx,%eax,2)
+ movl $1, %fs:(v_imm+4)(v_ecx,%eax,2)
+#CHECK: movl $1, %fs:8(%ecx,%eax,4)
+ movl $1, %fs:(v_imm+4)(v_ecx,%eax,v_imm)
+#CHECK: movl $1, %fs:8(%ecx,%eax)
+ movl $1, %fs:(v_imm+4)(v_ecx,v_eax)
+#CHECK: movl $1, %fs:8(%ecx,%eax,2)
+ movl $1, %fs:(v_imm+4)(v_ecx,v_eax,2)
+#CHECK: movl $1, %fs:8(%ecx,%eax,4)
+ movl $1, %fs:(v_imm+4)(v_ecx,v_eax,v_imm)
More information about the llvm-commits
mailing list