diff --git a/llvm/lib/MC/MCParser/COFFMasmParser.cpp b/llvm/lib/MC/MCParser/COFFMasmParser.cpp --- a/llvm/lib/MC/MCParser/COFFMasmParser.cpp +++ b/llvm/lib/MC/MCParser/COFFMasmParser.cpp @@ -53,6 +53,9 @@ bool ParseDirectiveSegmentEnd(StringRef, SMLoc); bool ParseDirectiveIncludelib(StringRef, SMLoc); + bool ParseSEHDirectiveAllocStack(StringRef, SMLoc); + bool ParseSEHDirectiveEndProlog(StringRef, SMLoc); + bool IgnoreDirective(StringRef, SMLoc) { while (!getLexer().is(AsmToken::EndOfStatement)) { Lex(); @@ -65,13 +68,10 @@ MCAsmParserExtension::Initialize(Parser); // x64 directives - // .allocstack - // .endprolog - // .pushframe - // .pushreg - // .savereg - // .savexmm128 - // .setframe + addDirectiveHandler<&COFFMasmParser::ParseSEHDirectiveAllocStack>( + ".allocstack"); + addDirectiveHandler<&COFFMasmParser::ParseSEHDirectiveEndProlog>( + ".endprolog"); // Code label directives // label @@ -92,16 +92,12 @@ // Data allocation directives // align - // byte/sbyte - // dword/sdword // even - // fword - // qword - // real4 - // real8 + // mmword // real10 // tbyte - // word/sword + // xmmword + // ymmword // Listing control directives addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref"); @@ -133,14 +129,11 @@ // .fpo addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>( "includelib"); - // mmword // option // popcontext // pushcontext // .radix // .safeseh - // xmmword - // ymmword // Procedure directives addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp"); @@ -148,7 +141,7 @@ addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc"); // proto - // Processor directives + // Processor directives; all ignored addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386"); addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386P"); addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387"); @@ -202,11 +195,8 @@ // substr (equivalent to TEXTEQU @SubStr()) // Structure and record directives - // ends // record - // struct // typedef - // union } bool ParseSectionDirectiveCode(StringRef, SMLoc) { @@ -234,6 +224,7 @@ } StringRef CurrentProcedure; + bool CurrentProcedureFramed; public: COFFMasmParser() = default; @@ -361,8 +352,17 @@ getStreamer().EmitCOFFSymbolType(0x20); getStreamer().EndCOFFSymbolDef(); + bool Framed = false; + if (getLexer().is(AsmToken::Identifier) && + getTok().getString().equals_lower("frame")) { + Lex(); + Framed = true; + getStreamer().EmitWinCFIStartProc(Sym, Loc); + } getStreamer().emitLabel(Sym, Loc); + CurrentProcedure = Label; + CurrentProcedureFramed = Framed; return false; } bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) { @@ -376,6 +376,30 @@ else if (CurrentProcedure != Label) return Error(LabelLoc, "endp does not match current procedure '" + CurrentProcedure + "'"); + + if (CurrentProcedureFramed) { + getStreamer().EmitWinCFIEndProc(Loc); + } + CurrentProcedure = ""; + CurrentProcedureFramed = false; + return false; +} + +bool COFFMasmParser::ParseSEHDirectiveAllocStack(StringRef Directive, + SMLoc Loc) { + int64_t Size; + SMLoc SizeLoc = getTok().getLoc(); + if (getParser().parseAbsoluteExpression(Size)) + return Error(SizeLoc, "expected integer size"); + if (Size % 8 != 0) + return Error(SizeLoc, "stack size must be a multiple of 8"); + getStreamer().EmitWinCFIAllocStack(static_cast(Size), Loc); + return false; +} + +bool COFFMasmParser::ParseSEHDirectiveEndProlog(StringRef Directive, + SMLoc Loc) { + getStreamer().EmitWinCFIEndProlog(Loc); return false; } diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -721,7 +721,12 @@ DK_STRUCT, DK_UNION, DK_ENDS, - DK_END + DK_END, + DK_PUSHFRAME, + DK_PUSHREG, + DK_SAVEREG, + DK_SAVEXMM128, + DK_SETFRAME, }; /// Maps directive name --> DirectiveKind enum, for directives parsed by this @@ -6281,6 +6286,11 @@ DirectiveKindMap[".erridni"] = DK_ERRIDNI; DirectiveKindMap[".erre"] = DK_ERRE; DirectiveKindMap[".errnz"] = DK_ERRNZ; + DirectiveKindMap[".pushframe"] = DK_PUSHFRAME; + DirectiveKindMap[".pushreg"] = DK_PUSHREG; + DirectiveKindMap[".savereg"] = DK_SAVEREG; + DirectiveKindMap[".savexmm128"] = DK_SAVEXMM128; + DirectiveKindMap[".setframe"] = DK_SETFRAME; // DirectiveKindMap[".altmacro"] = DK_ALTMACRO; // DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO; DirectiveKindMap["db"] = DK_DB; diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -4172,15 +4172,20 @@ return parseDirectiveFPOEndPrologue(DirectiveID.getLoc()); else if (IDVal == ".cv_fpo_endproc") return parseDirectiveFPOEndProc(DirectiveID.getLoc()); - else if (IDVal == ".seh_pushreg") + else if (IDVal == ".seh_pushreg" || + (Parser.isParsingMasm() && IDVal.equals_lower(".pushreg"))) return parseDirectiveSEHPushReg(DirectiveID.getLoc()); - else if (IDVal == ".seh_setframe") + else if (IDVal == ".seh_setframe" || + (Parser.isParsingMasm() && IDVal.equals_lower(".setframe"))) return parseDirectiveSEHSetFrame(DirectiveID.getLoc()); - else if (IDVal == ".seh_savereg") + else if (IDVal == ".seh_savereg" || + (Parser.isParsingMasm() && IDVal.equals_lower(".savereg"))) return parseDirectiveSEHSaveReg(DirectiveID.getLoc()); - else if (IDVal == ".seh_savexmm") + else if (IDVal == ".seh_savexmm" || + (Parser.isParsingMasm() && IDVal.equals_lower(".savexmm128"))) return parseDirectiveSEHSaveXMM(DirectiveID.getLoc()); - else if (IDVal == ".seh_pushframe") + else if (IDVal == ".seh_pushframe" || + (Parser.isParsingMasm() && IDVal.equals_lower(".pushframe"))) return parseDirectiveSEHPushFrame(DirectiveID.getLoc()); return true; diff --git a/llvm/test/tools/llvm-ml/proc.test b/llvm/test/tools/llvm-ml/proc.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ml/proc.test @@ -0,0 +1,18 @@ +# RUN: llvm-ml -m32 -filetype=asm %s | FileCheck %s +# RUN: llvm-ml -m64 -filetype=asm %s | FileCheck %s + +.code + +t1 PROC + ret +t1 ENDP + +; CHECK: .def t1 +; CHECK-NEXT: .scl 2 +; CHECK-NEXT: .type 32 +; CHECK-NEXT: .endef + +; CHECK: t1: +; CHECK: ret + +END diff --git a/llvm/test/tools/llvm-ml/proc_frame.test b/llvm/test/tools/llvm-ml/proc_frame.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ml/proc_frame.test @@ -0,0 +1,34 @@ +# RUN: llvm-ml -m64 -filetype=asm %s | FileCheck %s + +.code + +t1 PROC FRAME + push rbp + .pushreg rbp + mov rbp, rsp + .setframe rbp, 0 + pushfq + .allocstack 8 + .endprolog + ret +t1 ENDP + +; CHECK: .def t1 +; CHECK-NEXT: .scl 2 +; CHECK-NEXT: .type 32 +; CHECK-NEXT: .endef + +; CHECK: .seh_proc t1 + +; CHECK: t1: +; CHECK: push rbp +; CHECK: .seh_pushreg rbp +; CHECK: mov rbp, rsp +; CHECK: .seh_setframe rbp, 0 +; CHECK: pushfq +; CHECK: .seh_stackalloc 8 +; CHECK: .seh_endprologue +; CHECK: ret +; CHECK: .seh_endproc + +END