[ms] [llvm-ml] Add basic support for SEH, including PROC FRAME

Add basic support for SEH, including PROC FRAME

Reviewed By: thakis

Differential Revision: https://reviews.llvm.org/D86948
This commit is contained in:
Eric Astor 2020-09-14 14:32:33 -04:00
parent 20201dc76a
commit 23a2b03221
5 changed files with 118 additions and 27 deletions

View File

@ -53,6 +53,9 @@ class COFFMasmParser : public MCAsmParserExtension {
bool ParseDirectiveSegmentEnd(StringRef, SMLoc); bool ParseDirectiveSegmentEnd(StringRef, SMLoc);
bool ParseDirectiveIncludelib(StringRef, SMLoc); bool ParseDirectiveIncludelib(StringRef, SMLoc);
bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
bool IgnoreDirective(StringRef, SMLoc) { bool IgnoreDirective(StringRef, SMLoc) {
while (!getLexer().is(AsmToken::EndOfStatement)) { while (!getLexer().is(AsmToken::EndOfStatement)) {
Lex(); Lex();
@ -65,13 +68,10 @@ class COFFMasmParser : public MCAsmParserExtension {
MCAsmParserExtension::Initialize(Parser); MCAsmParserExtension::Initialize(Parser);
// x64 directives // x64 directives
// .allocstack addDirectiveHandler<&COFFMasmParser::ParseSEHDirectiveAllocStack>(
// .endprolog ".allocstack");
// .pushframe addDirectiveHandler<&COFFMasmParser::ParseSEHDirectiveEndProlog>(
// .pushreg ".endprolog");
// .savereg
// .savexmm128
// .setframe
// Code label directives // Code label directives
// label // label
@ -92,16 +92,12 @@ class COFFMasmParser : public MCAsmParserExtension {
// Data allocation directives // Data allocation directives
// align // align
// byte/sbyte
// dword/sdword
// even // even
// fword // mmword
// qword
// real4
// real8
// real10 // real10
// tbyte // tbyte
// word/sword // xmmword
// ymmword
// Listing control directives // Listing control directives
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref"); addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref");
@ -133,14 +129,11 @@ class COFFMasmParser : public MCAsmParserExtension {
// .fpo // .fpo
addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>( addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>(
"includelib"); "includelib");
// mmword
// option // option
// popcontext // popcontext
// pushcontext // pushcontext
// .radix // .radix
// .safeseh // .safeseh
// xmmword
// ymmword
// Procedure directives // Procedure directives
addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp"); addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp");
@ -148,7 +141,7 @@ class COFFMasmParser : public MCAsmParserExtension {
addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc"); addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc");
// proto // proto
// Processor directives // Processor directives; all ignored
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386"); addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386P"); addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386P");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387"); addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387");
@ -202,11 +195,8 @@ class COFFMasmParser : public MCAsmParserExtension {
// substr (equivalent to <name> TEXTEQU @SubStr(<params>)) // substr (equivalent to <name> TEXTEQU @SubStr(<params>))
// Structure and record directives // Structure and record directives
// ends
// record // record
// struct
// typedef // typedef
// union
} }
bool ParseSectionDirectiveCode(StringRef, SMLoc) { bool ParseSectionDirectiveCode(StringRef, SMLoc) {
@ -234,6 +224,7 @@ class COFFMasmParser : public MCAsmParserExtension {
} }
StringRef CurrentProcedure; StringRef CurrentProcedure;
bool CurrentProcedureFramed;
public: public:
COFFMasmParser() = default; COFFMasmParser() = default;
@ -361,8 +352,17 @@ bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) {
getStreamer().EmitCOFFSymbolType(0x20); getStreamer().EmitCOFFSymbolType(0x20);
getStreamer().EndCOFFSymbolDef(); 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); getStreamer().emitLabel(Sym, Loc);
CurrentProcedure = Label; CurrentProcedure = Label;
CurrentProcedureFramed = Framed;
return false; return false;
} }
bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) { bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) {
@ -376,6 +376,30 @@ bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) {
else if (CurrentProcedure != Label) else if (CurrentProcedure != Label)
return Error(LabelLoc, "endp does not match current procedure '" + return Error(LabelLoc, "endp does not match current procedure '" +
CurrentProcedure + "'"); 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<unsigned>(Size), Loc);
return false;
}
bool COFFMasmParser::ParseSEHDirectiveEndProlog(StringRef Directive,
SMLoc Loc) {
getStreamer().EmitWinCFIEndProlog(Loc);
return false; return false;
} }

View File

@ -726,7 +726,12 @@ private:
DK_STRUCT, DK_STRUCT,
DK_UNION, DK_UNION,
DK_ENDS, 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 /// Maps directive name --> DirectiveKind enum, for directives parsed by this
@ -6333,6 +6338,11 @@ void MasmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".erridni"] = DK_ERRIDNI; DirectiveKindMap[".erridni"] = DK_ERRIDNI;
DirectiveKindMap[".erre"] = DK_ERRE; DirectiveKindMap[".erre"] = DK_ERRE;
DirectiveKindMap[".errnz"] = DK_ERRNZ; 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[".altmacro"] = DK_ALTMACRO;
// DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO; // DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
DirectiveKindMap["db"] = DK_DB; DirectiveKindMap["db"] = DK_DB;

View File

@ -4172,15 +4172,20 @@ bool X86AsmParser::ParseDirective(AsmToken DirectiveID) {
return parseDirectiveFPOEndPrologue(DirectiveID.getLoc()); return parseDirectiveFPOEndPrologue(DirectiveID.getLoc());
else if (IDVal == ".cv_fpo_endproc") else if (IDVal == ".cv_fpo_endproc")
return parseDirectiveFPOEndProc(DirectiveID.getLoc()); return parseDirectiveFPOEndProc(DirectiveID.getLoc());
else if (IDVal == ".seh_pushreg") else if (IDVal == ".seh_pushreg" ||
(Parser.isParsingMasm() && IDVal.equals_lower(".pushreg")))
return parseDirectiveSEHPushReg(DirectiveID.getLoc()); return parseDirectiveSEHPushReg(DirectiveID.getLoc());
else if (IDVal == ".seh_setframe") else if (IDVal == ".seh_setframe" ||
(Parser.isParsingMasm() && IDVal.equals_lower(".setframe")))
return parseDirectiveSEHSetFrame(DirectiveID.getLoc()); return parseDirectiveSEHSetFrame(DirectiveID.getLoc());
else if (IDVal == ".seh_savereg") else if (IDVal == ".seh_savereg" ||
(Parser.isParsingMasm() && IDVal.equals_lower(".savereg")))
return parseDirectiveSEHSaveReg(DirectiveID.getLoc()); return parseDirectiveSEHSaveReg(DirectiveID.getLoc());
else if (IDVal == ".seh_savexmm") else if (IDVal == ".seh_savexmm" ||
(Parser.isParsingMasm() && IDVal.equals_lower(".savexmm128")))
return parseDirectiveSEHSaveXMM(DirectiveID.getLoc()); 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 parseDirectiveSEHPushFrame(DirectiveID.getLoc());
return true; return true;

View File

@ -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

View File

@ -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