mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-13 17:20:28 +00:00
[ms-inline asm] Add support for parsing complex immediate expressions. Test
cases to be submitted on clang side shortly. rdar://13663768 and PR15760 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179655 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ad74f335ef
commit
4afa9b7ffc
@ -203,23 +203,26 @@ private:
|
|||||||
class IntelExprStateMachine {
|
class IntelExprStateMachine {
|
||||||
IntelExprState State;
|
IntelExprState State;
|
||||||
unsigned BaseReg, IndexReg, TmpReg, Scale;
|
unsigned BaseReg, IndexReg, TmpReg, Scale;
|
||||||
int64_t Disp;
|
int64_t Imm;
|
||||||
const MCExpr *Sym;
|
const MCExpr *Sym;
|
||||||
StringRef SymName;
|
StringRef SymName;
|
||||||
|
bool StopOnLBrac, AddImmPrefix;
|
||||||
InfixCalculator IC;
|
InfixCalculator IC;
|
||||||
public:
|
public:
|
||||||
IntelExprStateMachine(int64_t disp) :
|
IntelExprStateMachine(int64_t imm, bool stoponlbrac, bool addimmprefix) :
|
||||||
State(IES_PLUS), BaseReg(0), IndexReg(0), TmpReg(0), Scale(1), Disp(disp),
|
State(IES_PLUS), BaseReg(0), IndexReg(0), TmpReg(0), Scale(1), Imm(imm),
|
||||||
Sym(0) {}
|
Sym(0), StopOnLBrac(stoponlbrac), AddImmPrefix(addimmprefix) {}
|
||||||
|
|
||||||
unsigned getBaseReg() { return BaseReg; }
|
unsigned getBaseReg() { return BaseReg; }
|
||||||
unsigned getIndexReg() { return IndexReg; }
|
unsigned getIndexReg() { return IndexReg; }
|
||||||
unsigned getScale() { return Scale; }
|
unsigned getScale() { return Scale; }
|
||||||
const MCExpr *getSym() { return Sym; }
|
const MCExpr *getSym() { return Sym; }
|
||||||
StringRef getSymName() { return SymName; }
|
StringRef getSymName() { return SymName; }
|
||||||
int64_t getImm() { return Disp + IC.execute(); }
|
int64_t getImm() { return Imm + IC.execute(); }
|
||||||
bool isValidEndState() { return State == IES_RBRAC; }
|
bool isValidEndState() { return State == IES_RBRAC; }
|
||||||
|
bool getStopOnLBrac() { return StopOnLBrac; }
|
||||||
|
bool getAddImmPrefix() { return AddImmPrefix; }
|
||||||
|
|
||||||
void onPlus() {
|
void onPlus() {
|
||||||
switch (State) {
|
switch (State) {
|
||||||
default:
|
default:
|
||||||
@ -1144,7 +1147,8 @@ RewriteIntelBracExpression(SmallVectorImpl<AsmRewrite> *AsmRewrites,
|
|||||||
E = AsmRewrites->end(); I != E; ++I) {
|
E = AsmRewrites->end(); I != E; ++I) {
|
||||||
if ((*I).Loc.getPointer() > BracLoc.getPointer())
|
if ((*I).Loc.getPointer() > BracLoc.getPointer())
|
||||||
continue;
|
continue;
|
||||||
if ((*I).Kind == AOK_ImmPrefix) {
|
if ((*I).Kind == AOK_ImmPrefix || (*I).Kind == AOK_Imm) {
|
||||||
|
assert (!Found && "ImmDisp already rewritten.");
|
||||||
(*I).Kind = AOK_Imm;
|
(*I).Kind = AOK_Imm;
|
||||||
(*I).Len = BracLoc.getPointer() - (*I).Loc.getPointer();
|
(*I).Len = BracLoc.getPointer() - (*I).Loc.getPointer();
|
||||||
(*I).Val = FinalImmDisp;
|
(*I).Val = FinalImmDisp;
|
||||||
@ -1155,11 +1159,9 @@ RewriteIntelBracExpression(SmallVectorImpl<AsmRewrite> *AsmRewrites,
|
|||||||
assert (Found && "Unable to rewrite ImmDisp.");
|
assert (Found && "Unable to rewrite ImmDisp.");
|
||||||
} else {
|
} else {
|
||||||
// We have a symbolic and an immediate displacement, but no displacement
|
// We have a symbolic and an immediate displacement, but no displacement
|
||||||
|
// before the bracketed expression. Put the immediate displacement
|
||||||
// before the bracketed expression.
|
// before the bracketed expression.
|
||||||
|
AsmRewrites->push_back(AsmRewrite(AOK_Imm, BracLoc, 0, FinalImmDisp));
|
||||||
// Put the immediate displacement before the bracketed expression.
|
|
||||||
AsmRewrites->push_back(AsmRewrite(AOK_Imm, BracLoc, 0,
|
|
||||||
FinalImmDisp));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove all the ImmPrefix rewrites within the brackets.
|
// Remove all the ImmPrefix rewrites within the brackets.
|
||||||
@ -1196,6 +1198,10 @@ X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
|
|||||||
// identifier. Don't try an parse it as a register.
|
// identifier. Don't try an parse it as a register.
|
||||||
if (Tok.getString().startswith("."))
|
if (Tok.getString().startswith("."))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// If we're parsing an immediate expression, we don't expect a '['.
|
||||||
|
if (SM.getStopOnLBrac() && getLexer().getKind() == AsmToken::LBrac)
|
||||||
|
break;
|
||||||
|
|
||||||
switch (getLexer().getKind()) {
|
switch (getLexer().getKind()) {
|
||||||
default: {
|
default: {
|
||||||
@ -1205,6 +1211,10 @@ X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
|
|||||||
}
|
}
|
||||||
return ErrorOperand(Tok.getLoc(), "Unexpected token!");
|
return ErrorOperand(Tok.getLoc(), "Unexpected token!");
|
||||||
}
|
}
|
||||||
|
case AsmToken::EndOfStatement: {
|
||||||
|
Done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case AsmToken::Identifier: {
|
case AsmToken::Identifier: {
|
||||||
// This could be a register or a symbolic displacement.
|
// This could be a register or a symbolic displacement.
|
||||||
unsigned TmpReg;
|
unsigned TmpReg;
|
||||||
@ -1226,7 +1236,7 @@ X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
|
|||||||
return ErrorOperand(Tok.getLoc(), "Unexpected identifier!");
|
return ErrorOperand(Tok.getLoc(), "Unexpected identifier!");
|
||||||
}
|
}
|
||||||
case AsmToken::Integer:
|
case AsmToken::Integer:
|
||||||
if (isParsingInlineAsm())
|
if (isParsingInlineAsm() && SM.getAddImmPrefix())
|
||||||
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_ImmPrefix,
|
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_ImmPrefix,
|
||||||
Tok.getLoc()));
|
Tok.getLoc()));
|
||||||
SM.onInteger(Tok.getIntVal());
|
SM.onInteger(Tok.getIntVal());
|
||||||
@ -1261,7 +1271,7 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, SMLoc Start,
|
|||||||
// Parse [ Symbol + ImmDisp ] and [ BaseReg + Scale*IndexReg + ImmDisp ]. We
|
// Parse [ Symbol + ImmDisp ] and [ BaseReg + Scale*IndexReg + ImmDisp ]. We
|
||||||
// may have already parsed an immediate displacement before the bracketed
|
// may have already parsed an immediate displacement before the bracketed
|
||||||
// expression.
|
// expression.
|
||||||
IntelExprStateMachine SM(ImmDisp);
|
IntelExprStateMachine SM(ImmDisp, /*StopOnLBrac=*/false, /*AddImmPrefix=*/true);
|
||||||
if (X86Operand *Err = ParseIntelExpression(SM, End))
|
if (X86Operand *Err = ParseIntelExpression(SM, End))
|
||||||
return Err;
|
return Err;
|
||||||
|
|
||||||
@ -1566,28 +1576,37 @@ X86Operand *X86AsmParser::ParseIntelOperand() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Immediate.
|
// Immediate.
|
||||||
if (getLexer().is(AsmToken::Integer) || getLexer().is(AsmToken::Real) ||
|
if (getLexer().is(AsmToken::Integer) || getLexer().is(AsmToken::Minus) ||
|
||||||
getLexer().is(AsmToken::Minus)) {
|
getLexer().is(AsmToken::LParen)) {
|
||||||
const MCExpr *Val;
|
AsmToken StartTok = Tok;
|
||||||
bool isInteger = getLexer().is(AsmToken::Integer);
|
IntelExprStateMachine SM(/*Imm=*/0, /*StopOnLBrac=*/true,
|
||||||
if (!getParser().parseExpression(Val, End)) {
|
/*AddImmPrefix=*/false);
|
||||||
if (isParsingInlineAsm())
|
if (X86Operand *Err = ParseIntelExpression(SM, End))
|
||||||
|
return Err;
|
||||||
|
|
||||||
|
int64_t Imm = SM.getImm();
|
||||||
|
if (isParsingInlineAsm()) {
|
||||||
|
unsigned Len = Tok.getLoc().getPointer() - Start.getPointer();
|
||||||
|
if (StartTok.getString().size() == Len)
|
||||||
|
// Just add a prefix if this wasn't a complex immediate expression.
|
||||||
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_ImmPrefix, Start));
|
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_ImmPrefix, Start));
|
||||||
// Immediate.
|
else
|
||||||
if (getLexer().isNot(AsmToken::LBrac))
|
// Otherwise, rewrite the complex expression as a single immediate.
|
||||||
return X86Operand::CreateImm(Val, Start, End);
|
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Imm, Start, Len, Imm));
|
||||||
|
|
||||||
// Only positive immediates are valid.
|
|
||||||
if (!isInteger) {
|
|
||||||
Error(Tok.getLoc(), "expected a positive immediate "
|
|
||||||
"displacement before bracketed expr.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse ImmDisp [ BaseReg + Scale*IndexReg + Disp ].
|
|
||||||
if (uint64_t ImmDisp = dyn_cast<MCConstantExpr>(Val)->getValue())
|
|
||||||
return ParseIntelMemOperand(/*SegReg=*/0, ImmDisp, Start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getLexer().isNot(AsmToken::LBrac)) {
|
||||||
|
const MCExpr *ImmExpr = MCConstantExpr::Create(Imm, getContext());
|
||||||
|
return X86Operand::CreateImm(ImmExpr, Start, End);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only positive immediates are valid.
|
||||||
|
if (Imm < 0)
|
||||||
|
return ErrorOperand(Start, "expected a positive immediate displacement "
|
||||||
|
"before bracketed expr.");
|
||||||
|
|
||||||
|
// Parse ImmDisp [ BaseReg + Scale*IndexReg + Disp ].
|
||||||
|
return ParseIntelMemOperand(/*SegReg=*/0, Imm, Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register.
|
// Register.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user