diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index c12caf01b03..4c7fa40a806 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -473,7 +473,7 @@ namespace llvm { virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); - virtual void EmitWin64EHStartProc(MCSymbol *Symbol); + virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); virtual void EmitWin64EHEndProc(); virtual void EmitWin64EHStartChained(); virtual void EmitWin64EHEndChained(); diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 9bd614acfc6..1df5c074746 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -208,7 +208,7 @@ public: virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); - virtual void EmitWin64EHStartProc(MCSymbol *Symbol); + virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); virtual void EmitWin64EHEndProc(); virtual void EmitWin64EHStartChained(); virtual void EmitWin64EHEndChained(); @@ -930,7 +930,7 @@ void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { EmitEOL(); } -void MCAsmStreamer::EmitWin64EHStartProc(MCSymbol *Symbol) { +void MCAsmStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) { MCStreamer::EmitWin64EHStartProc(Symbol); OS << ".seh_proc " << *Symbol; diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index 5ecab03b00f..0045950dcaa 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -14,6 +14,7 @@ #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCExpr.h" #include "llvm/Support/COFF.h" using namespace llvm; @@ -41,6 +42,34 @@ class COFFAsmParser : public MCAsmParserExtension { AddDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); AddDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); AddDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); + + // Win64 EH directives. + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>( + ".seh_proc"); + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>( + ".seh_endproc"); + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>( + ".seh_startchained"); + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>( + ".seh_endchained"); + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>( + ".seh_handler"); + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>( + ".seh_handlerdata"); + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>( + ".seh_pushreg"); + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>( + ".seh_setframe"); + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>( + ".seh_stackalloc"); + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>( + ".seh_savereg"); + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>( + ".seh_savexmm"); + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>( + ".seh_pushframe"); + AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>( + ".seh_endprologue"); } bool ParseSectionDirectiveText(StringRef, SMLoc) { @@ -70,6 +99,22 @@ class COFFAsmParser : public MCAsmParserExtension { bool ParseDirectiveType(StringRef, SMLoc); bool ParseDirectiveEndef(StringRef, SMLoc); + // Win64 EH directives. + bool ParseSEHDirectiveStartProc(StringRef, SMLoc); + bool ParseSEHDirectiveEndProc(StringRef, SMLoc); + bool ParseSEHDirectiveStartChained(StringRef, SMLoc); + bool ParseSEHDirectiveEndChained(StringRef, SMLoc); + bool ParseSEHDirectiveHandler(StringRef, SMLoc); + bool ParseSEHDirectiveHandlerData(StringRef, SMLoc); + bool ParseSEHDirectivePushReg(StringRef, SMLoc L); + bool ParseSEHDirectiveSetFrame(StringRef, SMLoc L); + bool ParseSEHDirectiveAllocStack(StringRef, SMLoc L); + bool ParseSEHDirectiveSaveReg(StringRef, SMLoc L); + bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc L); + bool ParseSEHDirectivePushFrame(StringRef, SMLoc L); + bool ParseSEHDirectiveEndProlog(StringRef, SMLoc); + + bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except); public: COFFAsmParser() {} }; @@ -135,6 +180,118 @@ bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { return false; } +bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) { + const MCExpr *e; + const MCSymbolRefExpr *funcExpr; + SMLoc startLoc = getLexer().getLoc(); + if (getParser().ParseExpression(e)) + return true; + + if (!(funcExpr = dyn_cast(e))) + return Error(startLoc, "expected symbol"); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + Lex(); + getStreamer().EmitWin64EHStartProc(&funcExpr->getSymbol()); + return false; +} + +bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) { + Lex(); + getStreamer().EmitWin64EHEndProc(); + return false; +} + +bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) { + Lex(); + getStreamer().EmitWin64EHStartChained(); + return false; +} + +bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) { + Lex(); + getStreamer().EmitWin64EHEndChained(); + return false; +} + +bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) { + const MCExpr *e; + const MCSymbolRefExpr *funcExpr; + SMLoc startLoc = getLexer().getLoc(); + if (getParser().ParseExpression(e)) + return true; + + if (!(funcExpr = dyn_cast(e))) + return Error(startLoc, "expected symbol"); + + bool unwind = false, except = false; + if (!ParseAtUnwindOrAtExcept(unwind, except)) + return true; + if (getLexer().is(AsmToken::Comma)) { + Lex(); + if (!ParseAtUnwindOrAtExcept(unwind, except)) + return true; + } + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + Lex(); + getStreamer().EmitWin64EHHandler(&funcExpr->getSymbol(), unwind, except); + return false; +} + +bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) { + Lex(); + getStreamer().EmitWin64EHHandlerData(); + return false; +} + +bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) { + return Error(L, "not implemented yet"); +} + +bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) { + return Error(L, "not implemented yet"); +} + +bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc L) { + return Error(L, "not implemented yet"); +} + +bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) { + return Error(L, "not implemented yet"); +} + +bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) { + return Error(L, "not implemented yet"); +} + +bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc L) { + return Error(L, "not implemented yet"); +} + +bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) { + Lex(); + getStreamer().EmitWin64EHEndProlog(); + return false; +} + +bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) { + StringRef identifier; + SMLoc startLoc = getLexer().getLoc(); + if (!getParser().ParseIdentifier(identifier)) + return Error(startLoc, "expected @unwind or @except"); + if (identifier == "@unwind") + unwind = true; + else if (identifier == "@except") + except = true; + else + return Error(startLoc, "expected @unwind or @except"); + return false; +} + namespace llvm { MCAsmParserExtension *createCOFFAsmParser() { diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index f268f9e3756..1402033d41d 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -316,7 +316,7 @@ void MCStreamer::EnsureValidW64UnwindInfo() { report_fatal_error("No open Win64 EH frame function!"); } -void MCStreamer::EmitWin64EHStartProc(MCSymbol *Symbol) { +void MCStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) { MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; if (CurFrame && !CurFrame->End) report_fatal_error("Starting a function before ending the previous one!");