+void MCAsmStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) {
+ MCStreamer::EmitWin64EHStartProc(Symbol);
+
+ OS << ".seh_proc " << *Symbol;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWin64EHEndProc() {
+ MCStreamer::EmitWin64EHEndProc();
+
+ OS << "\t.seh_endproc";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWin64EHStartChained() {
+ MCStreamer::EmitWin64EHStartChained();
+
+ OS << "\t.seh_startchained";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWin64EHEndChained() {
+ MCStreamer::EmitWin64EHEndChained();
+
+ OS << "\t.seh_endchained";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind,
+ bool Except) {
+ MCStreamer::EmitWin64EHHandler(Sym, Unwind, Except);
+
+ OS << "\t.seh_handler " << *Sym;
+ if (Unwind)
+ OS << ", @unwind";
+ if (Except)
+ OS << ", @except";
+ EmitEOL();
+}
+
+static const MCSection *getWin64EHTableSection(StringRef suffix,
+ MCContext &context) {
+ // FIXME: This doesn't belong in MCObjectFileInfo. However,
+ /// this duplicate code in MCWin64EH.cpp.
+ if (suffix == "")
+ return context.getObjectFileInfo()->getXDataSection();
+ return context.getCOFFSection((".xdata"+suffix).str(),
+ COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ |
+ COFF::IMAGE_SCN_MEM_WRITE,
+ SectionKind::getDataRel());
+}
+
+void MCAsmStreamer::EmitWin64EHHandlerData() {
+ MCStreamer::EmitWin64EHHandlerData();
+
+ // Switch sections. Don't call SwitchSection directly, because that will
+ // cause the section switch to be visible in the emitted assembly.
+ // We only do this so the section switch that terminates the handler
+ // data block is visible.
+ MCWin64EHUnwindInfo *CurFrame = getCurrentW64UnwindInfo();
+ StringRef suffix=MCWin64EHUnwindEmitter::GetSectionSuffix(CurFrame->Function);
+ const MCSection *xdataSect = getWin64EHTableSection(suffix, getContext());
+ if (xdataSect)
+ SwitchSectionNoChange(xdataSect);
+
+ OS << "\t.seh_handlerdata";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWin64EHPushReg(unsigned Register) {
+ MCStreamer::EmitWin64EHPushReg(Register);
+
+ OS << "\t.seh_pushreg " << Register;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWin64EHSetFrame(unsigned Register, unsigned Offset) {
+ MCStreamer::EmitWin64EHSetFrame(Register, Offset);
+
+ OS << "\t.seh_setframe " << Register << ", " << Offset;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWin64EHAllocStack(unsigned Size) {
+ MCStreamer::EmitWin64EHAllocStack(Size);
+
+ OS << "\t.seh_stackalloc " << Size;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWin64EHSaveReg(unsigned Register, unsigned Offset) {
+ MCStreamer::EmitWin64EHSaveReg(Register, Offset);
+
+ OS << "\t.seh_savereg " << Register << ", " << Offset;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWin64EHSaveXMM(unsigned Register, unsigned Offset) {
+ MCStreamer::EmitWin64EHSaveXMM(Register, Offset);
+
+ OS << "\t.seh_savexmm " << Register << ", " << Offset;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWin64EHPushFrame(bool Code) {
+ MCStreamer::EmitWin64EHPushFrame(Code);
+
+ OS << "\t.seh_pushframe";
+ if (Code)
+ OS << " @code";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWin64EHEndProlog(void) {
+ MCStreamer::EmitWin64EHEndProlog();
+
+ OS << "\t.seh_endprologue";
+ EmitEOL();