Index: include/llvm/MC/MCParser/MCAsmParser.h =================================================================== --- include/llvm/MC/MCParser/MCAsmParser.h +++ include/llvm/MC/MCParser/MCAsmParser.h @@ -61,6 +61,7 @@ SMLoc Location, bool Create) = 0; virtual bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset) = 0; + virtual bool EvaluateLookupAsEnum(void *LookupResult,int64_t &Result) = 0; }; /// \brief Generic assembler parser interface, for use by target specific Index: lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmParser.cpp +++ lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -718,7 +718,8 @@ ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, unsigned Size); std::unique_ptr ParseRoundingModeOp(SMLoc Start, SMLoc End); bool ParseIntelNamedOperator(StringRef Name, IntelExprStateMachine &SM); - bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End); + bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End, + bool &ReplaceEnumIdentifier); std::unique_ptr ParseIntelBracExpression(unsigned SegReg, SMLoc Start, int64_t ImmDisp, bool isSymbol, unsigned Size); @@ -1306,8 +1307,9 @@ return false; return true; } - -bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) { +bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End, + bool &ReplaceEnumIdentifier) { + ReplaceEnumIdentifier = false; MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); @@ -1368,11 +1370,40 @@ PrevTK == AsmToken::RBrac) { return false; } else { - InlineAsmIdentifierInfo &Info = SM.getIdentifierInfo(); + InlineAsmIdentifierInfo Info; + Info.clear(); if (ParseIntelIdentifier(Val, Identifier, Info, /*Unevaluated=*/false, End)) return true; - SM.onIdentifierExpr(Val, Identifier); + // 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(Val)) { + StringRef ErrMsg; + // SM should treat the value as it would an explicit integer in the + // expression. + if(SM.onInteger(CE->getValue(), ErrMsg)) + return Error(IdentLoc, ErrMsg); + // In case we are called on a bracketed expression, + if (isParsingInlineAsm() && SM.getAddImmPrefix()) { + // A single rewrite of the integer value is preformed for each enum + // identifier. This is only done when we are inside a bracketed + // expression in order to match the behavior for the equivalent + // integer tokens. + size_t Len = End.getPointer() - IdentLoc.getPointer(); + InstInfo->AsmRewrites->emplace_back(AOK_Imm, IdentLoc,Len, + CE->getValue()); + break; + } + // Set force rewrite flag only when not bracketed expression. + ReplaceEnumIdentifier = true; + } else { + // Notify the SM a variable identifier was found. + InlineAsmIdentifierInfo &SMInfo = SM.getIdentifierInfo(); + SMInfo = Info; + SM.onIdentifierExpr(Val, Identifier); + } } break; } @@ -1452,7 +1483,8 @@ // may have already parsed an immediate displacement before the bracketed // expression. IntelExprStateMachine SM(ImmDisp, /*StopOnLBrac=*/false, /*AddImmPrefix=*/true); - if (ParseIntelExpression(SM, End)) + bool ReplaceEnumIdentifier; + if (ParseIntelExpression(SM, End, ReplaceEnumIdentifier)) return nullptr; const MCExpr *Disp = nullptr; @@ -1559,7 +1591,15 @@ // failed parsing. assert((End.getPointer() == EndPtr || !Result) && "frontend claimed part of a token?"); - + + // Try to evaluate the result as a constant integer (enum identifier). + int64_t ConstVal = 0; + if (SemaCallback->EvaluateLookupAsEnum(Result, ConstVal)) { + // 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(ConstVal, getParser().getContext()); + return false; + } // If the identifier lookup was unsuccessful, assume that we are dealing with // a label. if (!Result) { @@ -1852,18 +1892,21 @@ AsmToken StartTok = Tok; IntelExprStateMachine SM(/*Imm=*/0, /*StopOnLBrac=*/true, /*AddImmPrefix=*/false); - if (ParseIntelExpression(SM, End)) + // The parsed expression may contain enum identifier tokens which we must + // replace, ReplaceEnumIdentifier flag lets us know when to force rewrite. + bool ReplaceEnumIdentifier; + if (ParseIntelExpression(SM, End, ReplaceEnumIdentifier)) return nullptr; - bool isSymbol = SM.getSym() && SM.getSym()->getKind() != MCExpr::Constant; int64_t Imm = SM.getImm(); if (SM.getSym() && SM.getSym()->getKind() == MCExpr::Constant) SM.getSym()->evaluateAsAbsolute(Imm); - if (StartTok.isNot(AsmToken::Identifier) && + if ((ReplaceEnumIdentifier || + StartTok.isNot(AsmToken::Identifier)) && StartTok.isNot(AsmToken::String) && isParsingInlineAsm()) { unsigned Len = Tok.getLoc().getPointer() - Start.getPointer(); - if (StartTok.getString().size() == Len) + if (StartTok.getString().size() == Len && !ReplaceEnumIdentifier) // Just add a prefix if this wasn't a complex immediate expression. InstInfo->AsmRewrites->emplace_back(AOK_ImmPrefix, Start); else