1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 11:42:57 +01:00

[X86][MS-compatability][llvm] allow MS TYPE/SIZE/LENGTH operators as a part of a compound expression

This patch introduces X86AsmParser with the ability to handle the aforementioned ops within compound "MS" arithmetical expressions.
Currently - only supported as a stand alone Operand, e.g.:
"TYPE X"
now allowed :
"4 + TYPE X * 128"

Clang side: https://reviews.llvm.org/D31174

Differential Revision: https://reviews.llvm.org/D31173

llvm-svn: 298425
This commit is contained in:
Coby Tayree 2017-03-21 19:31:55 +00:00
parent 68c26974a8
commit 06adb3d9b0

View File

@ -98,6 +98,14 @@ private:
IC_REGISTER
};
enum IntelOperatorKind {
IOK_INVALID = 0,
IOK_LENGTH,
IOK_SIZE,
IOK_TYPE,
IOK_OFFSET
};
class InfixCalculator {
typedef std::pair< InfixCalculatorTok, int64_t > ICToken;
SmallVector<InfixCalculatorTok, 4> InfixOperatorStack;
@ -704,7 +712,8 @@ private:
std::unique_ptr<X86Operand> ParseIntelOperand();
std::unique_ptr<X86Operand> ParseIntelOffsetOfOperator();
bool ParseIntelDotOperator(const MCExpr *Disp, const MCExpr *&NewDisp);
std::unique_ptr<X86Operand> ParseIntelOperator(unsigned OpKind);
unsigned IdentifyIntelOperator(StringRef Name);
unsigned ParseIntelOperator(unsigned OpKind);
std::unique_ptr<X86Operand>
ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, unsigned Size);
std::unique_ptr<X86Operand> ParseRoundingModeOp(SMLoc Start, SMLoc End);
@ -814,6 +823,7 @@ private:
/// }
public:
X86AsmParser(const MCSubtargetInfo &sti, MCAsmParser &Parser,
const MCInstrInfo &mii, const MCTargetOptions &Options)
: MCTargetAsmParser(Options, sti), MII(mii), InstInfo(nullptr),
@ -1266,10 +1276,12 @@ RewriteIntelBracExpression(SmallVectorImpl<AsmRewrite> &AsmRewrites,
}
}
// Remove all the ImmPrefix rewrites within the brackets.
// We may have some Imm rewrties as a result of an operator applying,
// remove them as well
for (AsmRewrite &AR : AsmRewrites) {
if (AR.Loc.getPointer() < StartInBrac.getPointer())
continue;
if (AR.Kind == AOK_ImmPrefix)
if (AR.Kind == AOK_ImmPrefix || AR.Kind == AOK_Imm)
AR.Kind = AOK_Delete;
}
const char *SymLocPtr = SymName.data();
@ -1324,31 +1336,34 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
const MCExpr *Val;
SMLoc IdentLoc = Tok.getLoc();
StringRef Identifier = Tok.getString();
UpdateLocLex = false;
if (TK != AsmToken::String && !ParseRegister(TmpReg, IdentLoc, End)) {
SM.onRegister(TmpReg);
UpdateLocLex = false;
break;
} else {
if (!isParsingInlineAsm()) {
if (getParser().parsePrimaryExpr(Val, End))
return Error(Tok.getLoc(), "Unexpected identifier!");
} else {
// This is a dot operator, not an adjacent identifier.
if (Identifier.find('.') != StringRef::npos &&
PrevTK == AsmToken::RBrac) {
return false;
} else {
InlineAsmIdentifierInfo &Info = SM.getIdentifierInfo();
if (ParseIntelIdentifier(Val, Identifier, Info,
/*Unevaluated=*/false, End))
return true;
}
}
} else if (!isParsingInlineAsm()) {
if (getParser().parsePrimaryExpr(Val, End))
return Error(Tok.getLoc(), "Unexpected identifier!");
SM.onIdentifierExpr(Val, Identifier);
} else if (unsigned OpKind = IdentifyIntelOperator(Identifier)) {
if (OpKind == IOK_OFFSET)
return Error(IdentLoc, "Dealing OFFSET operator as part of"
"a compound immediate expression is yet to be supported");
int64_t Val = ParseIntelOperator(OpKind);
if (!Val)
return true;
StringRef ErrMsg;
if (SM.onInteger(Val, ErrMsg))
return Error(IdentLoc, ErrMsg);
} else if (Identifier.find('.') != StringRef::npos &&
PrevTK == AsmToken::RBrac) {
return false;
} else {
InlineAsmIdentifierInfo &Info = SM.getIdentifierInfo();
if (ParseIntelIdentifier(Val, Identifier, Info,
/*Unevaluated=*/false, End))
return true;
SM.onIdentifierExpr(Val, Identifier);
UpdateLocLex = false;
break;
}
return Error(Tok.getLoc(), "Unexpected identifier!");
break;
}
case AsmToken::Integer: {
StringRef ErrMsg;
@ -1715,11 +1730,16 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOffsetOfOperator() {
OffsetOfLoc, Identifier, Info.OpDecl);
}
enum IntelOperatorKind {
IOK_LENGTH,
IOK_SIZE,
IOK_TYPE
};
// Query a candidate string for being an Intel assembly operator
// Report back its kind, or IOK_INVALID if does not evaluated as a known one
unsigned X86AsmParser::IdentifyIntelOperator(StringRef Name) {
return StringSwitch<unsigned>(Name)
.Cases("TYPE","type",IOK_TYPE)
.Cases("SIZE","size",IOK_SIZE)
.Cases("LENGTH","length",IOK_LENGTH)
.Cases("OFFSET","offset",IOK_OFFSET)
.Default(IOK_INVALID);
}
/// Parse the 'LENGTH', 'TYPE' and 'SIZE' operators. The LENGTH operator
/// returns the number of elements in an array. It returns the value 1 for
@ -1727,7 +1747,7 @@ enum IntelOperatorKind {
/// variable. A variable's size is the product of its LENGTH and TYPE. The
/// TYPE operator returns the size of a C or C++ type or variable. If the
/// variable is an array, TYPE returns the size of a single element.
std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperator(unsigned OpKind) {
unsigned X86AsmParser::ParseIntelOperator(unsigned OpKind) {
MCAsmParser &Parser = getParser();
const AsmToken &Tok = Parser.getTok();
SMLoc TypeLoc = Tok.getLoc();
@ -1739,11 +1759,13 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperator(unsigned OpKind) {
StringRef Identifier = Tok.getString();
if (ParseIntelIdentifier(Val, Identifier, Info,
/*Unevaluated=*/true, End))
return nullptr;
if (!Info.OpDecl)
return ErrorOperand(Start, "unable to lookup expression");
return 0;
if (!Info.OpDecl) {
Error(Start, "unable to lookup expression");
return 0;
}
unsigned CVal = 0;
switch(OpKind) {
default: llvm_unreachable("Unexpected operand kind!");
@ -1757,8 +1779,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperator(unsigned OpKind) {
unsigned Len = End.getPointer() - TypeLoc.getPointer();
InstInfo->AsmRewrites->emplace_back(AOK_Imm, TypeLoc, Len, CVal);
const MCExpr *Imm = MCConstantExpr::create(CVal, getContext());
return X86Operand::CreateImm(Imm, Start, End);
return CVal;
}
std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() {
@ -1766,18 +1787,12 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() {
const AsmToken &Tok = Parser.getTok();
SMLoc Start, End;
// Offset, length, type and size operators.
if (isParsingInlineAsm()) {
StringRef AsmTokStr = Tok.getString();
if (AsmTokStr == "offset" || AsmTokStr == "OFFSET")
// FIXME: Offset operator
// Should be handled as part of immediate expression, as other operators
// Currently, only supported as a stand-alone operand
if (isParsingInlineAsm())
if (IdentifyIntelOperator(Tok.getString()) == IOK_OFFSET)
return ParseIntelOffsetOfOperator();
if (AsmTokStr == "length" || AsmTokStr == "LENGTH")
return ParseIntelOperator(IOK_LENGTH);
if (AsmTokStr == "size" || AsmTokStr == "SIZE")
return ParseIntelOperator(IOK_SIZE);
if (AsmTokStr == "type" || AsmTokStr == "TYPE")
return ParseIntelOperator(IOK_TYPE);
}
bool PtrInOperand = false;
unsigned Size = getIntelMemOperandSize(Tok.getString());