virtual bool evaluateAsRelocatableImpl(MCValue &Res,
const MCAsmLayout *Layout,
const MCFixup *Fixup) const = 0;
+ // allow Target Expressions to be checked for equality
+ virtual bool isEqualTo(const MCExpr *x) const { return false; }
// This should be set when assigned expressions are not valid ".set"
// expressions, e.g. registers, and must be inlined.
virtual bool inlineAssignedExpr() const { return false; }
/// On success, returns false and sets the Symbol and Value output parameters.
bool parseAssignmentExpression(StringRef Name, bool allow_redef,
MCAsmParser &Parser, MCSymbol *&Symbol,
- const MCExpr *&Value, bool AllowExtendedExpr = false);
+ const MCExpr *&Value);
} // namespace MCParserUtils
SemaCallback = Callback;
}
- // Target-specific parsing of assembler-level variable assignment.
- virtual bool parseAssignmentExpression(const MCExpr *&Res, SMLoc &EndLoc) {
- return getParser().parseExpression(Res, EndLoc);
+ // Target-specific parsing of expression.
+ virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+ return getParser().parsePrimaryExpr(Res, EndLoc);
}
virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
if (!ABE->getLHS()->evaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup,
Addrs, InSet) ||
!ABE->getRHS()->evaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup,
- Addrs, InSet))
+ Addrs, InSet)) {
+ // Check if both are Target Expressions, see if we can compare them.
+ if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(ABE->getLHS()))
+ if (const MCTargetExpr *R = cast<MCTargetExpr>(ABE->getRHS())) {
+ switch (ABE->getOpcode()) {
+ case MCBinaryExpr::EQ:
+ Res = MCValue::get((L->isEqualTo(R)) ? -1 : 0);
+ return true;
+ case MCBinaryExpr::NE:
+ Res = MCValue::get((R->isEqualTo(R)) ? 0 : -1);
+ return true;
+ default: {}
+ }
+ }
return false;
+ }
// We only support a few operations on non-constant expressions, handle
// those first.
StringRef parseStringToComma();
bool parseAssignment(StringRef Name, bool allow_redef,
- bool NoDeadStrip = false, bool AllowExtendedExpr = false);
+ bool NoDeadStrip = false);
unsigned getBinOpPrecedence(AsmToken::TokenKind K,
MCBinaryExpr::Opcode &Kind);
bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
// Parse the expression.
Res = nullptr;
- if (parsePrimaryExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc))
+ if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
+ parseBinOpRHS(1, Res, EndLoc))
return true;
// As a special case, we support 'a op b @ modifier' by rewriting the
// Eat the next primary expression.
const MCExpr *RHS;
- if (parsePrimaryExpr(RHS, EndLoc))
+ if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
return true;
// If BinOp binds less tightly with RHS than the operator after RHS, let
// identifier '=' ... -> assignment statement
Lex();
- return parseAssignment(IDVal, true, /*NoDeadStrip*/ false, /*AllowExtendedExpr*/true);
+ return parseAssignment(IDVal, true);
default: // Normal instruction or directive.
break;
}
bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
- bool NoDeadStrip, bool AllowExtendedExpr) {
+ bool NoDeadStrip) {
MCSymbol *Sym;
const MCExpr *Value;
if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym,
- Value, AllowExtendedExpr))
+ Value))
return true;
if (!Sym) {
bool parseAssignmentExpression(StringRef Name, bool allow_redef,
MCAsmParser &Parser, MCSymbol *&Sym,
- const MCExpr *&Value, bool AllowExtendedExpr) {
+ const MCExpr *&Value) {
// FIXME: Use better location, we should use proper tokens.
SMLoc EqualLoc = Parser.getTok().getLoc();
SMLoc EndLoc;
- if (AllowExtendedExpr) {
- if (Parser.getTargetParser().parseAssignmentExpression(Value, EndLoc)) {
- return Parser.TokError("missing expression");
- }
- } else if (Parser.parseExpression(Value, EndLoc))
- return Parser.TokError("missing expression");
+ if (Parser.parseExpression(Value))
+ return Parser.TokError("missing expression");
// Note: we don't count b as used in "a = b". This is to allow
// a = b
void SetFrameRegister(unsigned RegNo) override;
- bool parseAssignmentExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
+ bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) override;
return X86Operand::CreateMem(getPointerWidth(), Disp, MemStart, MemEnd);
}
-// Parse either a standard expression or a register.
-bool X86AsmParser::parseAssignmentExpression(const MCExpr *&Res,
- SMLoc &EndLoc) {
+// Parse either a standard primary expression or a register.
+bool X86AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
MCAsmParser &Parser = getParser();
- if (Parser.parseExpression(Res, EndLoc)) {
+ if (Parser.parsePrimaryExpr(Res, EndLoc)) {
SMLoc StartLoc = Parser.getTok().getLoc();
// Normal Expression parse fails, check if it could be a register.
unsigned RegNo;
- if (Parser.getTargetParser().ParseRegister(RegNo, StartLoc, EndLoc))
+ bool TryRegParse =
+ getTok().is(AsmToken::Percent) ||
+ (isParsingIntelSyntax() && getTok().is(AsmToken::Identifier));
+ if (!TryRegParse || ParseRegister(RegNo, StartLoc, EndLoc))
return true;
// Clear previous parse error and return correct expression.
Parser.clearPendingErrors();
/// @}
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override {
- if (MAI->getAssemblerDialect() == 0)
+ if (!MAI || MAI->getAssemblerDialect() == 0)
OS << '%';
OS << X86ATTInstPrinter::getRegisterName(RegNo);
}
}
// Register values should be inlined as they are not valid .set expressions.
bool inlineAssignedExpr() const override { return true; }
+ bool isEqualTo(const MCExpr *X) const override {
+ if (auto *E = dyn_cast<X86MCExpr>(X))
+ return getRegNo() == E->getRegNo();
+ return false;
+ }
void visitUsedExpr(MCStreamer &Streamer) const override{};
MCFragment *findAssociatedFragment() const override { return nullptr; }
-// RUN: llvm-mc -triple x86_64-unknown-unknown -defsym=ERR=0 %s -o - | FileCheck %s
-// RUN: not llvm-mc -triple x86_64-unknown-unknown -defsym=ERR=1 %s -o - 2>&1 | FileCheck --check-prefix=ERR %s
+// RUN: llvm-mc -triple x86_64-unknown-unknown %s -o - | FileCheck %s
// CHECK-NOT: .set var_xdata
var_xdata = %rcx
// CHECK: xorq %rcx, %rcx
xorq var_xdata, var_xdata
-.if (ERR==1)
-// ERR: [[@LINE+2]]:15: error: unknown token in expression in '.set' directive
-// ERR: [[@LINE+1]]:15: error: missing expression in '.set' directive
-.set err_var, %rcx
-.endif
+// CHECK: .data
+// CHECK-NEXT: .byte 1
+.data
+.if var_xdata == %rax
+ .byte 0
+.elseif var_xdata == %rcx
+ .byte 1
+.else
+ .byte 2
+.endif