diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-10-22 23:58:19 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-10-22 23:58:19 +0000 |
commit | 2128aaebd850edc0415ab8f37b907077651d4399 (patch) | |
tree | c456e15411ebf3db171ac62abdfa684d9a109fdd /lib/MC/MCParser/AsmParser.cpp | |
parent | 8f47fc8f00fbb1cc2215fc90942b0948e3ca121b (diff) | |
download | external_llvm-2128aaebd850edc0415ab8f37b907077651d4399.zip external_llvm-2128aaebd850edc0415ab8f37b907077651d4399.tar.gz external_llvm-2128aaebd850edc0415ab8f37b907077651d4399.tar.bz2 |
[ms-inline-asm] Implement _emit directive (which is roughly equivalent to .byte).
<rdar://problem/12470345>.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166451 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC/MCParser/AsmParser.cpp')
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 112 |
1 files changed, 68 insertions, 44 deletions
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 2f63fd4..9d3d4e3 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -86,6 +86,28 @@ public: MemoryBuffer *I); }; +struct AsmRewrite; +struct ParseStatementInfo { + /// ParsedOperands - The parsed operands from the last parsed statement. + SmallVector<MCParsedAsmOperand*, 8> ParsedOperands; + + /// Opcode - The opcode from the last parsed instruction. + unsigned Opcode; + + SmallVectorImpl<AsmRewrite> *AsmRewrites; + + ParseStatementInfo() : Opcode(~0U), AsmRewrites(0) {} + ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites) + : Opcode(~0), AsmRewrites(rewrites) {} + + ~ParseStatementInfo() { + // Free any parsed operands. + for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i) + delete ParsedOperands[i]; + ParsedOperands.clear(); + } +}; + /// \brief The concrete assembly parser instance. class AsmParser : public MCAsmParser { friend class GenericAsmParser; @@ -142,13 +164,6 @@ private: /// ParsingInlineAsm - Are we parsing ms-style inline assembly? bool ParsingInlineAsm; - /// ParsedOperands - The parsed operands from the last parsed statement. - SmallVector<MCParsedAsmOperand*, 8> ParsedOperands; - - /// Opcode - The opcode from the last parsed instruction. This is MS-style - /// inline asm specific. - unsigned Opcode; - public: AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, const MCAsmInfo &MAI); @@ -209,7 +224,7 @@ public: private: void CheckForValidSection(); - bool ParseStatement(); + bool ParseStatement(ParseStatementInfo &Info); void EatToEndOfLine(); bool ParseCppHashLineFilenameComment(const SMLoc &L); @@ -316,10 +331,8 @@ private: bool ParseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc" bool ParseDirectiveEndr(SMLoc DirectiveLoc); // ".endr" - // MS-style inline assembly parsing. - bool isInstruction() { return Opcode != (unsigned)~0x0; } - unsigned getOpcode() { return Opcode; } - void setOpcode(unsigned Value) { Opcode = Value; } + // "_emit" + bool ParseDirectiveEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info); }; /// \brief Generic implementations of directive handling, etc. which is shared @@ -445,8 +458,7 @@ AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM), GenericParser(new GenericAsmParser), PlatformParser(0), CurBuffer(0), MacrosEnabled(true), CppHashLineNumber(0), - AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false), - Opcode(~0x0) { + AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false) { // Save the old handler. SavedDiagHandler = SrcMgr.getDiagHandler(); SavedDiagContext = SrcMgr.getDiagContext(); @@ -585,7 +597,8 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // While we have input, parse each statement. while (Lexer.isNot(AsmToken::Eof)) { - if (!ParseStatement()) continue; + ParseStatementInfo Info; + if (!ParseStatement(Info)) continue; // We had an error, validate that one was emitted and recover by skipping to // the next line. @@ -1068,7 +1081,7 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, /// ::= EndOfStatement /// ::= Label* Directive ...Operands... EndOfStatement /// ::= Label* Identifier OperandList* EndOfStatement -bool AsmParser::ParseStatement() { +bool AsmParser::ParseStatement(ParseStatementInfo &Info) { if (Lexer.is(AsmToken::EndOfStatement)) { Out.AddBlankLine(); Lex(); @@ -1187,7 +1200,7 @@ bool AsmParser::ParseStatement() { return false; } - return ParseStatement(); + return false; } case AsmToken::Equal: @@ -1341,6 +1354,10 @@ bool AsmParser::ParseStatement() { return Error(IDLoc, "unknown directive"); } + // _emit + if (ParsingInlineAsm && IDVal == "_emit") + return ParseDirectiveEmit(IDLoc, Info); + CheckForValidSection(); // Canonicalize the opcode to lower case. @@ -1349,17 +1366,17 @@ bool AsmParser::ParseStatement() { OpcodeStr.push_back(tolower(IDVal[i])); bool HadError = getTargetParser().ParseInstruction(OpcodeStr.str(), IDLoc, - ParsedOperands); + Info.ParsedOperands); // Dump the parsed representation, if requested. if (getShowParsedOperands()) { SmallString<256> Str; raw_svector_ostream OS(Str); OS << "parsed instruction: ["; - for (unsigned i = 0; i != ParsedOperands.size(); ++i) { + for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) { if (i != 0) OS << ", "; - ParsedOperands[i]->print(OS); + Info.ParsedOperands[i]->print(OS); } OS << "]"; @@ -1381,20 +1398,12 @@ bool AsmParser::ParseStatement() { // If parsing succeeded, match the instruction. if (!HadError) { unsigned ErrorInfo; - HadError = getTargetParser().MatchAndEmitInstruction(IDLoc, Opcode, - ParsedOperands, Out, - ErrorInfo, + HadError = getTargetParser().MatchAndEmitInstruction(IDLoc, Info.Opcode, + Info.ParsedOperands, + Out, ErrorInfo, ParsingInlineAsm); } - // Free any parsed operands. If parsing ms-style inline assembly the operands - // will be freed by the ParseMSInlineAsm() function. - if (!ParsingInlineAsm) { - for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i) - delete ParsedOperands[i]; - ParsedOperands.clear(); - } - // Don't skip the rest of the line, the instruction parser is responsible for // that. return false; @@ -3579,7 +3588,8 @@ enum AsmRewriteKind { AOK_Imm, AOK_Input, AOK_Output, - AOK_SizeDirective + AOK_SizeDirective, + AOK_Emit }; struct AsmRewrite { @@ -3593,6 +3603,22 @@ public: }; } +bool AsmParser::ParseDirectiveEmit(SMLoc IDLoc, ParseStatementInfo &Info) { + const MCExpr *Value; + SMLoc ExprLoc = getLexer().getLoc(); + if (ParseExpression(Value)) + return true; + const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); + if (!MCE) + return Error(ExprLoc, "unexpected expression in _emit"); + uint64_t IntValue = MCE->getValue(); + if (!isUIntN(8, IntValue) && !isIntN(8, IntValue)) + return Error(ExprLoc, "literal value out of range for directive"); + + Info.AsmRewrites->push_back(AsmRewrite(AOK_Emit, IDLoc, 5)); + return false; +} + bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, SmallVectorImpl<void *> &OpDecls, @@ -3616,18 +3642,16 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned InputIdx = 0; unsigned OutputIdx = 0; while (getLexer().isNot(AsmToken::Eof)) { - // Clear the opcode. - setOpcode(~0x0); - - if (ParseStatement()) + ParseStatementInfo Info(&AsmStrRewrites); + if (ParseStatement(Info)) return true; - if (isInstruction()) { - const MCInstrDesc &Desc = MII->get(getOpcode()); + if (Info.Opcode != ~0U) { + const MCInstrDesc &Desc = MII->get(Info.Opcode); // Build the list of clobbers, outputs and inputs. - for (unsigned i = 1, e = ParsedOperands.size(); i != e; ++i) { - MCParsedAsmOperand *Operand = ParsedOperands[i]; + for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) { + MCParsedAsmOperand *Operand = Info.ParsedOperands[i]; // Immediate. if (Operand->isImm()) { @@ -3679,10 +3703,6 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, } } } - // Free any parsed operands. - for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i) - delete ParsedOperands[i]; - ParsedOperands.clear(); } } @@ -3751,6 +3771,10 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, case 128: OS << "xmmword ptr "; break; case 256: OS << "ymmword ptr "; break; } + break; + case AOK_Emit: + OS << ".byte"; + break; } // Skip the original expression. |