summaryrefslogtreecommitdiff
path: root/lib/Target/X86/MCTargetDesc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/X86/MCTargetDesc')
-rw-r--r--lib/Target/X86/MCTargetDesc/CMakeLists.txt3
-rw-r--r--lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp26
-rw-r--r--lib/Target/X86/MCTargetDesc/X86BaseInfo.h22
-rw-r--r--lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp12
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp13
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp11
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp180
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h36
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp13
-rw-r--r--lib/Target/X86/MCTargetDesc/X86TargetStreamer.h34
-rw-r--r--lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp9
-rw-r--r--lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp31
-rw-r--r--lib/Target/X86/MCTargetDesc/X86WinCOFFTargetStreamer.cpp415
13 files changed, 686 insertions, 119 deletions
diff --git a/lib/Target/X86/MCTargetDesc/CMakeLists.txt b/lib/Target/X86/MCTargetDesc/CMakeLists.txt
index 33df9ec7dcde..8d0d9fa1215c 100644
--- a/lib/Target/X86/MCTargetDesc/CMakeLists.txt
+++ b/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/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
index 733eac7c0321..78385ae1877b 100644
--- a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
@@ -20,12 +20,9 @@
#include "llvm/MC/MCMachObjectWriter.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -76,7 +73,7 @@ class X86AsmBackend : public MCAsmBackend {
public:
X86AsmBackend(const Target &T, StringRef CPU)
: MCAsmBackend(), CPU(CPU),
- MaxNopLength((CPU == "slm") ? 7 : 15) {
+ MaxNopLength((CPU == "slm" || CPU == "silvermont") ? 7 : 15) {
HasNopl = CPU != "generic" && CPU != "i386" && CPU != "i486" &&
CPU != "i586" && CPU != "pentium" && CPU != "pentium-mmx" &&
CPU != "i686" && CPU != "k6" && CPU != "k6-2" && CPU != "k6-3" &&
@@ -389,7 +386,8 @@ public:
ELFX86_32AsmBackend(const Target &T, uint8_t OSABI, StringRef CPU)
: ELFX86AsmBackend(T, OSABI, CPU) {}
- MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
+ std::unique_ptr<MCObjectWriter>
+ createObjectWriter(raw_pwrite_stream &OS) const override {
return createX86ELFObjectWriter(OS, /*IsELF64*/ false, OSABI, ELF::EM_386);
}
};
@@ -399,7 +397,8 @@ public:
ELFX86_X32AsmBackend(const Target &T, uint8_t OSABI, StringRef CPU)
: ELFX86AsmBackend(T, OSABI, CPU) {}
- MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
+ std::unique_ptr<MCObjectWriter>
+ createObjectWriter(raw_pwrite_stream &OS) const override {
return createX86ELFObjectWriter(OS, /*IsELF64*/ false, OSABI,
ELF::EM_X86_64);
}
@@ -410,7 +409,8 @@ public:
ELFX86_IAMCUAsmBackend(const Target &T, uint8_t OSABI, StringRef CPU)
: ELFX86AsmBackend(T, OSABI, CPU) {}
- MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
+ std::unique_ptr<MCObjectWriter>
+ createObjectWriter(raw_pwrite_stream &OS) const override {
return createX86ELFObjectWriter(OS, /*IsELF64*/ false, OSABI,
ELF::EM_IAMCU);
}
@@ -421,7 +421,8 @@ public:
ELFX86_64AsmBackend(const Target &T, uint8_t OSABI, StringRef CPU)
: ELFX86AsmBackend(T, OSABI, CPU) {}
- MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
+ std::unique_ptr<MCObjectWriter>
+ createObjectWriter(raw_pwrite_stream &OS) const override {
return createX86ELFObjectWriter(OS, /*IsELF64*/ true, OSABI, ELF::EM_X86_64);
}
};
@@ -443,7 +444,8 @@ public:
.Default(MCAsmBackend::getFixupKind(Name));
}
- MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
+ std::unique_ptr<MCObjectWriter>
+ createObjectWriter(raw_pwrite_stream &OS) const override {
return createX86WinCOFFObjectWriter(OS, Is64Bit);
}
};
@@ -804,7 +806,8 @@ public:
StringRef CPU)
: DarwinX86AsmBackend(T, MRI, CPU, false) {}
- MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
+ std::unique_ptr<MCObjectWriter>
+ createObjectWriter(raw_pwrite_stream &OS) const override {
return createX86MachObjectWriter(OS, /*Is64Bit=*/false,
MachO::CPU_TYPE_I386,
MachO::CPU_SUBTYPE_I386_ALL);
@@ -824,7 +827,8 @@ public:
StringRef CPU, MachO::CPUSubTypeX86 st)
: DarwinX86AsmBackend(T, MRI, CPU, true), Subtype(st) {}
- MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
+ std::unique_ptr<MCObjectWriter>
+ createObjectWriter(raw_pwrite_stream &OS) const override {
return createX86MachObjectWriter(OS, /*Is64Bit=*/true,
MachO::CPU_TYPE_X86_64, Subtype);
}
diff --git a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
index d8953da4abb2..07cc488d047e 100644
--- a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
+++ b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
@@ -51,6 +51,18 @@ namespace X86 {
TO_ZERO = 3,
CUR_DIRECTION = 4
};
+
+ /// The constants to describe instr prefixes if there are
+ enum IPREFIXES {
+ IP_NO_PREFIX = 0,
+ IP_HAS_OP_SIZE = 1,
+ IP_HAS_AD_SIZE = 2,
+ IP_HAS_REPEAT_NE = 4,
+ IP_HAS_REPEAT = 8,
+ IP_HAS_LOCK = 16,
+ NO_SCHED_INFO = 32 // Don't add sched comment to the current instr because
+ // it was already added
+ };
} // end namespace X86;
/// X86II - This namespace holds all of the target specific flags that
@@ -356,13 +368,15 @@ namespace X86II {
// OpSize - OpSizeFixed implies instruction never needs a 0x66 prefix.
// OpSize16 means this is a 16-bit instruction and needs 0x66 prefix in
// 32-bit mode. OpSize32 means this is a 32-bit instruction needs a 0x66
- // prefix in 16-bit mode.
+ // prefix in 16-bit mode. OpSizeIgnore means that the instruction may
+ // take a optional 0x66 byte but should not emit with one.
OpSizeShift = 7,
OpSizeMask = 0x3 << OpSizeShift,
- OpSizeFixed = 0 << OpSizeShift,
- OpSize16 = 1 << OpSizeShift,
- OpSize32 = 2 << OpSizeShift,
+ OpSizeFixed = 0 << OpSizeShift,
+ OpSize16 = 1 << OpSizeShift,
+ OpSize32 = 2 << OpSizeShift,
+ OpSizeIgnore = 3 << OpSizeShift,
// AsSize - AdSizeX implies this instruction determines its need of 0x67
// prefix from a normal ModRM memory operand. The other types indicate that
diff --git a/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
index 4da4eebec038..4cdbae4d0d96 100644
--- a/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
@@ -15,6 +15,7 @@
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
@@ -297,10 +298,9 @@ unsigned X86ELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
return getRelocType32(Ctx, Modifier, getType32(Type), IsPCRel, Kind);
}
-MCObjectWriter *llvm::createX86ELFObjectWriter(raw_pwrite_stream &OS,
- bool IsELF64, uint8_t OSABI,
- uint16_t EMachine) {
- MCELFObjectTargetWriter *MOTW =
- new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
- return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true);
+std::unique_ptr<MCObjectWriter>
+llvm::createX86ELFObjectWriter(raw_pwrite_stream &OS, bool IsELF64,
+ uint8_t OSABI, uint16_t EMachine) {
+ auto MOTW = llvm::make_unique<X86ELFObjectWriter>(IsELF64, OSABI, EMachine);
+ return createELFObjectWriter(std::move(MOTW), OS, /*IsLittleEndian=*/true);
}
diff --git a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
index 1538a515f419..fa7c352a1b63 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
@@ -13,10 +13,7 @@
#include "X86MCAsmInfo.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
@@ -27,11 +24,11 @@ enum AsmWriterFlavorTy {
ATT = 0, Intel = 1
};
-static cl::opt<AsmWriterFlavorTy>
-AsmWriterFlavor("x86-asm-syntax", cl::init(ATT),
- cl::desc("Choose style of code to emit from X86 backend:"),
- cl::values(clEnumValN(ATT, "att", "Emit AT&T-style assembly"),
- clEnumValN(Intel, "intel", "Emit Intel-style assembly")));
+static cl::opt<AsmWriterFlavorTy> AsmWriterFlavor(
+ "x86-asm-syntax", cl::init(ATT), cl::Hidden,
+ cl::desc("Choose style of code to emit from X86 backend:"),
+ cl::values(clEnumValN(ATT, "att", "Emit AT&T-style assembly"),
+ clEnumValN(Intel, "intel", "Emit Intel-style assembly")));
static cl::opt<bool>
MarkedJTDataRegions("mark-data-regions", cl::init(true),
diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 10e2bbc64d3c..a7059c6914df 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -380,7 +380,7 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
return X86::reloc_riprel_4byte_movq_load;
case X86::CALL64m:
case X86::JMP64m:
- case X86::TEST64rm:
+ case X86::TEST64mr:
case X86::ADC64rm:
case X86::ADD64rm:
case X86::AND64rm:
@@ -1108,7 +1108,7 @@ bool X86MCCodeEmitter::emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
EmitByte(0x66, CurByte, OS);
// Emit the LOCK opcode prefix.
- if (TSFlags & X86II::LOCK)
+ if (TSFlags & X86II::LOCK || MI.getFlags() & X86::IP_HAS_LOCK)
EmitByte(0xF0, CurByte, OS);
switch (TSFlags & X86II::OpPrefixMask) {
@@ -1130,6 +1130,8 @@ bool X86MCCodeEmitter::emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
EmitByte(0x40 | REX, CurByte, OS);
Ret = true;
}
+ } else {
+ assert(!(TSFlags & X86II::REX_W) && "REX.W requires 64bit mode.");
}
// 0x0F escape code must be emitted just before the opcode.
@@ -1159,6 +1161,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
unsigned Opcode = MI.getOpcode();
const MCInstrDesc &Desc = MCII.get(Opcode);
uint64_t TSFlags = Desc.TSFlags;
+ unsigned Flags = MI.getFlags();
// Pseudo instructions don't get encoded.
if ((TSFlags & X86II::FormMask) == X86II::Pseudo)
@@ -1194,8 +1197,10 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
MI, OS);
// Emit the repeat opcode prefix as needed.
- if (TSFlags & X86II::REP)
+ if (TSFlags & X86II::REP || Flags & X86::IP_HAS_REPEAT)
EmitByte(0xF3, CurByte, OS);
+ if (Flags & X86::IP_HAS_REPEAT_NE)
+ EmitByte(0xF2, CurByte, OS);
// Emit the address size opcode prefix as needed.
bool need_address_override;
diff --git a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
index 22cb0fac33cb..cdd43478baed 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
@@ -16,6 +16,7 @@
#include "InstPrinter/X86IntelInstPrinter.h"
#include "X86MCAsmInfo.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -72,52 +73,128 @@ void X86_MC::initLLVMToSEHAndCVRegMapping(MCRegisterInfo *MRI) {
MRI->mapLLVMRegToSEHReg(Reg, SEH);
}
- // These CodeView registers are numbered sequentially starting at value 1.
- static const MCPhysReg LowCVRegs[] = {
- X86::AL, X86::CL, X86::DL, X86::BL, X86::AH, X86::CH,
- X86::DH, X86::BH, X86::AX, X86::CX, X86::DX, X86::BX,
- X86::SP, X86::BP, X86::SI, X86::DI, X86::EAX, X86::ECX,
- X86::EDX, X86::EBX, X86::ESP, X86::EBP, X86::ESI, X86::EDI,
- };
- unsigned CVLowRegStart = 1;
- for (unsigned I = 0; I < array_lengthof(LowCVRegs); ++I)
- MRI->mapLLVMRegToCVReg(LowCVRegs[I], I + CVLowRegStart);
-
- MRI->mapLLVMRegToCVReg(X86::EFLAGS, 34);
+ // Mapping from CodeView to MC register id.
+ static const struct {
+ codeview::RegisterId CVReg;
+ MCPhysReg Reg;
+ } RegMap[] = {
+ { codeview::RegisterId::AL, X86::AL},
+ { codeview::RegisterId::CL, X86::CL},
+ { codeview::RegisterId::DL, X86::DL},
+ { codeview::RegisterId::BL, X86::BL},
+ { codeview::RegisterId::AH, X86::AH},
+ { codeview::RegisterId::CH, X86::CH},
+ { codeview::RegisterId::DH, X86::DH},
+ { codeview::RegisterId::BH, X86::BH},
+ { codeview::RegisterId::AX, X86::AX},
+ { codeview::RegisterId::CX, X86::CX},
+ { codeview::RegisterId::DX, X86::DX},
+ { codeview::RegisterId::BX, X86::BX},
+ { codeview::RegisterId::SP, X86::SP},
+ { codeview::RegisterId::BP, X86::BP},
+ { codeview::RegisterId::SI, X86::SI},
+ { codeview::RegisterId::DI, X86::DI},
+ { codeview::RegisterId::EAX, X86::EAX},
+ { codeview::RegisterId::ECX, X86::ECX},
+ { codeview::RegisterId::EDX, X86::EDX},
+ { codeview::RegisterId::EBX, X86::EBX},
+ { codeview::RegisterId::ESP, X86::ESP},
+ { codeview::RegisterId::EBP, X86::EBP},
+ { codeview::RegisterId::ESI, X86::ESI},
+ { codeview::RegisterId::EDI, X86::EDI},
- // The x87 registers start at 128 and are numbered sequentially.
- unsigned FP0Start = 128;
- for (unsigned I = 0; I < 8; ++I)
- MRI->mapLLVMRegToCVReg(X86::FP0 + I, FP0Start + I);
+ { codeview::RegisterId::EFLAGS, X86::EFLAGS},
- // The low 8 XMM registers start at 154 and are numbered sequentially.
- unsigned CVXMM0Start = 154;
- for (unsigned I = 0; I < 8; ++I)
- MRI->mapLLVMRegToCVReg(X86::XMM0 + I, CVXMM0Start + I);
+ { codeview::RegisterId::ST0, X86::FP0},
+ { codeview::RegisterId::ST1, X86::FP1},
+ { codeview::RegisterId::ST2, X86::FP2},
+ { codeview::RegisterId::ST3, X86::FP3},
+ { codeview::RegisterId::ST4, X86::FP4},
+ { codeview::RegisterId::ST5, X86::FP5},
+ { codeview::RegisterId::ST6, X86::FP6},
+ { codeview::RegisterId::ST7, X86::FP7},
- // The high 8 XMM registers start at 252 and are numbered sequentially.
- unsigned CVXMM8Start = 252;
- for (unsigned I = 0; I < 8; ++I)
- MRI->mapLLVMRegToCVReg(X86::XMM8 + I, CVXMM8Start + I);
+ { codeview::RegisterId::XMM0, X86::XMM0},
+ { codeview::RegisterId::XMM1, X86::XMM1},
+ { codeview::RegisterId::XMM2, X86::XMM2},
+ { codeview::RegisterId::XMM3, X86::XMM3},
+ { codeview::RegisterId::XMM4, X86::XMM4},
+ { codeview::RegisterId::XMM5, X86::XMM5},
+ { codeview::RegisterId::XMM6, X86::XMM6},
+ { codeview::RegisterId::XMM7, X86::XMM7},
- // FIXME: XMM16 and above from AVX512 not yet documented.
+ { codeview::RegisterId::XMM8, X86::XMM8},
+ { codeview::RegisterId::XMM9, X86::XMM9},
+ { codeview::RegisterId::XMM10, X86::XMM10},
+ { codeview::RegisterId::XMM11, X86::XMM11},
+ { codeview::RegisterId::XMM12, X86::XMM12},
+ { codeview::RegisterId::XMM13, X86::XMM13},
+ { codeview::RegisterId::XMM14, X86::XMM14},
+ { codeview::RegisterId::XMM15, X86::XMM15},
- // AMD64 registers start at 324 and count up.
- unsigned CVX64RegStart = 324;
- static const MCPhysReg CVX64Regs[] = {
- X86::SIL, X86::DIL, X86::BPL, X86::SPL, X86::RAX, X86::RBX,
- X86::RCX, X86::RDX, X86::RSI, X86::RDI, X86::RBP, X86::RSP,
- X86::R8, X86::R9, X86::R10, X86::R11, X86::R12, X86::R13,
- X86::R14, X86::R15, X86::R8B, X86::R9B, X86::R10B, X86::R11B,
- X86::R12B, X86::R13B, X86::R14B, X86::R15B, X86::R8W, X86::R9W,
- X86::R10W, X86::R11W, X86::R12W, X86::R13W, X86::R14W, X86::R15W,
- X86::R8D, X86::R9D, X86::R10D, X86::R11D, X86::R12D, X86::R13D,
- X86::R14D, X86::R15D, X86::YMM0, X86::YMM1, X86::YMM2, X86::YMM3,
- X86::YMM4, X86::YMM5, X86::YMM6, X86::YMM7, X86::YMM8, X86::YMM9,
- X86::YMM10, X86::YMM11, X86::YMM12, X86::YMM13, X86::YMM14, X86::YMM15,
+ { codeview::RegisterId::SIL, X86::SIL},
+ { codeview::RegisterId::DIL, X86::DIL},
+ { codeview::RegisterId::BPL, X86::BPL},
+ { codeview::RegisterId::SPL, X86::SPL},
+ { codeview::RegisterId::RAX, X86::RAX},
+ { codeview::RegisterId::RBX, X86::RBX},
+ { codeview::RegisterId::RCX, X86::RCX},
+ { codeview::RegisterId::RDX, X86::RDX},
+ { codeview::RegisterId::RSI, X86::RSI},
+ { codeview::RegisterId::RDI, X86::RDI},
+ { codeview::RegisterId::RBP, X86::RBP},
+ { codeview::RegisterId::RSP, X86::RSP},
+ { codeview::RegisterId::R8, X86::R8},
+ { codeview::RegisterId::R9, X86::R9},
+ { codeview::RegisterId::R10, X86::R10},
+ { codeview::RegisterId::R11, X86::R11},
+ { codeview::RegisterId::R12, X86::R12},
+ { codeview::RegisterId::R13, X86::R13},
+ { codeview::RegisterId::R14, X86::R14},
+ { codeview::RegisterId::R15, X86::R15},
+ { codeview::RegisterId::R8B, X86::R8B},
+ { codeview::RegisterId::R9B, X86::R9B},
+ { codeview::RegisterId::R10B, X86::R10B},
+ { codeview::RegisterId::R11B, X86::R11B},
+ { codeview::RegisterId::R12B, X86::R12B},
+ { codeview::RegisterId::R13B, X86::R13B},
+ { codeview::RegisterId::R14B, X86::R14B},
+ { codeview::RegisterId::R15B, X86::R15B},
+ { codeview::RegisterId::R8W, X86::R8W},
+ { codeview::RegisterId::R9W, X86::R9W},
+ { codeview::RegisterId::R10W, X86::R10W},
+ { codeview::RegisterId::R11W, X86::R11W},
+ { codeview::RegisterId::R12W, X86::R12W},
+ { codeview::RegisterId::R13W, X86::R13W},
+ { codeview::RegisterId::R14W, X86::R14W},
+ { codeview::RegisterId::R15W, X86::R15W},
+ { codeview::RegisterId::R8D, X86::R8D},
+ { codeview::RegisterId::R9D, X86::R9D},
+ { codeview::RegisterId::R10D, X86::R10D},
+ { codeview::RegisterId::R11D, X86::R11D},
+ { codeview::RegisterId::R12D, X86::R12D},
+ { codeview::RegisterId::R13D, X86::R13D},
+ { codeview::RegisterId::R14D, X86::R14D},
+ { codeview::RegisterId::R15D, X86::R15D},
+ { codeview::RegisterId::AMD64_YMM0, X86::YMM0},
+ { codeview::RegisterId::AMD64_YMM1, X86::YMM1},
+ { codeview::RegisterId::AMD64_YMM2, X86::YMM2},
+ { codeview::RegisterId::AMD64_YMM3, X86::YMM3},
+ { codeview::RegisterId::AMD64_YMM4, X86::YMM4},
+ { codeview::RegisterId::AMD64_YMM5, X86::YMM5},
+ { codeview::RegisterId::AMD64_YMM6, X86::YMM6},
+ { codeview::RegisterId::AMD64_YMM7, X86::YMM7},
+ { codeview::RegisterId::AMD64_YMM8, X86::YMM8},
+ { codeview::RegisterId::AMD64_YMM9, X86::YMM9},
+ { codeview::RegisterId::AMD64_YMM10, X86::YMM10},
+ { codeview::RegisterId::AMD64_YMM11, X86::YMM11},
+ { codeview::RegisterId::AMD64_YMM12, X86::YMM12},
+ { codeview::RegisterId::AMD64_YMM13, X86::YMM13},
+ { codeview::RegisterId::AMD64_YMM14, X86::YMM14},
+ { codeview::RegisterId::AMD64_YMM15, X86::YMM15},
};
- for (unsigned I = 0; I < array_lengthof(CVX64Regs); ++I)
- MRI->mapLLVMRegToCVReg(CVX64Regs[I], CVX64RegStart + I);
+ for (unsigned I = 0; I < array_lengthof(RegMap); ++I)
+ MRI->mapLLVMRegToCVReg(RegMap[I].Reg, static_cast<int>(RegMap[I].CVReg));
}
MCSubtargetInfo *X86_MC::createX86MCSubtargetInfo(const Triple &TT,
@@ -198,18 +275,6 @@ static MCAsmInfo *createX86MCAsmInfo(const MCRegisterInfo &MRI,
return MAI;
}
-static void adjustCodeGenOpts(const Triple &TT, Reloc::Model RM,
- CodeModel::Model &CM) {
- bool is64Bit = TT.getArch() == Triple::x86_64;
-
- // For static codegen, if we're not already set, use Small codegen.
- if (CM == CodeModel::Default)
- CM = CodeModel::Small;
- else if (CM == CodeModel::JITDefault)
- // 64-bit JIT places everything in the same buffer except external funcs.
- CM = is64Bit ? CodeModel::Large : CodeModel::Small;
-}
-
static MCInstPrinter *createX86MCInstPrinter(const Triple &T,
unsigned SyntaxVariant,
const MCAsmInfo &MAI,
@@ -238,9 +303,6 @@ extern "C" void LLVMInitializeX86TargetMC() {
// Register the MC asm info.
RegisterMCAsmInfoFn X(*T, createX86MCAsmInfo);
- // Register the MC codegen info.
- RegisterMCAdjustCodeGenOptsFn Y(*T, adjustCodeGenOpts);
-
// Register the MC instruction info.
TargetRegistry::RegisterMCInstrInfo(*T, createX86MCInstrInfo);
@@ -257,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/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
index f73e734b9b0e..c5859b600ad2 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
+++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
@@ -77,25 +77,41 @@ 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.
///
/// Takes ownership of \p AB and \p CE.
-MCStreamer *createX86WinCOFFStreamer(MCContext &C, MCAsmBackend &AB,
- raw_pwrite_stream &OS, MCCodeEmitter *CE,
- bool RelaxAll, bool IncrementalLinkerCompatible);
+MCStreamer *createX86WinCOFFStreamer(MCContext &C,
+ std::unique_ptr<MCAsmBackend> &&AB,
+ raw_pwrite_stream &OS,
+ std::unique_ptr<MCCodeEmitter> &&CE,
+ bool RelaxAll,
+ bool IncrementalLinkerCompatible);
/// Construct an X86 Mach-O object writer.
-MCObjectWriter *createX86MachObjectWriter(raw_pwrite_stream &OS, bool Is64Bit,
- uint32_t CPUType,
- uint32_t CPUSubtype);
+std::unique_ptr<MCObjectWriter> createX86MachObjectWriter(raw_pwrite_stream &OS,
+ bool Is64Bit,
+ uint32_t CPUType,
+ uint32_t CPUSubtype);
/// Construct an X86 ELF object writer.
-MCObjectWriter *createX86ELFObjectWriter(raw_pwrite_stream &OS, bool IsELF64,
- uint8_t OSABI, uint16_t EMachine);
+std::unique_ptr<MCObjectWriter> createX86ELFObjectWriter(raw_pwrite_stream &OS,
+ bool IsELF64,
+ uint8_t OSABI,
+ uint16_t EMachine);
/// Construct an X86 Win COFF object writer.
-MCObjectWriter *createX86WinCOFFObjectWriter(raw_pwrite_stream &OS,
- bool Is64Bit);
+std::unique_ptr<MCObjectWriter>
+createX86WinCOFFObjectWriter(raw_pwrite_stream &OS, bool Is64Bit);
/// Returns the sub or super register of a specific X86 register.
/// e.g. getX86SubSuperRegister(X86::EAX, 16) returns X86::AX.
diff --git a/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
index 8f2017e990c5..965f7de809b3 100644
--- a/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp
@@ -597,11 +597,10 @@ void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
}
-MCObjectWriter *llvm::createX86MachObjectWriter(raw_pwrite_stream &OS,
- bool Is64Bit, uint32_t CPUType,
- uint32_t CPUSubtype) {
- return createMachObjectWriter(new X86MachObjectWriter(Is64Bit,
- CPUType,
- CPUSubtype),
- OS, /*IsLittleEndian=*/true);
+std::unique_ptr<MCObjectWriter>
+llvm::createX86MachObjectWriter(raw_pwrite_stream &OS, bool Is64Bit,
+ uint32_t CPUType, uint32_t CPUSubtype) {
+ return createMachObjectWriter(
+ llvm::make_unique<X86MachObjectWriter>(Is64Bit, CPUType, CPUSubtype), OS,
+ /*IsLittleEndian=*/true);
}
diff --git a/lib/Target/X86/MCTargetDesc/X86TargetStreamer.h b/lib/Target/X86/MCTargetDesc/X86TargetStreamer.h
new file mode 100644
index 000000000000..8d38cd32b82c
--- /dev/null
+++ b/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/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
index 807f7a6ddb19..5139bb46b561 100644
--- a/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp
@@ -13,6 +13,7 @@
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCWinCOFFObjectWriter.h"
#include "llvm/Support/ErrorHandling.h"
@@ -104,8 +105,8 @@ unsigned X86WinCOFFObjectWriter::getRelocType(MCContext &Ctx,
llvm_unreachable("Unsupported COFF machine type.");
}
-MCObjectWriter *llvm::createX86WinCOFFObjectWriter(raw_pwrite_stream &OS,
- bool Is64Bit) {
- MCWinCOFFObjectTargetWriter *MOTW = new X86WinCOFFObjectWriter(Is64Bit);
- return createWinCOFFObjectWriter(MOTW, OS);
+std::unique_ptr<MCObjectWriter>
+llvm::createX86WinCOFFObjectWriter(raw_pwrite_stream &OS, bool Is64Bit) {
+ auto MOTW = llvm::make_unique<X86WinCOFFObjectWriter>(Is64Bit);
+ return createWinCOFFObjectWriter(std::move(MOTW), OS);
}
diff --git a/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp b/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp
index d04511873b46..5b1357ae4a7b 100644
--- a/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp
@@ -8,6 +8,9 @@
//===----------------------------------------------------------------------===//
#include "X86MCTargetDesc.h"
+#include "X86TargetStreamer.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCWin64EH.h"
#include "llvm/MC/MCWinCOFFStreamer.h"
@@ -17,17 +20,18 @@ namespace {
class X86WinCOFFStreamer : public MCWinCOFFStreamer {
Win64EH::UnwindEmitter EHStreamer;
public:
- X86WinCOFFStreamer(MCContext &C, MCAsmBackend &AB, MCCodeEmitter *CE,
- raw_pwrite_stream &OS)
- : MCWinCOFFStreamer(C, AB, *CE, OS) {}
+ X86WinCOFFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> AB,
+ std::unique_ptr<MCCodeEmitter> CE, raw_pwrite_stream &OS)
+ : MCWinCOFFStreamer(C, std::move(AB), std::move(CE), OS) {}
- void EmitWinEHHandlerData() override;
+ void EmitWinEHHandlerData(SMLoc Loc) override;
void EmitWindowsUnwindTables() override;
+ void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc) override;
void FinishImpl() override;
};
-void X86WinCOFFStreamer::EmitWinEHHandlerData() {
- MCStreamer::EmitWinEHHandlerData();
+void X86WinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) {
+ MCStreamer::EmitWinEHHandlerData(Loc);
// We have to emit the unwind info now, because this directive
// actually switches to the .xdata section!
@@ -40,6 +44,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();
@@ -48,11 +58,14 @@ void X86WinCOFFStreamer::FinishImpl() {
}
}
-MCStreamer *llvm::createX86WinCOFFStreamer(MCContext &C, MCAsmBackend &AB,
+MCStreamer *llvm::createX86WinCOFFStreamer(MCContext &C,
+ std::unique_ptr<MCAsmBackend> &&AB,
raw_pwrite_stream &OS,
- MCCodeEmitter *CE, bool RelaxAll,
+ std::unique_ptr<MCCodeEmitter> &&CE,
+ bool RelaxAll,
bool IncrementalLinkerCompatible) {
- X86WinCOFFStreamer *S = new X86WinCOFFStreamer(C, AB, CE, OS);
+ X86WinCOFFStreamer *S =
+ new X86WinCOFFStreamer(C, std::move(AB), std::move(CE), OS);
S->getAssembler().setRelaxAll(RelaxAll);
S->getAssembler().setIncrementalLinkerCompatible(IncrementalLinkerCompatible);
return S;
diff --git a/lib/Target/X86/MCTargetDesc/X86WinCOFFTargetStreamer.cpp b/lib/Target/X86/MCTargetDesc/X86WinCOFFTargetStreamer.cpp
new file mode 100644
index 000000000000..093dab4f2f96
--- /dev/null
+++ b/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);
+}