Add methods to parse the SEH directives to the COFFAsmParser. Implement some
authorCharles Davis <cdavis@mines.edu>
Sun, 22 May 2011 21:12:15 +0000 (21:12 +0000)
committerCharles Davis <cdavis@mines.edu>
Sun, 22 May 2011 21:12:15 +0000 (21:12 +0000)
of them, particularly the ones that don't take arguments. Also implement
.seh_proc and .seh_handler.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131866 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCStreamer.h
lib/MC/MCAsmStreamer.cpp
lib/MC/MCParser/COFFAsmParser.cpp
lib/MC/MCStreamer.cpp

index c12caf01b03d0cd9af725a79886f8de5e4ebd66d..4c7fa40a8065c9abd89148e789b93b802c6f19d8 100644 (file)
@@ -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();
index 9bd614acfc65adb2e758a00c813aae0166c475ba..1df5c074746305a16540ea260c41849a438a8e44 100644 (file)
@@ -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;
index 5ecab03b00f0c42975137850265849e1e356e47c..0045950dcaaca82e2560cd2be4161dcc732b0c25 100644 (file)
@@ -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<MCSymbolRefExpr>(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<MCSymbolRefExpr>(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() {
index f268f9e3756e10da53ff724033ad15142b76026b..1402033d41da3067f39abfb788f334352759f59d 100644 (file)
@@ -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!");