summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp4
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp7
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp19
-rw-r--r--llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp97
-rw-r--r--llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt3
-rw-r--r--llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp8
-rw-r--r--llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h10
-rw-r--r--llvm/lib/Target/X86/MCTargetDesc/X86TargetStreamer.h34
-rw-r--r--llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp8
-rw-r--r--llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFTargetStreamer.cpp415
-rw-r--r--llvm/lib/Target/X86/X86AsmPrinter.cpp26
-rw-r--r--llvm/lib/Target/X86/X86AsmPrinter.h6
-rw-r--r--llvm/lib/Target/X86/X86FrameLowering.cpp27
-rw-r--r--llvm/lib/Target/X86/X86MCInstLower.cpp107
-rw-r--r--llvm/lib/Target/X86/X86Subtarget.h8
15 files changed, 734 insertions, 45 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 021cee526d8..7d50d643c99 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -808,6 +808,10 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
if (FuncName.empty())
FuncName = GlobalValue::dropLLVMManglingEscape(GV->getName());
+ // Emit FPO data, but only on 32-bit x86. No other platforms use it.
+ if (Triple(MMI->getModule()->getTargetTriple()).getArch() == Triple::x86)
+ OS.EmitCVFPOData(Fn);
+
// Emit a symbol subsection, required by VS2012+ to find function boundaries.
OS.AddComment("Symbol subsection for " + Twine(FuncName));
MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 08b02d0f85b..f48ae84950e 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -248,6 +248,7 @@ public:
void EmitCVStringTableDirective() override;
void EmitCVFileChecksumsDirective() override;
void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override;
+ void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
void EmitIdent(StringRef IdentString) override;
void EmitCFISections(bool EH, bool Debug) override;
@@ -1252,6 +1253,12 @@ void MCAsmStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
EmitEOL();
}
+void MCAsmStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
+ OS << "\t.cv_fpo_data\t";
+ ProcSym->print(OS, MAI);
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitIdent(StringRef IdentString) {
assert(MAI->hasIdentDirective() && ".ident directive not supported");
OS << "\t.ident\t";
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 186f33987a4..2259136c6ec 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -503,6 +503,7 @@ private:
DK_CV_STRINGTABLE,
DK_CV_FILECHECKSUMS,
DK_CV_FILECHECKSUM_OFFSET,
+ DK_CV_FPO_DATA,
DK_CFI_SECTIONS,
DK_CFI_STARTPROC,
DK_CFI_ENDPROC,
@@ -580,6 +581,7 @@ private:
bool parseDirectiveCVStringTable();
bool parseDirectiveCVFileChecksums();
bool parseDirectiveCVFileChecksumOffset();
+ bool parseDirectiveCVFPOData();
// .cfi directives
bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
@@ -2039,6 +2041,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectiveCVFileChecksums();
case DK_CV_FILECHECKSUM_OFFSET:
return parseDirectiveCVFileChecksumOffset();
+ case DK_CV_FPO_DATA:
+ return parseDirectiveCVFPOData();
case DK_CFI_SECTIONS:
return parseDirectiveCFISections();
case DK_CFI_STARTPROC:
@@ -3791,6 +3795,20 @@ bool AsmParser::parseDirectiveCVFileChecksumOffset() {
return false;
}
+/// parseDirectiveCVFPOData
+/// ::= .cv_fpo_data procsym
+bool AsmParser::parseDirectiveCVFPOData() {
+ SMLoc DirLoc = getLexer().getLoc();
+ StringRef ProcName;
+ if (parseIdentifier(ProcName))
+ return TokError("expected symbol name");
+ if (parseEOL("unexpected tokens"))
+ return addErrorSuffix(" in '.cv_fpo_data' directive");
+ MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
+ getStreamer().EmitCVFPOData(ProcSym, DirLoc);
+ return false;
+}
+
/// parseDirectiveCFISections
/// ::= .cfi_sections section [, section]
bool AsmParser::parseDirectiveCFISections() {
@@ -5174,6 +5192,7 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
+ DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
DirectiveKindMap[".sleb128"] = DK_SLEB128;
DirectiveKindMap[".uleb128"] = DK_ULEB128;
DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 22ad3cbd3eb..385bbbe60a2 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -7,11 +7,12 @@
//
//===----------------------------------------------------------------------===//
+#include "InstPrinter/X86IntelInstPrinter.h"
#include "MCTargetDesc/X86BaseInfo.h"
+#include "MCTargetDesc/X86TargetStreamer.h"
#include "X86AsmInstrumentation.h"
#include "X86AsmParserCommon.h"
#include "X86Operand.h"
-#include "InstPrinter/X86IntelInstPrinter.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -80,6 +81,13 @@ private:
return Result;
}
+ X86TargetStreamer &getTargetStreamer() {
+ assert(getParser().getStreamer().getTargetStreamer() &&
+ "do not have a target streamer");
+ MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
+ return static_cast<X86TargetStreamer &>(TS);
+ }
+
unsigned MatchInstruction(const OperandVector &Operands, MCInst &Inst,
uint64_t &ErrorInfo, bool matchingInlineAsm,
unsigned VariantID = 0) {
@@ -839,6 +847,15 @@ private:
bool ParseDirectiveWord(unsigned Size, SMLoc L);
bool ParseDirectiveCode(StringRef IDVal, SMLoc L);
+ /// CodeView FPO data directives.
+ bool parseDirectiveFPOProc(SMLoc L);
+ bool parseDirectiveFPOSetFrame(SMLoc L);
+ bool parseDirectiveFPOPushReg(SMLoc L);
+ bool parseDirectiveFPOStackAlloc(SMLoc L);
+ bool parseDirectiveFPOEndPrologue(SMLoc L);
+ bool parseDirectiveFPOEndProc(SMLoc L);
+ bool parseDirectiveFPOData(SMLoc L);
+
bool processInstruction(MCInst &Inst, const OperandVector &Ops);
/// Wrapper around MCStreamer::EmitInstruction(). Possibly adds
@@ -3027,6 +3044,19 @@ bool X86AsmParser::ParseDirective(AsmToken DirectiveID) {
return false;
} else if (IDVal == ".even")
return parseDirectiveEven(DirectiveID.getLoc());
+ else if (IDVal == ".cv_fpo_proc")
+ return parseDirectiveFPOProc(DirectiveID.getLoc());
+ else if (IDVal == ".cv_fpo_setframe")
+ return parseDirectiveFPOSetFrame(DirectiveID.getLoc());
+ else if (IDVal == ".cv_fpo_pushreg")
+ return parseDirectiveFPOPushReg(DirectiveID.getLoc());
+ else if (IDVal == ".cv_fpo_stackalloc")
+ return parseDirectiveFPOStackAlloc(DirectiveID.getLoc());
+ else if (IDVal == ".cv_fpo_endprologue")
+ return parseDirectiveFPOEndPrologue(DirectiveID.getLoc());
+ else if (IDVal == ".cv_fpo_endproc")
+ return parseDirectiveFPOEndProc(DirectiveID.getLoc());
+
return true;
}
@@ -3124,6 +3154,71 @@ bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) {
return false;
}
+// .cv_fpo_proc foo
+bool X86AsmParser::parseDirectiveFPOProc(SMLoc L) {
+ MCAsmParser &Parser = getParser();
+ StringRef ProcName;
+ int64_t ParamsSize;
+ if (Parser.parseIdentifier(ProcName))
+ return Parser.TokError("expected symbol name");
+ if (Parser.parseIntToken(ParamsSize, "expected parameter byte count"))
+ return true;
+ if (!isUIntN(32, ParamsSize))
+ return Parser.TokError("parameters size out of range");
+ if (Parser.parseEOL("unexpected tokens"))
+ return addErrorSuffix(" in '.cv_fpo_proc' directive");
+ MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
+ return getTargetStreamer().emitFPOProc(ProcSym, ParamsSize, L);
+}
+
+// .cv_fpo_setframe ebp
+bool X86AsmParser::parseDirectiveFPOSetFrame(SMLoc L) {
+ MCAsmParser &Parser = getParser();
+ unsigned Reg;
+ SMLoc DummyLoc;
+ if (ParseRegister(Reg, DummyLoc, DummyLoc) ||
+ Parser.parseEOL("unexpected tokens"))
+ return addErrorSuffix(" in '.cv_fpo_setframe' directive");
+ return getTargetStreamer().emitFPOSetFrame(Reg, L);
+}
+
+// .cv_fpo_pushreg ebx
+bool X86AsmParser::parseDirectiveFPOPushReg(SMLoc L) {
+ MCAsmParser &Parser = getParser();
+ unsigned Reg;
+ SMLoc DummyLoc;
+ if (ParseRegister(Reg, DummyLoc, DummyLoc) ||
+ Parser.parseEOL("unexpected tokens"))
+ return addErrorSuffix(" in '.cv_fpo_pushreg' directive");
+ return getTargetStreamer().emitFPOPushReg(Reg, L);
+}
+
+// .cv_fpo_stackalloc 20
+bool X86AsmParser::parseDirectiveFPOStackAlloc(SMLoc L) {
+ MCAsmParser &Parser = getParser();
+ int64_t Offset;
+ if (Parser.parseIntToken(Offset, "expected offset") ||
+ Parser.parseEOL("unexpected tokens"))
+ return addErrorSuffix(" in '.cv_fpo_stackalloc' directive");
+ return getTargetStreamer().emitFPOStackAlloc(Offset, L);
+}
+
+// .cv_fpo_endprologue
+bool X86AsmParser::parseDirectiveFPOEndPrologue(SMLoc L) {
+ MCAsmParser &Parser = getParser();
+ if (Parser.parseEOL("unexpected tokens"))
+ return addErrorSuffix(" in '.cv_fpo_endprologue' directive");
+ return getTargetStreamer().emitFPOEndPrologue(L);
+}
+
+// .cv_fpo_endproc
+bool X86AsmParser::parseDirectiveFPOEndProc(SMLoc L) {
+ MCAsmParser &Parser = getParser();
+ if (Parser.parseEOL("unexpected tokens"))
+ return addErrorSuffix(" in '.cv_fpo_endproc' directive");
+ return getTargetStreamer().emitFPOEndProc(L);
+}
+
// Force static initialization.
extern "C" void LLVMInitializeX86AsmParser() {
RegisterMCAsmParser<X86AsmParser> X(getTheX86_32Target());
diff --git a/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt
index 33df9ec7dcd..8d0d9fa1215 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt
@@ -5,6 +5,7 @@ add_llvm_library(LLVMX86Desc
X86MCCodeEmitter.cpp
X86MachObjectWriter.cpp
X86ELFObjectWriter.cpp
- X86WinCOFFStreamer.cpp
X86WinCOFFObjectWriter.cpp
+ X86WinCOFFStreamer.cpp
+ X86WinCOFFTargetStreamer.cpp
)
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
index 29b47fd220f..cdd43478bae 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
@@ -319,7 +319,13 @@ extern "C" void LLVMInitializeX86TargetMC() {
// Register the code emitter.
TargetRegistry::RegisterMCCodeEmitter(*T, createX86MCCodeEmitter);
- // Register the object streamer.
+ // Register the obj target streamer.
+ TargetRegistry::RegisterObjectTargetStreamer(*T,
+ createX86ObjectTargetStreamer);
+
+ // Register the asm target streamer.
+ TargetRegistry::RegisterAsmTargetStreamer(*T, createX86AsmTargetStreamer);
+
TargetRegistry::RegisterCOFFStreamer(*T, createX86WinCOFFStreamer);
// Register the MCInstPrinter.
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
index 327852396e4..757ae5d197e 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
@@ -77,6 +77,16 @@ MCAsmBackend *createX86_64AsmBackend(const Target &T, const MCRegisterInfo &MRI,
const Triple &TT, StringRef CPU,
const MCTargetOptions &Options);
+/// Implements X86-only directives for assembly emission.
+MCTargetStreamer *createX86AsmTargetStreamer(MCStreamer &S,
+ formatted_raw_ostream &OS,
+ MCInstPrinter *InstPrint,
+ bool isVerboseAsm);
+
+/// Implements X86-only directives for object files.
+MCTargetStreamer *createX86ObjectTargetStreamer(MCStreamer &OS,
+ const MCSubtargetInfo &STI);
+
/// Construct an X86 Windows COFF machine code streamer which will generate
/// PE/COFF format object files.
///
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86TargetStreamer.h b/llvm/lib/Target/X86/MCTargetDesc/X86TargetStreamer.h
new file mode 100644
index 00000000000..8d38cd32b82
--- /dev/null
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86TargetStreamer.h
@@ -0,0 +1,34 @@
+//===- X86TargetStreamer.h ------------------------------*- C++ -*---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_X86_MCTARGETDESC_X86TARGETSTREAMER_H
+#define LLVM_LIB_TARGET_X86_MCTARGETDESC_X86TARGETSTREAMER_H
+
+#include "llvm/MC/MCStreamer.h"
+
+namespace llvm {
+
+/// X86 target streamer implementing x86-only assembly directives.
+class X86TargetStreamer : public MCTargetStreamer {
+public:
+ X86TargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
+
+ virtual bool emitFPOProc(const MCSymbol *ProcSym, unsigned ParamsSize,
+ SMLoc L = {}) = 0;
+ virtual bool emitFPOEndPrologue(SMLoc L = {}) = 0;
+ virtual bool emitFPOEndProc(SMLoc L = {}) = 0;
+ virtual bool emitFPOData(const MCSymbol *ProcSym, SMLoc L = {}) = 0;
+ virtual bool emitFPOPushReg(unsigned Reg, SMLoc L = {}) = 0;
+ virtual bool emitFPOStackAlloc(unsigned StackAlloc, SMLoc L = {}) = 0;
+ virtual bool emitFPOSetFrame(unsigned Reg, SMLoc L = {}) = 0;
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp
index 487823b258a..157c4c7b62b 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "X86MCTargetDesc.h"
+#include "X86TargetStreamer.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCWin64EH.h"
#include "llvm/MC/MCWinCOFFStreamer.h"
@@ -24,6 +25,7 @@ public:
void EmitWinEHHandlerData(SMLoc Loc) override;
void EmitWindowsUnwindTables() override;
+ void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc) override;
void FinishImpl() override;
};
@@ -41,6 +43,12 @@ void X86WinCOFFStreamer::EmitWindowsUnwindTables() {
EHStreamer.Emit(*this);
}
+void X86WinCOFFStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc) {
+ X86TargetStreamer *XTS =
+ static_cast<X86TargetStreamer *>(getTargetStreamer());
+ XTS->emitFPOData(ProcSym, Loc);
+}
+
void X86WinCOFFStreamer::FinishImpl() {
EmitFrames(nullptr);
EmitWindowsUnwindTables();
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFTargetStreamer.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFTargetStreamer.cpp
new file mode 100644
index 00000000000..093dab4f2f9
--- /dev/null
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFTargetStreamer.cpp
@@ -0,0 +1,415 @@
+//===-- X86WinCOFFTargetStreamer.cpp ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86MCTargetDesc.h"
+#include "X86TargetStreamer.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/MC/MCCodeView.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/FormattedStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+namespace {
+/// Implements Windows x86-only directives for assembly emission.
+class X86WinCOFFAsmTargetStreamer : public X86TargetStreamer {
+ formatted_raw_ostream &OS;
+ MCInstPrinter &InstPrinter;
+
+public:
+ X86WinCOFFAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
+ MCInstPrinter &InstPrinter)
+ : X86TargetStreamer(S), OS(OS), InstPrinter(InstPrinter) {}
+
+ bool emitFPOProc(const MCSymbol *ProcSym, unsigned ParamsSize,
+ SMLoc L) override;
+ bool emitFPOEndPrologue(SMLoc L) override;
+ bool emitFPOEndProc(SMLoc L) override;
+ bool emitFPOData(const MCSymbol *ProcSym, SMLoc L) override;
+ bool emitFPOPushReg(unsigned Reg, SMLoc L) override;
+ bool emitFPOStackAlloc(unsigned StackAlloc, SMLoc L) override;
+ bool emitFPOSetFrame(unsigned Reg, SMLoc L) override;
+};
+
+/// Represents a single FPO directive.
+struct FPOInstruction {
+ MCSymbol *Label;
+ enum Operation {
+ PushReg,
+ StackAlloc,
+ SetFrame,
+ } Op;
+ unsigned RegOrOffset;
+};
+
+struct FPOData {
+ const MCSymbol *Function = nullptr;
+ MCSymbol *Begin = nullptr;
+ MCSymbol *PrologueEnd = nullptr;
+ MCSymbol *End = nullptr;
+ unsigned ParamsSize = 0;
+
+ SmallVector<FPOInstruction, 5> Instructions;
+};
+
+/// Implements Windows x86-only directives for object emission.
+class X86WinCOFFTargetStreamer : public X86TargetStreamer {
+ /// Map from function symbol to its FPO data.
+ DenseMap<const MCSymbol *, std::unique_ptr<FPOData>> AllFPOData;
+
+ /// Current FPO data created by .cv_fpo_proc.
+ std::unique_ptr<FPOData> CurFPOData;
+
+ bool haveOpenFPOData() { return !!CurFPOData; }
+
+ /// Diagnoses an error at L if we are not in an FPO prologue. Return true on
+ /// error.
+ bool checkInFPOPrologue(SMLoc L);
+
+ MCSymbol *emitFPOLabel();
+
+ MCContext &getContext() { return getStreamer().getContext(); }
+
+public:
+ X86WinCOFFTargetStreamer(MCStreamer &S) : X86TargetStreamer(S) {}
+
+ bool emitFPOProc(const MCSymbol *ProcSym, unsigned ParamsSize,
+ SMLoc L) override;
+ bool emitFPOEndPrologue(SMLoc L) override;
+ bool emitFPOEndProc(SMLoc L) override;
+ bool emitFPOData(const MCSymbol *ProcSym, SMLoc L) override;
+ bool emitFPOPushReg(unsigned Reg, SMLoc L) override;
+ bool emitFPOStackAlloc(unsigned StackAlloc, SMLoc L) override;
+ bool emitFPOSetFrame(unsigned Reg, SMLoc L) override;
+};
+} // end namespace
+
+bool X86WinCOFFAsmTargetStreamer::emitFPOProc(const MCSymbol *ProcSym,
+ unsigned ParamsSize, SMLoc L) {
+ OS << "\t.cv_fpo_proc\t";
+ ProcSym->print(OS, getStreamer().getContext().getAsmInfo());
+ OS << ' ' << ParamsSize << '\n';
+ return false;
+}
+
+bool X86WinCOFFAsmTargetStreamer::emitFPOEndPrologue(SMLoc L) {
+ OS << "\t.cv_fpo_endprologue\n";
+ return false;
+}
+
+bool X86WinCOFFAsmTargetStreamer::emitFPOEndProc(SMLoc L) {
+ OS << "\t.cv_fpo_endproc\n";
+ return false;
+}
+
+bool X86WinCOFFAsmTargetStreamer::emitFPOData(const MCSymbol *ProcSym,
+ SMLoc L) {
+ OS << "\t.cv_fpo_data\t";
+ ProcSym->print(OS, getStreamer().getContext().getAsmInfo());
+ OS << '\n';
+ return false;
+}
+
+bool X86WinCOFFAsmTargetStreamer::emitFPOPushReg(unsigned Reg, SMLoc L) {
+ OS << "\t.cv_fpo_pushreg\t";
+ InstPrinter.printRegName(OS, Reg);
+ OS << '\n';
+ return false;
+}
+
+bool X86WinCOFFAsmTargetStreamer::emitFPOStackAlloc(unsigned StackAlloc,
+ SMLoc L) {
+ OS << "\t.cv_fpo_stackalloc\t" << StackAlloc << '\n';
+ return false;
+}
+
+bool X86WinCOFFAsmTargetStreamer::emitFPOSetFrame(unsigned Reg, SMLoc L) {
+ OS << "\t.cv_fpo_setframe\t";
+ InstPrinter.printRegName(OS, Reg);
+ OS << '\n';
+ return false;
+}
+
+bool X86WinCOFFTargetStreamer::checkInFPOPrologue(SMLoc L) {
+ if (!haveOpenFPOData() || CurFPOData->PrologueEnd) {
+ getContext().reportError(
+ L,
+ "directive must appear between .cv_fpo_proc and .cv_fpo_endprologue");
+ return true;
+ }
+ return false;
+}
+
+MCSymbol *X86WinCOFFTargetStreamer::emitFPOLabel() {
+ MCSymbol *Label = getContext().createTempSymbol("cfi", true);
+ getStreamer().EmitLabel(Label);
+ return Label;
+}
+
+bool X86WinCOFFTargetStreamer::emitFPOProc(const MCSymbol *ProcSym,
+ unsigned ParamsSize, SMLoc L) {
+ if (haveOpenFPOData()) {
+ getContext().reportError(
+ L, "opening new .cv_fpo_proc before closing previous frame");
+ return true;
+ }
+ CurFPOData = llvm::make_unique<FPOData>();
+ CurFPOData->Function = ProcSym;
+ CurFPOData->Begin = emitFPOLabel();
+ CurFPOData->ParamsSize = ParamsSize;
+ return false;
+}
+
+bool X86WinCOFFTargetStreamer::emitFPOEndProc(SMLoc L) {
+ if (!haveOpenFPOData()) {
+ getContext().reportError(L, ".cv_fpo_endproc must appear after .cv_proc");
+ return true;
+ }
+ if (!CurFPOData->PrologueEnd) {
+ // Complain if there were prologue setup instructions but no end prologue.
+ if (!CurFPOData->Instructions.empty()) {
+ getContext().reportError(L, "missing .cv_fpo_endprologue");
+ CurFPOData->Instructions.clear();
+ }
+
+ // Claim there is a zero-length prologue to make the label math work out
+ // later.
+ CurFPOData->PrologueEnd = CurFPOData->Begin;
+ }
+
+ CurFPOData->End = emitFPOLabel();
+ const MCSymbol *Fn = CurFPOData->Function;
+ AllFPOData.insert({Fn, std::move(CurFPOData)});
+ return false;
+}
+
+bool X86WinCOFFTargetStreamer::emitFPOSetFrame(unsigned Reg, SMLoc L) {
+ if (checkInFPOPrologue(L))
+ return true;
+ FPOInstruction Inst;
+ Inst.Label = emitFPOLabel();
+ Inst.Op = FPOInstruction::SetFrame;
+ Inst.RegOrOffset = Reg;
+ CurFPOData->Instructions.push_back(Inst);
+ return false;
+}
+
+bool X86WinCOFFTargetStreamer::emitFPOPushReg(unsigned Reg, SMLoc L) {
+ if (checkInFPOPrologue(L))
+ return true;
+ FPOInstruction Inst;
+ Inst.Label = emitFPOLabel();
+ Inst.Op = FPOInstruction::PushReg;
+ Inst.RegOrOffset = Reg;
+ CurFPOData->Instructions.push_back(Inst);
+ return false;
+}
+
+bool X86WinCOFFTargetStreamer::emitFPOStackAlloc(unsigned StackAlloc, SMLoc L) {
+ if (checkInFPOPrologue(L))
+ return true;
+ FPOInstruction Inst;
+ Inst.Label = emitFPOLabel();
+ Inst.Op = FPOInstruction::StackAlloc;
+ Inst.RegOrOffset = StackAlloc;
+ CurFPOData->Instructions.push_back(Inst);
+ return false;
+}
+
+bool X86WinCOFFTargetStreamer::emitFPOEndPrologue(SMLoc L) {
+ if (checkInFPOPrologue(L))
+ return true;
+ CurFPOData->PrologueEnd = emitFPOLabel();
+ return false;
+}
+
+namespace {
+struct RegSaveOffset {
+ RegSaveOffset(unsigned Reg, unsigned Offset) : Reg(Reg), Offset(Offset) {}
+
+ unsigned Reg = 0;
+ unsigned Offset = 0;
+};
+
+struct FPOStateMachine {
+ explicit FPOStateMachine(const FPOData *FPO) : FPO(FPO) {}
+
+ const FPOData *FPO = nullptr;
+ unsigned FrameReg = 0;
+ unsigned FrameRegOff = 0;
+ unsigned CurOffset = 0;
+ unsigned LocalSize = 0;
+ unsigned SavedRegSize = 0;
+ unsigned Flags = 0; // FIXME: Set HasSEH / HasEH.
+
+ SmallString<128> FrameFunc;
+
+ SmallVector<RegSaveOffset, 4> RegSaveOffsets;
+
+ void emitFrameDataRecord(MCStreamer &OS, MCSymbol *Label);
+};
+} // end namespace
+
+static Printable printFPOReg(const MCRegisterInfo *MRI, unsigned LLVMReg) {
+ return Printable([MRI, LLVMReg](raw_ostream &OS) {
+ switch (LLVMReg) {
+ // MSVC only seems to emit symbolic register names for EIP, EBP, and ESP,
+ // but the format seems to support more than that, so we emit them.
+ case X86::EAX: OS << "$eax"; break;
+ case X86::EBX: OS << "$ebx"; break;
+ case X86::ECX: OS << "$ecx"; break;
+ case X86::EDX: OS << "$edx"; break;
+ case X86::EDI: OS << "$edi"; break;
+ case X86::ESI: OS << "$esi"; break;
+ case X86::ESP: OS << "$esp"; break;
+ case X86::EBP: OS << "$ebp"; break;
+ case X86::EIP: OS << "$eip"; break;
+ // Otherwise, get the codeview register number and print $N.
+ default:
+ OS << '$' << MRI->getCodeViewRegNum(LLVMReg);
+ break;
+ }
+ });
+}
+
+void FPOStateMachine::emitFrameDataRecord(MCStreamer &OS, MCSymbol *Label) {
+ unsigned CurFlags = Flags;
+ if (Label == FPO->Begin)
+ CurFlags |= FrameData::IsFunctionStart;
+
+ // Compute the new FrameFunc string.
+ FrameFunc.clear();
+ raw_svector_ostream FuncOS(FrameFunc);
+ const MCRegisterInfo *MRI = OS.getContext().getRegisterInfo();
+ if (FrameReg) {
+ // CFA is FrameReg + FrameRegOff.
+ FuncOS << "$T0 " << printFPOReg(MRI, FrameReg) << " " << FrameRegOff
+ << " + = ";
+ } else {
+ // The address of return address is ESP + CurOffset, but we use .raSearch to
+ // match MSVC. This seems to ask the debugger to subtract some combination
+ // of LocalSize and SavedRegSize from ESP and grovel around in that memory
+ // to find the address of a plausible return address.
+ FuncOS << "$T0 .raSearch = ";
+ }
+
+ // Caller's $eip should be dereferenced CFA, and $esp should be CFA plus 4.
+ FuncOS << "$eip $T0 ^ = $esp $T0 4 + = ";
+
+ // Each saved register is stored at an unchanging negative CFA offset.
+ for (RegSaveOffset RO : RegSaveOffsets)
+ FuncOS << printFPOReg(MRI, RO.Reg) << " $T0 " << RO.Offset << " - ^ = ";
+
+ // Add it to the CV string table.
+ CodeViewContext &CVCtx = OS.getContext().getCVContext();
+ unsigned FrameFuncStrTabOff = CVCtx.addToStringTable(FuncOS.str()).second;
+
+ // MSVC has only ever been observed to emit a MaxStackSize of zero.
+ unsigned MaxStackSize = 0;
+
+ // The FrameData record format is:
+ // ulittle32_t RvaStart;
+ // ulittle32_t CodeSize;
+ // ulittle32_t LocalSize;
+ // ulittle32_t ParamsSize;
+ // ulittle32_t MaxStackSize;
+ // ulittle32_t FrameFunc; // String table offset
+ // ulittle16_t PrologSize;
+ // ulittle16_t SavedRegsSize;
+ // ulittle32_t Flags;
+
+ OS.emitAbsoluteSymbolDiff(Label, FPO->Begin, 4); // RvaStart
+ OS.emitAbsoluteSymbolDiff(FPO->End, Label, 4); // CodeSize
+ OS.EmitIntValue(LocalSize, 4);
+ OS.EmitIntValue(FPO->ParamsSize, 4);
+ OS.EmitIntValue(MaxStackSize, 4);
+ OS.EmitIntValue(FrameFuncStrTabOff, 4); // FrameFunc
+ OS.emitAbsoluteSymbolDiff(FPO->PrologueEnd, Label, 2);
+ OS.EmitIntValue(SavedRegSize, 2);
+ OS.EmitIntValue(CurFlags, 4);
+}
+
+/// Compute and emit the real CodeView FrameData subsection.
+bool X86WinCOFFTargetStreamer::emitFPOData(const MCSymbol *ProcSym, SMLoc L) {
+ MCStreamer &OS = getStreamer();
+ MCContext &Ctx = OS.getContext();
+
+ auto I = AllFPOData.find(ProcSym);
+ if (I == AllFPOData.end()) {
+ Ctx.reportError(L, Twine("no FPO data found for symbol ") +
+ ProcSym->getName());
+ return true;
+ }
+ const FPOData *FPO = I->second.get();
+ assert(FPO->Begin && FPO->End && FPO->PrologueEnd && "missing FPO label");
+
+ MCSymbol *FrameBegin = Ctx.createTempSymbol(),
+ *FrameEnd = Ctx.createTempSymbol();
+
+ OS.EmitIntValue(unsigned(DebugSubsectionKind::FrameData), 4);
+ OS.emitAbsoluteSymbolDiff(FrameEnd, FrameBegin, 4);
+ OS.EmitLabel(FrameBegin);
+
+ // Start with the RVA of the function in question.
+ OS.EmitValue(MCSymbolRefExpr::create(FPO->Function,
+ MCSymbolRefExpr::VK_COFF_IMGREL32, Ctx),
+ 4);
+
+ // Emit a sequence of FrameData records.
+ FPOStateMachine FSM(FPO);
+
+ FSM.emitFrameDataRecord(OS, FPO->Begin);
+ for (const FPOInstruction &Inst : FPO->Instructions) {
+ switch (Inst.Op) {
+ case FPOInstruction::PushReg:
+ FSM.CurOffset += 4;
+ FSM.SavedRegSize += 4;
+ FSM.RegSaveOffsets.push_back({Inst.RegOrOffset, FSM.CurOffset});
+ break;
+ case FPOInstruction::SetFrame:
+ FSM.FrameReg = Inst.RegOrOffset;
+ FSM.FrameRegOff = FSM.CurOffset;
+ break;
+ case FPOInstruction::StackAlloc:
+ FSM.CurOffset += Inst.RegOrOffset;
+ FSM.LocalSize += Inst.RegOrOffset;
+ // No need to emit FrameData for stack allocations with a frame pointer.
+ if (FSM.FrameReg)
+ continue;
+ break;
+ }
+ FSM.emitFrameDataRecord(OS, Inst.Label);
+ }
+
+ OS.EmitValueToAlignment(4, 0);
+ OS.EmitLabel(FrameEnd);
+ return false;
+}
+
+MCTargetStreamer *llvm::createX86AsmTargetStreamer(MCStreamer &S,
+ formatted_raw_ostream &OS,
+ MCInstPrinter *InstPrinter,
+ bool IsVerboseAsm) {
+ // FIXME: This makes it so we textually assemble COFF directives on ELF.
+ // That's kind of nonsensical.
+ return new X86WinCOFFAsmTargetStreamer(S, OS, *InstPrinter);
+}
+
+MCTargetStreamer *
+llvm::createX86ObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
+ // No need to register a target streamer.
+ if (!STI.getTargetTriple().isOSBinFormatCOFF())
+ return nullptr;
+ // Registers itself to the MCStreamer.
+ return new X86WinCOFFTargetStreamer(S);
+}
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp
index dc15aeadaa6..9673d97b408 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -15,6 +15,7 @@
#include "X86AsmPrinter.h"
#include "InstPrinter/X86ATTInstPrinter.h"
#include "MCTargetDesc/X86BaseInfo.h"
+#include "MCTargetDesc/X86TargetStreamer.h"
#include "X86InstrInfo.h"
#include "X86MachineFunctionInfo.h"
#include "llvm/BinaryFormat/COFF.h"
@@ -51,9 +52,12 @@ bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
SMShadowTracker.startFunction(MF);
CodeEmitter.reset(TM.getTarget().createMCCodeEmitter(
- *MF.getSubtarget().getInstrInfo(), *MF.getSubtarget().getRegisterInfo(),
+ *Subtarget->getInstrInfo(), *Subtarget->getRegisterInfo(),
MF.getContext()));
+ EmitFPOData =
+ Subtarget->isTargetWin32() && MF.getMMI().getModule()->getCodeViewFlag();
+
SetupMachineFunction(MF);
if (Subtarget->isTargetCOFF()) {
@@ -72,10 +76,30 @@ bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// Emit the XRay table for this function.
emitXRayTable();
+ EmitFPOData = false;
+
// We didn't modify anything.
return false;
}
+void X86AsmPrinter::EmitFunctionBodyStart() {
+ if (EmitFPOData) {
+ X86TargetStreamer *XTS =
+ static_cast<X86TargetStreamer *>(OutStreamer->getTargetStreamer());
+ unsigned ParamsSize =
+ MF->getInfo<X86MachineFunctionInfo>()->getArgumentStackSize();
+ XTS->emitFPOProc(CurrentFnSym, ParamsSize);
+ }
+}
+
+void X86AsmPrinter::EmitFunctionBodyEnd() {
+ if (EmitFPOData) {
+ X86TargetStreamer *XTS =
+ static_cast<X86TargetStreamer *>(OutStreamer->getTargetStreamer());
+ XTS->emitFPOEndProc();
+ }
+}
+
/// printSymbolOperand - Print a raw symbol reference operand. This handles
/// jump tables, constant pools, global address and external symbols, all of
/// which print to a label with various suffixes for relocation types etc.
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.h b/llvm/lib/Target/X86/X86AsmPrinter.h
index d7c3b74d3ef..d1773913236 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.h
+++ b/llvm/lib/Target/X86/X86AsmPrinter.h
@@ -30,6 +30,7 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
StackMaps SM;
FaultMaps FM;
std::unique_ptr<MCCodeEmitter> CodeEmitter;
+ bool EmitFPOData = false;
// This utility class tracks the length of a stackmap instruction's 'shadow'.
// It is used by the X86AsmPrinter to ensure that the stackmap shadow
@@ -99,6 +100,9 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
// function.
void EmitXRayTable();
+ // Choose between emitting .seh_ directives and .cv_fpo_ directives.
+ void EmitSEHInstruction(const MachineInstr *MI);
+
public:
explicit X86AsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
@@ -137,6 +141,8 @@ public:
}
bool runOnMachineFunction(MachineFunction &F) override;
+ void EmitFunctionBodyStart() override;
+ void EmitFunctionBodyEnd() override;
};
} // end namespace llvm
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index e5140778e75..dd68cb154a5 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -924,6 +924,7 @@ void X86FrameLowering::BuildStackAlignAND(MachineBasicBlock &MBB,
Notes:
- .seh directives are emitted only for Windows 64 ABI
+ - .cv_fpo directives are emitted on win32 when emitting CodeView
- .cfi directives are emitted for all other ABIs
- for 32-bit code, substitute %e?? registers for %r??
*/
@@ -949,7 +950,9 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
bool HasFP = hasFP(MF);
bool IsWin64CC = STI.isCallingConvWin64(Fn->getCallingConv());
bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
- bool NeedsWinCFI = IsWin64Prologue && Fn->needsUnwindTableEntry();
+ bool NeedsWin64CFI = IsWin64Prologue && Fn->needsUnwindTableEntry();
+ bool NeedsWinFPO = STI.isTargetWin32() && MMI.getModule()->getCodeViewFlag();
+ bool NeedsWinCFI = NeedsWin64CFI || NeedsWinFPO;
bool NeedsDwarfCFI =
!IsWin64Prologue && (MMI.hasDebugInfo() || Fn->needsUnwindTableEntry());
unsigned FramePtr = TRI->getFrameRegister(MF);
@@ -958,7 +961,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
? getX86SubSuperRegister(FramePtr, 64) : FramePtr;
unsigned BasePtr = TRI->getBaseRegister();
bool HasWinCFI = false;
-
+
// Debug location must be unknown since the first debug location is used
// to determine the end of the prologue.
DebugLoc DL;
@@ -1120,6 +1123,15 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
BuildCFI(MBB, MBBI, DL, MCCFIInstruction::createDefCfaRegister(
nullptr, DwarfFramePtr));
}
+
+ if (NeedsWinFPO) {
+ // .cv_fpo_setframe $FramePtr
+ HasWinCFI = true;
+ BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SetFrame))
+ .addImm(FramePtr)
+ .addImm(0)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
}
} else {
assert(!IsFunclet && "funclets without FPs not yet implemented");
@@ -1155,8 +1167,9 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
if (NeedsWinCFI) {
HasWinCFI = true;
- BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg)).addImm(Reg).setMIFlag(
- MachineInstr::FrameSetup);
+ BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg))
+ .addImm(Reg)
+ .setMIFlag(MachineInstr::FrameSetup);
}
}
@@ -1295,6 +1308,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
// If this is not a funclet, emit the CFI describing our frame pointer.
if (NeedsWinCFI && !IsFunclet) {
+ assert(!NeedsWinFPO && "this setframe incompatible with FPO data");
HasWinCFI = true;
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SetFrame))
.addImm(FramePtr)
@@ -1333,6 +1347,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
Offset += SEHFrameOffset;
HasWinCFI = true;
+ assert(!NeedsWinFPO && "SEH_SaveXMM incompatible with FPO data");
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SaveXMM))
.addImm(Reg)
.addImm(Offset)
@@ -1534,7 +1549,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
Is64BitILP32 ? getX86SubSuperRegister(FramePtr, 64) : FramePtr;
bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
- bool NeedsWinCFI =
+ bool NeedsWin64CFI =
IsWin64Prologue && MF.getFunction()->needsUnwindTableEntry();
bool IsFunclet = MBBI == MBB.end() ? false : isFuncletReturnInstr(*MBBI);
@@ -1639,7 +1654,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
// into the epilogue. To cope with that, we insert an epilogue marker here,
// then replace it with a 'nop' if it ends up immediately after a CALL in the
// final emitted code.
- if (NeedsWinCFI && MF.hasWinCFI())
+ if (NeedsWin64CFI && MF.hasWinCFI())
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_Epilogue));
if (Terminator == MBB.end() || !isTailCallOpcode(Terminator->getOpcode())) {
diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp
index 36d81128acf..78e6e5f1b2e 100644
--- a/llvm/lib/Target/X86/X86MCInstLower.cpp
+++ b/llvm/lib/Target/X86/X86MCInstLower.cpp
@@ -15,6 +15,7 @@
#include "InstPrinter/X86ATTInstPrinter.h"
#include "InstPrinter/X86InstComments.h"
#include "MCTargetDesc/X86BaseInfo.h"
+#include "MCTargetDesc/X86TargetStreamer.h"
#include "Utils/X86ShuffleDecode.h"
#include "X86AsmPrinter.h"
#include "X86RegisterInfo.h"
@@ -1363,6 +1364,82 @@ static void printConstant(const Constant *COp, raw_ostream &CS) {
}
}
+void X86AsmPrinter::EmitSEHInstruction(const MachineInstr *MI) {
+ assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
+ assert(getSubtarget().isOSWindows() && "SEH_ instruction Windows only");
+ const X86RegisterInfo *RI =
+ MF->getSubtarget<X86Subtarget>().getRegisterInfo();
+
+ // Use the .cv_fpo directives if we're emitting CodeView on 32-bit x86.
+ if (EmitFPOData) {
+ X86TargetStreamer *XTS =
+ static_cast<X86TargetStreamer *>(OutStreamer->getTargetStreamer());
+ switch (MI->getOpcode()) {
+ case X86::SEH_PushReg:
+ XTS->emitFPOPushReg(MI->getOperand(0).getImm());
+ break;
+ case X86::SEH_StackAlloc:
+ XTS->emitFPOStackAlloc(MI->getOperand(0).getImm());
+ break;
+ case X86::SEH_SetFrame:
+ assert(MI->getOperand(1).getImm() == 0 &&
+ ".cv_fpo_setframe takes no offset");
+ XTS->emitFPOSetFrame(MI->getOperand(0).getImm());
+ break;
+ case X86::SEH_EndPrologue:
+ XTS->emitFPOEndPrologue();
+ break;
+ case X86::SEH_SaveReg:
+ case X86::SEH_SaveXMM:
+ case X86::SEH_PushFrame:
+ llvm_unreachable("SEH_ directive incompatible with FPO");
+ break;
+ default:
+ llvm_unreachable("expected SEH_ instruction");
+ }
+ return;
+ }
+
+ // Otherwise, use the .seh_ directives for all other Windows platforms.
+ switch (MI->getOpcode()) {
+ case X86::SEH_PushReg:
+ OutStreamer->EmitWinCFIPushReg(
+ RI->getSEHRegNum(MI->getOperand(0).getImm()));
+ break;
+
+ case X86::SEH_SaveReg:
+ OutStreamer->EmitWinCFISaveReg(RI->getSEHRegNum(MI->getOperand(0).getImm()),
+ MI->getOperand(1).getImm());
+ break;
+
+ case X86::SEH_SaveXMM:
+ OutStreamer->EmitWinCFISaveXMM(RI->getSEHRegNum(MI->getOperand(0).getImm()),
+ MI->getOperand(1).getImm());
+ break;
+
+ case X86::SEH_StackAlloc:
+ OutStreamer->EmitWinCFIAllocStack(MI->getOperand(0).getImm());
+ break;
+
+ case X86::SEH_SetFrame:
+ OutStreamer->EmitWinCFISetFrame(
+ RI->getSEHRegNum(MI->getOperand(0).getImm()),
+ MI->getOperand(1).getImm());
+ break;
+
+ case X86::SEH_PushFrame:
+ OutStreamer->EmitWinCFIPushFrame(MI->getOperand(0).getImm());
+ break;
+
+ case X86::SEH_EndPrologue:
+ OutStreamer->EmitWinCFIEndProlog();
+ break;
+
+ default:
+ llvm_unreachable("expected SEH_ instruction");
+ }
+}
+
void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
X86MCInstLower MCInstLowering(*MF, *this);
const X86RegisterInfo *RI = MF->getSubtarget<X86Subtarget>().getRegisterInfo();
@@ -1540,41 +1617,13 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
return;
case X86::SEH_PushReg:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFIPushReg(RI->getSEHRegNum(MI->getOperand(0).getImm()));
- return;
-
case X86::SEH_SaveReg:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFISaveReg(RI->getSEHRegNum(MI->getOperand(0).getImm()),
- MI->getOperand(1).getImm());
- return;
-
case X86::SEH_SaveXMM:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFISaveXMM(RI->getSEHRegNum(MI->getOperand(0).getImm()),
- MI->getOperand(1).getImm());
- return;
-
case X86::SEH_StackAlloc:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFIAllocStack(MI->getOperand(0).getImm());
- return;
-
case X86::SEH_SetFrame:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFISetFrame(RI->getSEHRegNum(MI->getOperand(0).getImm()),
- MI->getOperand(1).getImm());
- return;
-
case X86::SEH_PushFrame:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFIPushFrame(MI->getOperand(0).getImm());
- return;
-
case X86::SEH_EndPrologue:
- assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
- OutStreamer->EmitWinCFIEndProlog();
+ EmitSEHInstruction(MI);
return;
case X86::SEH_Epilogue: {
diff --git a/llvm/lib/Target/X86/X86Subtarget.h b/llvm/lib/Target/X86/X86Subtarget.h
index a8de6eaf1cc..5816e860e01 100644
--- a/llvm/lib/Target/X86/X86Subtarget.h
+++ b/llvm/lib/Target/X86/X86Subtarget.h
@@ -592,13 +592,9 @@ public:
bool isOSWindows() const { return TargetTriple.isOSWindows(); }
- bool isTargetWin64() const {
- return In64BitMode && TargetTriple.isOSWindows();
- }
+ bool isTargetWin64() const { return In64BitMode && isOSWindows(); }
- bool isTargetWin32() const {
- return !In64BitMode && (isTargetCygMing() || isTargetKnownWindowsMSVC());
- }
+ bool isTargetWin32() const { return !In64BitMode && isOSWindows(); }
bool isPICStyleGOT() const { return PICStyle == PICStyles::GOT; }
bool isPICStyleRIPRel() const { return PICStyle == PICStyles::RIPRel; }
OpenPOWER on IntegriCloud