Skip to content

Commit

Permalink
[X86AsmParser] Refactoring, (almost) NFC.
Browse files Browse the repository at this point in the history
Some refactoring to X86AsmParser, mostly regarding the way rewrites are conducted.
Mainly, we try to concentrate all the rewrite effort under one hood, so it'll hopefully be less of a mess and easier to maintain and understand.
naturally, some frontend tests were affected: D36794

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

llvm-svn: 311639
  • Loading branch information
Coby Tayree committed Aug 24, 2017
1 parent d664315 commit d891289
Show file tree
Hide file tree
Showing 6 changed files with 316 additions and 480 deletions.
64 changes: 53 additions & 11 deletions llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
Expand Up @@ -30,36 +30,75 @@ template <typename T> class SmallVectorImpl;
using OperandVector = SmallVectorImpl<std::unique_ptr<MCParsedAsmOperand>>;

enum AsmRewriteKind {
AOK_Delete = 0, // Rewrite should be ignored.
AOK_Align, // Rewrite align as .align.
AOK_EVEN, // Rewrite even as .even.
AOK_DotOperator, // Rewrite a dot operator expression as an immediate.
// E.g., [eax].foo.bar -> [eax].8
AOK_Emit, // Rewrite _emit as .byte.
AOK_Imm, // Rewrite as $$N.
AOK_ImmPrefix, // Add $$ before a parsed Imm.
AOK_Input, // Rewrite in terms of $N.
AOK_Output, // Rewrite in terms of $N.
AOK_SizeDirective, // Add a sizing directive (e.g., dword ptr).
AOK_Label, // Rewrite local labels.
AOK_EndOfStatement, // Add EndOfStatement (e.g., "\n\t").
AOK_Skip // Skip emission (e.g., offset/type operators).
AOK_Skip, // Skip emission (e.g., offset/type operators).
AOK_IntelExpr // SizeDirective SymDisp [BaseReg + IndexReg * Scale + ImmDisp]
};

const char AsmRewritePrecedence [] = {
0, // AOK_Delete
2, // AOK_Align
2, // AOK_EVEN
2, // AOK_DotOperator
2, // AOK_Emit
4, // AOK_Imm
4, // AOK_ImmPrefix
3, // AOK_Input
3, // AOK_Output
5, // AOK_SizeDirective
1, // AOK_Label
5, // AOK_EndOfStatement
2 // AOK_Skip
2, // AOK_Skip
2 // AOK_IntelExpr
};

// Represnt the various parts which makes up an intel expression,
// used for emitting compound intel expressions
struct IntelExpr {
bool NeedBracs;
int64_t Imm;
StringRef BaseReg;
StringRef IndexReg;
unsigned Scale;

IntelExpr(bool needBracs = false) : NeedBracs(needBracs), Imm(0),
BaseReg(StringRef()), IndexReg(StringRef()),
Scale(1) {}
// Compund immediate expression
IntelExpr(int64_t imm, bool needBracs) : IntelExpr(needBracs) {
Imm = imm;
}
// [Reg + ImmediateExpression]
// We don't bother to emit an immediate expression evaluated to zero
IntelExpr(StringRef reg, int64_t imm = 0, unsigned scale = 0,
bool needBracs = true) :
IntelExpr(imm, needBracs) {
IndexReg = reg;
if (scale)
Scale = scale;
}
// [BaseReg + IndexReg * ScaleExpression + ImmediateExpression]
IntelExpr(StringRef baseReg, StringRef indexReg, unsigned scale = 0,
int64_t imm = 0, bool needBracs = true) :
IntelExpr(indexReg, imm, scale, needBracs) {
BaseReg = baseReg;
}
bool hasBaseReg() const {
return BaseReg.size();
}
bool hasIndexReg() const {
return IndexReg.size();
}
bool hasRegs() const {
return hasBaseReg() || hasIndexReg();
}
bool isValid() const {
return (Scale == 1) ||
(hasIndexReg() && (Scale == 2 || Scale == 4 || Scale == 8));
}
};

struct AsmRewrite {
Expand All @@ -68,12 +107,15 @@ struct AsmRewrite {
unsigned Len;
int64_t Val;
StringRef Label;
IntelExpr IntelExp;

public:
AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len = 0, int64_t val = 0)
: Kind(kind), Loc(loc), Len(len), Val(val) {}
AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len, StringRef label)
: Kind(kind), Loc(loc), Len(len), Val(0), Label(label) {}
AsmRewrite(SMLoc loc, unsigned len, IntelExpr exp)
: Kind(AOK_IntelExpr), Loc(loc), Len(len), IntelExp(exp) {}
};

struct ParseInstructionInfo {
Expand Down
29 changes: 15 additions & 14 deletions llvm/lib/MC/MCParser/AsmParser.cpp
Expand Up @@ -5573,8 +5573,6 @@ bool AsmParser::parseMSInlineAsm(
array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
for (const AsmRewrite &AR : AsmStrRewrites) {
AsmRewriteKind Kind = AR.Kind;
if (Kind == AOK_Delete)
continue;

const char *Loc = AR.Loc.getPointer();
assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
Expand All @@ -5594,11 +5592,21 @@ bool AsmParser::parseMSInlineAsm(
switch (Kind) {
default:
break;
case AOK_Imm:
OS << "$$" << AR.Val;
break;
case AOK_ImmPrefix:
OS << "$$";
case AOK_IntelExpr:
assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
if (AR.IntelExp.NeedBracs)
OS << "[";
if (AR.IntelExp.hasBaseReg())
OS << AR.IntelExp.BaseReg;
if (AR.IntelExp.hasIndexReg())
OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
<< AR.IntelExp.IndexReg;
if (AR.IntelExp.Scale > 1)
OS << " * $$" << AR.IntelExp.Scale;
if (AR.IntelExp.Imm || !AR.IntelExp.hasRegs())
OS << (AR.IntelExp.hasRegs() ? " + $$" : "$$") << AR.IntelExp.Imm;
if (AR.IntelExp.NeedBracs)
OS << "]";
break;
case AOK_Label:
OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
Expand Down Expand Up @@ -5642,13 +5650,6 @@ bool AsmParser::parseMSInlineAsm(
case AOK_EVEN:
OS << ".even";
break;
case AOK_DotOperator:
// Insert the dot if the user omitted it.
OS.flush();
if (AsmStringIR.back() != '.')
OS << '.';
OS << AR.Val;
break;
case AOK_EndOfStatement:
OS << "\n\t";
break;
Expand Down

0 comments on commit d891289

Please sign in to comment.