[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 d82f49fb4b
commit c1961f9100
5 changed files with 118 additions and 27 deletions

View File

@ -53,6 +53,9 @@ class COFFMasmParser : public MCAsmParserExtension {
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 @@ class COFFMasmParser : public MCAsmParserExtension {
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 @@ class COFFMasmParser : public MCAsmParserExtension {
// 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 @@ class COFFMasmParser : public MCAsmParserExtension {
// .fpo
addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>(
"includelib");
// mmword
// option
// popcontext
// pushcontext
// .radix
// .safeseh
// xmmword
// ymmword
// Procedure directives
addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp");
@ -148,7 +141,7 @@ class COFFMasmParser : public MCAsmParserExtension {
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 @@ class COFFMasmParser : public MCAsmParserExtension {
// substr (equivalent to <name> TEXTEQU @SubStr(<params>))
// Structure and record directives
// ends
// record
// struct
// typedef
// union
}
bool ParseSectionDirectiveCode(StringRef, SMLoc) {
@ -234,6 +224,7 @@ class COFFMasmParser : public MCAsmParserExtension {
}
StringRef CurrentProcedure;
bool CurrentProcedureFramed;
public:
COFFMasmParser() = default;
@ -361,8 +352,17 @@ bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) {
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 @@ bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) {
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<unsigned>(Size), Loc);
return false;
}
bool COFFMasmParser::ParseSEHDirectiveEndProlog(StringRef Directive,
SMLoc Loc) {
getStreamer().EmitWinCFIEndProlog(Loc);
return false;
}

View File

@ -726,7 +726,12 @@ private:
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
@ -6333,6 +6338,11 @@ void MasmParser::initializeDirectiveKindMap() {
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;

View File

@ -4172,15 +4172,20 @@ bool X86AsmParser::ParseDirective(AsmToken DirectiveID) {
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;

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