Skip to content

Commit

Permalink
This patch enables the usage of constant Enum identifiers within Micr…
Browse files Browse the repository at this point in the history
…osoft style inline assembly statements.

Differential Revision:
https://reviews.llvm.org/D33277
https://reviews.llvm.org/D33278

llvm-svn: 308966
  • Loading branch information
Matan Haroush committed Jul 25, 2017
1 parent b4b8d10 commit 2f21017
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 24 deletions.
19 changes: 16 additions & 3 deletions llvm/include/llvm/MC/MCParser/MCAsmParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,30 @@ class MCTargetAsmParser;
class SourceMgr;

class InlineAsmIdentifierInfo {
private:
enum IdDeclKind : uint8_t {
Default,
Variable,
ConstEnum,
};
IdDeclKind Kind;

public:
void *OpDecl;
bool IsVarDecl;
unsigned Length, Size, Type;

APInt ConstIntValue;
bool isVarDecl() { return Kind == Variable; }
bool isConstEnum() { return Kind == ConstEnum; }
void setKindVariable() { Kind = Variable; }
void setKindConstEnum() { Kind = ConstEnum; }
void clear() {
OpDecl = nullptr;
IsVarDecl = false;
Kind = Default;
Length = 1;
Size = 0;
Type = 0;
// On clear flush possibly old APInt value as a precaution;
ConstIntValue = APInt();
}
};

Expand Down
76 changes: 55 additions & 21 deletions llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,7 @@ class X86AsmParser : public MCTargetAsmParser {
std::unique_ptr<X86Operand> ParseIntelOffsetOfOperator();
bool ParseIntelDotOperator(const MCExpr *Disp, const MCExpr *&NewDisp);
unsigned IdentifyIntelOperator(StringRef Name);
unsigned ParseIntelOperator(unsigned OpKind);
unsigned ParseIntelOperator(unsigned OpKind, bool AddImmPrefix);
std::unique_ptr<X86Operand>
ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, unsigned Size);
std::unique_ptr<X86Operand> ParseRoundingModeOp(SMLoc Start, SMLoc End);
Expand Down Expand Up @@ -1223,7 +1223,7 @@ std::unique_ptr<X86Operand> X86AsmParser::CreateMemForInlineAsm(
InlineAsmIdentifierInfo &Info, bool AllowBetterSizeMatch) {
// If we found a decl other than a VarDecl, then assume it is a FuncDecl or
// some other label reference.
if (isa<MCSymbolRefExpr>(Disp) && Info.OpDecl && !Info.IsVarDecl) {
if (isa<MCSymbolRefExpr>(Disp) && Info.OpDecl && !Info.isVarDecl()) {
// Insert an explicit size if the user didn't have one.
if (!Size) {
Size = getPointerWidth();
Expand Down Expand Up @@ -1397,7 +1397,7 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
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);
int64_t Val = ParseIntelOperator(OpKind,SM.getAddImmPrefix());
if (!Val)
return true;
StringRef ErrMsg;
Expand All @@ -1407,11 +1407,38 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
PrevTK == AsmToken::RBrac) {
return false;
} else {
InlineAsmIdentifierInfo &Info = SM.getIdentifierInfo();
if (ParseIntelIdentifier(Val, Identifier, Info,
InlineAsmIdentifierInfo Info;
if (ParseIntelIdentifier(Val, Identifier, Info,
/*Unevaluated=*/false, End))
return true;
SM.onIdentifierExpr(Val, Identifier);
return true;
// Check if the parsed identifier was a constant Integer. Here we
// assume Val is of type MCConstantExpr only when it is safe to replace
// the identifier with its constant value.
if (const MCConstantExpr *CE =
dyn_cast_or_null<const MCConstantExpr>(Val)) {
StringRef ErrMsg;
// Pass the enum identifier integer value to the SM calculator.
if (SM.onInteger(CE->getValue(), ErrMsg))
return Error(IdentLoc, ErrMsg);
// Match the behavior of integer tokens when getAddImmPrefix flag is
// set.
if (SM.getAddImmPrefix()) {
assert(isParsingInlineAsm() &&
"Expected to be parsing inline assembly.");
// A single rewrite of the integer value is preformed for each enum
// identifier. This is only done when we are inside a bracketed
// expression.
size_t Len = End.getPointer() - IdentLoc.getPointer();
InstInfo->AsmRewrites->emplace_back(AOK_Imm, IdentLoc, Len,
CE->getValue());
break;
}
} else {
// Notify the SM a variable identifier was found.
InlineAsmIdentifierInfo &SMInfo = SM.getIdentifierInfo();
SMInfo = Info;
SM.onIdentifierExpr(Val, Identifier);
}
}
break;
}
Expand Down Expand Up @@ -1599,6 +1626,14 @@ bool X86AsmParser::ParseIntelIdentifier(const MCExpr *&Val,
assert((End.getPointer() == EndPtr || !Result) &&
"frontend claimed part of a token?");

// Check if the search yielded a constant integer (enum identifier).
if (Result && Info.isConstEnum()) {
// By creating MCConstantExpr we let the user of Val know it is safe
// to use as an explicit constant with value = ConstVal.
Val = MCConstantExpr::create(Info.ConstIntValue.getSExtValue(),
getParser().getContext());
return false;
}
// If the identifier lookup was unsuccessful, assume that we are dealing with
// a label.
if (!Result) {
Expand Down Expand Up @@ -1796,7 +1831,7 @@ unsigned X86AsmParser::IdentifyIntelOperator(StringRef Name) {
/// 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.
unsigned X86AsmParser::ParseIntelOperator(unsigned OpKind) {
unsigned X86AsmParser::ParseIntelOperator(unsigned OpKind, bool AddImmPrefix) {
MCAsmParser &Parser = getParser();
const AsmToken &Tok = Parser.getTok();
SMLoc TypeLoc = Tok.getLoc();
Expand All @@ -1822,12 +1857,17 @@ unsigned X86AsmParser::ParseIntelOperator(unsigned OpKind) {
case IOK_SIZE: CVal = Info.Size; break;
case IOK_TYPE: CVal = Info.Type; break;
}

// Rewrite the type operator and the C or C++ type or variable in terms of an
// immediate. E.g. TYPE foo -> $$4
unsigned Len = End.getPointer() - TypeLoc.getPointer();
InstInfo->AsmRewrites->emplace_back(AOK_Imm, TypeLoc, Len, CVal);


// Only when in bracketed mode, preform explicit rewrite. This is requierd to
// avoid rewrite collision.
if (AddImmPrefix) {
// Rewrite the type operator and the C or C++ type or variable in terms of
// an immediate. e.g. mov eax, [eax + SIZE _foo * $$4] ->
// mov eax, [eax + $$1 * $$4].
unsigned Len = End.getPointer() - TypeLoc.getPointer();
InstInfo->AsmRewrites->emplace_back(AOK_Imm, TypeLoc, Len, CVal);
}

return CVal;
}

Expand Down Expand Up @@ -1898,14 +1938,8 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() {
if (SM.getSym() && SM.getSym()->getKind() == MCExpr::Constant)
SM.getSym()->evaluateAsAbsolute(Imm);

if (StartTok.isNot(AsmToken::Identifier) &&
StartTok.isNot(AsmToken::String) && isParsingInlineAsm()) {
if (isParsingInlineAsm() && !isSymbol) {
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->emplace_back(AOK_ImmPrefix, Start);
else
// Otherwise, rewrite the complex expression as a single immediate.
InstInfo->AsmRewrites->emplace_back(AOK_Imm, Start, Len, Imm);
}

Expand Down

0 comments on commit 2f21017

Please sign in to comment.