Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,11 @@
add_llvm_library(LLVMX86Desc
X86AsmBackend.cpp
X86MCTargetDesc.cpp
X86MCAsmInfo.cpp
X86MCCodeEmitter.cpp
X86MachObjectWriter.cpp
X86ELFObjectWriter.cpp
X86WinCOFFObjectWriter.cpp
X86WinCOFFStreamer.cpp
X86WinCOFFTargetStreamer.cpp
)

View File

@@ -0,0 +1,23 @@
;===- ./lib/Target/X86/MCTargetDesc/LLVMBuild.txt --------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Library
name = X86Desc
parent = X86
required_libraries = MC MCDisassembler Object Support X86AsmPrinter X86Info
add_to_library_groups = X86

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,306 @@
//===-- X86ELFObjectWriter.cpp - X86 ELF Writer ---------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/X86FixupKinds.h"
#include "MCTargetDesc/X86MCTargetDesc.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#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>
#include <cstdint>
using namespace llvm;
namespace {
class X86ELFObjectWriter : public MCELFObjectTargetWriter {
public:
X86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine);
~X86ELFObjectWriter() override = default;
protected:
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
const MCFixup &Fixup, bool IsPCRel) const override;
};
} // end anonymous namespace
X86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI,
uint16_t EMachine)
: MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
// Only i386 and IAMCU use Rel instead of RelA.
/*HasRelocationAddend*/
(EMachine != ELF::EM_386) &&
(EMachine != ELF::EM_IAMCU)) {}
enum X86_64RelType { RT64_64, RT64_32, RT64_32S, RT64_16, RT64_8 };
static X86_64RelType getType64(unsigned Kind,
MCSymbolRefExpr::VariantKind &Modifier,
bool &IsPCRel) {
switch (Kind) {
default:
llvm_unreachable("Unimplemented");
case X86::reloc_global_offset_table8:
Modifier = MCSymbolRefExpr::VK_GOT;
IsPCRel = true;
return RT64_64;
case FK_Data_8:
return RT64_64;
case X86::reloc_signed_4byte:
case X86::reloc_signed_4byte_relax:
if (Modifier == MCSymbolRefExpr::VK_None && !IsPCRel)
return RT64_32S;
return RT64_32;
case X86::reloc_global_offset_table:
Modifier = MCSymbolRefExpr::VK_GOT;
IsPCRel = true;
return RT64_32;
case FK_Data_4:
case FK_PCRel_4:
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_relax:
case X86::reloc_riprel_4byte_relax_rex:
case X86::reloc_riprel_4byte_movq_load:
return RT64_32;
case FK_PCRel_2:
case FK_Data_2:
return RT64_16;
case FK_PCRel_1:
case FK_Data_1:
return RT64_8;
}
}
static void checkIs32(MCContext &Ctx, SMLoc Loc, X86_64RelType Type) {
if (Type != RT64_32)
Ctx.reportError(Loc,
"32 bit reloc applied to a field with a different size");
}
static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
MCSymbolRefExpr::VariantKind Modifier,
X86_64RelType Type, bool IsPCRel,
unsigned Kind) {
switch (Modifier) {
default:
llvm_unreachable("Unimplemented");
case MCSymbolRefExpr::VK_None:
case MCSymbolRefExpr::VK_X86_ABS8:
switch (Type) {
case RT64_64:
return IsPCRel ? ELF::R_X86_64_PC64 : ELF::R_X86_64_64;
case RT64_32:
return IsPCRel ? ELF::R_X86_64_PC32 : ELF::R_X86_64_32;
case RT64_32S:
return ELF::R_X86_64_32S;
case RT64_16:
return IsPCRel ? ELF::R_X86_64_PC16 : ELF::R_X86_64_16;
case RT64_8:
return IsPCRel ? ELF::R_X86_64_PC8 : ELF::R_X86_64_8;
}
case MCSymbolRefExpr::VK_GOT:
switch (Type) {
case RT64_64:
return IsPCRel ? ELF::R_X86_64_GOTPC64 : ELF::R_X86_64_GOT64;
case RT64_32:
return IsPCRel ? ELF::R_X86_64_GOTPC32 : ELF::R_X86_64_GOT32;
case RT64_32S:
case RT64_16:
case RT64_8:
llvm_unreachable("Unimplemented");
}
case MCSymbolRefExpr::VK_GOTOFF:
assert(Type == RT64_64);
assert(!IsPCRel);
return ELF::R_X86_64_GOTOFF64;
case MCSymbolRefExpr::VK_TPOFF:
assert(!IsPCRel);
switch (Type) {
case RT64_64:
return ELF::R_X86_64_TPOFF64;
case RT64_32:
return ELF::R_X86_64_TPOFF32;
case RT64_32S:
case RT64_16:
case RT64_8:
llvm_unreachable("Unimplemented");
}
case MCSymbolRefExpr::VK_DTPOFF:
assert(!IsPCRel);
switch (Type) {
case RT64_64:
return ELF::R_X86_64_DTPOFF64;
case RT64_32:
return ELF::R_X86_64_DTPOFF32;
case RT64_32S:
case RT64_16:
case RT64_8:
llvm_unreachable("Unimplemented");
}
case MCSymbolRefExpr::VK_SIZE:
assert(!IsPCRel);
switch (Type) {
case RT64_64:
return ELF::R_X86_64_SIZE64;
case RT64_32:
return ELF::R_X86_64_SIZE32;
case RT64_32S:
case RT64_16:
case RT64_8:
llvm_unreachable("Unimplemented");
}
case MCSymbolRefExpr::VK_TLSCALL:
return ELF::R_X86_64_TLSDESC_CALL;
case MCSymbolRefExpr::VK_TLSDESC:
return ELF::R_X86_64_GOTPC32_TLSDESC;
case MCSymbolRefExpr::VK_TLSGD:
checkIs32(Ctx, Loc, Type);
return ELF::R_X86_64_TLSGD;
case MCSymbolRefExpr::VK_GOTTPOFF:
checkIs32(Ctx, Loc, Type);
return ELF::R_X86_64_GOTTPOFF;
case MCSymbolRefExpr::VK_TLSLD:
checkIs32(Ctx, Loc, Type);
return ELF::R_X86_64_TLSLD;
case MCSymbolRefExpr::VK_PLT:
checkIs32(Ctx, Loc, Type);
return ELF::R_X86_64_PLT32;
case MCSymbolRefExpr::VK_GOTPCREL:
checkIs32(Ctx, Loc, Type);
// Older versions of ld.bfd/ld.gold/lld
// do not support GOTPCRELX/REX_GOTPCRELX,
// and we want to keep back-compatibility.
if (!Ctx.getAsmInfo()->canRelaxRelocations())
return ELF::R_X86_64_GOTPCREL;
switch (Kind) {
default:
return ELF::R_X86_64_GOTPCREL;
case X86::reloc_riprel_4byte_relax:
return ELF::R_X86_64_GOTPCRELX;
case X86::reloc_riprel_4byte_relax_rex:
case X86::reloc_riprel_4byte_movq_load:
return ELF::R_X86_64_REX_GOTPCRELX;
}
}
}
enum X86_32RelType { RT32_32, RT32_16, RT32_8 };
static X86_32RelType getType32(X86_64RelType T) {
switch (T) {
case RT64_64:
llvm_unreachable("Unimplemented");
case RT64_32:
case RT64_32S:
return RT32_32;
case RT64_16:
return RT32_16;
case RT64_8:
return RT32_8;
}
llvm_unreachable("unexpected relocation type!");
}
static unsigned getRelocType32(MCContext &Ctx,
MCSymbolRefExpr::VariantKind Modifier,
X86_32RelType Type, bool IsPCRel,
unsigned Kind) {
switch (Modifier) {
default:
llvm_unreachable("Unimplemented");
case MCSymbolRefExpr::VK_None:
case MCSymbolRefExpr::VK_X86_ABS8:
switch (Type) {
case RT32_32:
return IsPCRel ? ELF::R_386_PC32 : ELF::R_386_32;
case RT32_16:
return IsPCRel ? ELF::R_386_PC16 : ELF::R_386_16;
case RT32_8:
return IsPCRel ? ELF::R_386_PC8 : ELF::R_386_8;
}
case MCSymbolRefExpr::VK_GOT:
assert(Type == RT32_32);
if (IsPCRel)
return ELF::R_386_GOTPC;
// Older versions of ld.bfd/ld.gold/lld do not support R_386_GOT32X and we
// want to maintain compatibility.
if (!Ctx.getAsmInfo()->canRelaxRelocations())
return ELF::R_386_GOT32;
return Kind == X86::reloc_signed_4byte_relax ? ELF::R_386_GOT32X
: ELF::R_386_GOT32;
case MCSymbolRefExpr::VK_GOTOFF:
assert(Type == RT32_32);
assert(!IsPCRel);
return ELF::R_386_GOTOFF;
case MCSymbolRefExpr::VK_TPOFF:
assert(Type == RT32_32);
assert(!IsPCRel);
return ELF::R_386_TLS_LE_32;
case MCSymbolRefExpr::VK_DTPOFF:
assert(Type == RT32_32);
assert(!IsPCRel);
return ELF::R_386_TLS_LDO_32;
case MCSymbolRefExpr::VK_TLSGD:
assert(Type == RT32_32);
assert(!IsPCRel);
return ELF::R_386_TLS_GD;
case MCSymbolRefExpr::VK_GOTTPOFF:
assert(Type == RT32_32);
assert(!IsPCRel);
return ELF::R_386_TLS_IE_32;
case MCSymbolRefExpr::VK_PLT:
assert(Type == RT32_32);
return ELF::R_386_PLT32;
case MCSymbolRefExpr::VK_INDNTPOFF:
assert(Type == RT32_32);
assert(!IsPCRel);
return ELF::R_386_TLS_IE;
case MCSymbolRefExpr::VK_NTPOFF:
assert(Type == RT32_32);
assert(!IsPCRel);
return ELF::R_386_TLS_LE;
case MCSymbolRefExpr::VK_GOTNTPOFF:
assert(Type == RT32_32);
assert(!IsPCRel);
return ELF::R_386_TLS_GOTIE;
case MCSymbolRefExpr::VK_TLSLDM:
assert(Type == RT32_32);
assert(!IsPCRel);
return ELF::R_386_TLS_LDM;
}
}
unsigned X86ELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
const MCFixup &Fixup,
bool IsPCRel) const {
MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
unsigned Kind = Fixup.getKind();
X86_64RelType Type = getType64(Kind, Modifier, IsPCRel);
if (getEMachine() == ELF::EM_X86_64)
return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel, Kind);
assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) &&
"Unsupported ELF machine type.");
return getRelocType32(Ctx, Modifier, getType32(Type), IsPCRel, Kind);
}
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);
}

View File

@@ -0,0 +1,40 @@
//===-- X86FixupKinds.h - X86 Specific Fixup Entries ------------*- 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_X86FIXUPKINDS_H
#define LLVM_LIB_TARGET_X86_MCTARGETDESC_X86FIXUPKINDS_H
#include "llvm/MC/MCFixup.h"
namespace llvm {
namespace X86 {
enum Fixups {
reloc_riprel_4byte = FirstTargetFixupKind, // 32-bit rip-relative
reloc_riprel_4byte_movq_load, // 32-bit rip-relative in movq
reloc_riprel_4byte_relax, // 32-bit rip-relative in relaxable
// instruction
reloc_riprel_4byte_relax_rex, // 32-bit rip-relative in relaxable
// instruction with rex prefix
reloc_signed_4byte, // 32-bit signed. Unlike FK_Data_4
// this will be sign extended at
// runtime.
reloc_signed_4byte_relax, // like reloc_signed_4byte, but
// in a relaxable instruction.
reloc_global_offset_table, // 32-bit, relative to the start
// of the instruction. Used only
// for _GLOBAL_OFFSET_TABLE_.
reloc_global_offset_table8, // 64-bit variant.
// Marker
LastTargetFixupKind,
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
};
}
}
#endif

View File

@@ -0,0 +1,168 @@
//===-- X86MCAsmInfo.cpp - X86 asm properties -----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the X86MCAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#include "X86MCAsmInfo.h"
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
enum AsmWriterFlavorTy {
// Note: This numbering has to match the GCC assembler dialects for inline
// asm alternatives to work right.
ATT = 0, Intel = 1
};
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),
cl::desc("Mark code section jump table data regions."),
cl::Hidden);
void X86MCAsmInfoDarwin::anchor() { }
X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T) {
bool is64Bit = T.getArch() == Triple::x86_64;
if (is64Bit)
CodePointerSize = CalleeSaveStackSlotSize = 8;
AssemblerDialect = AsmWriterFlavor;
TextAlignFillValue = 0x90;
if (!is64Bit)
Data64bitsDirective = nullptr; // we can't emit a 64-bit unit
// Use ## as a comment string so that .s files generated by llvm can go
// through the GCC preprocessor without causing an error. This is needed
// because "clang foo.s" runs the C preprocessor, which is usually reserved
// for .S files on other systems. Perhaps this is because the file system
// wasn't always case preserving or something.
CommentString = "##";
SupportsDebugInformation = true;
UseDataRegionDirectives = MarkedJTDataRegions;
// Exceptions handling
ExceptionsType = ExceptionHandling::DwarfCFI;
// old assembler lacks some directives
// FIXME: this should really be a check on the assembler characteristics
// rather than OS version
if (T.isMacOSX() && T.isMacOSXVersionLT(10, 6))
HasWeakDefCanBeHiddenDirective = false;
// Assume ld64 is new enough that the abs-ified FDE relocs may be used
// (actually, must, since otherwise the non-extern relocations we produce
// overwhelm ld64's tiny little mind and it fails).
DwarfFDESymbolsUseAbsDiff = true;
UseIntegratedAssembler = true;
}
X86_64MCAsmInfoDarwin::X86_64MCAsmInfoDarwin(const Triple &Triple)
: X86MCAsmInfoDarwin(Triple) {
}
void X86ELFMCAsmInfo::anchor() { }
X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) {
bool is64Bit = T.getArch() == Triple::x86_64;
bool isX32 = T.getEnvironment() == Triple::GNUX32;
// For ELF, x86-64 pointer size depends on the ABI.
// For x86-64 without the x32 ABI, pointer size is 8. For x86 and for x86-64
// with the x32 ABI, pointer size remains the default 4.
CodePointerSize = (is64Bit && !isX32) ? 8 : 4;
// OTOH, stack slot size is always 8 for x86-64, even with the x32 ABI.
CalleeSaveStackSlotSize = is64Bit ? 8 : 4;
AssemblerDialect = AsmWriterFlavor;
TextAlignFillValue = 0x90;
// Debug Information
SupportsDebugInformation = true;
// Exceptions handling
ExceptionsType = ExceptionHandling::DwarfCFI;
// Always enable the integrated assembler by default.
// Clang also enabled it when the OS is Solaris but that is redundant here.
UseIntegratedAssembler = true;
}
const MCExpr *
X86_64MCAsmInfoDarwin::getExprForPersonalitySymbol(const MCSymbol *Sym,
unsigned Encoding,
MCStreamer &Streamer) const {
MCContext &Context = Streamer.getContext();
const MCExpr *Res =
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Context);
const MCExpr *Four = MCConstantExpr::create(4, Context);
return MCBinaryExpr::createAdd(Res, Four, Context);
}
void X86MCAsmInfoMicrosoft::anchor() { }
X86MCAsmInfoMicrosoft::X86MCAsmInfoMicrosoft(const Triple &Triple) {
if (Triple.getArch() == Triple::x86_64) {
PrivateGlobalPrefix = ".L";
PrivateLabelPrefix = ".L";
CodePointerSize = 8;
WinEHEncodingType = WinEH::EncodingType::Itanium;
} else {
// 32-bit X86 doesn't use CFI, so this isn't a real encoding type. It's just
// a place holder that the Windows EHStreamer looks for to suppress CFI
// output. In particular, usesWindowsCFI() returns false.
WinEHEncodingType = WinEH::EncodingType::X86;
}
ExceptionsType = ExceptionHandling::WinEH;
AssemblerDialect = AsmWriterFlavor;
TextAlignFillValue = 0x90;
AllowAtInName = true;
UseIntegratedAssembler = true;
}
void X86MCAsmInfoGNUCOFF::anchor() { }
X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple &Triple) {
assert(Triple.isOSWindows() && "Windows is the only supported COFF target");
if (Triple.getArch() == Triple::x86_64) {
PrivateGlobalPrefix = ".L";
PrivateLabelPrefix = ".L";
CodePointerSize = 8;
WinEHEncodingType = WinEH::EncodingType::Itanium;
ExceptionsType = ExceptionHandling::WinEH;
} else {
ExceptionsType = ExceptionHandling::DwarfCFI;
}
AssemblerDialect = AsmWriterFlavor;
TextAlignFillValue = 0x90;
UseIntegratedAssembler = true;
}

View File

@@ -0,0 +1,61 @@
//===-- X86MCAsmInfo.h - X86 asm properties --------------------*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the X86MCAsmInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_X86_MCTARGETDESC_X86MCASMINFO_H
#define LLVM_LIB_TARGET_X86_MCTARGETDESC_X86MCASMINFO_H
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmInfoCOFF.h"
#include "llvm/MC/MCAsmInfoDarwin.h"
#include "llvm/MC/MCAsmInfoELF.h"
namespace llvm {
class Triple;
class X86MCAsmInfoDarwin : public MCAsmInfoDarwin {
virtual void anchor();
public:
explicit X86MCAsmInfoDarwin(const Triple &Triple);
};
struct X86_64MCAsmInfoDarwin : public X86MCAsmInfoDarwin {
explicit X86_64MCAsmInfoDarwin(const Triple &Triple);
const MCExpr *
getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding,
MCStreamer &Streamer) const override;
};
class X86ELFMCAsmInfo : public MCAsmInfoELF {
void anchor() override;
public:
explicit X86ELFMCAsmInfo(const Triple &Triple);
};
class X86MCAsmInfoMicrosoft : public MCAsmInfoMicrosoft {
void anchor() override;
public:
explicit X86MCAsmInfoMicrosoft(const Triple &Triple);
};
class X86MCAsmInfoGNUCOFF : public MCAsmInfoGNUCOFF {
void anchor() override;
public:
explicit X86MCAsmInfoGNUCOFF(const Triple &Triple);
};
} // namespace llvm
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,145 @@
//===-- X86MCTargetDesc.h - X86 Target Descriptions -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides X86 specific target descriptions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_X86_MCTARGETDESC_X86MCTARGETDESC_H
#define LLVM_LIB_TARGET_X86_MCTARGETDESC_X86MCTARGETDESC_H
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/DataTypes.h"
#include <string>
namespace llvm {
class MCAsmBackend;
class MCCodeEmitter;
class MCContext;
class MCInstrInfo;
class MCObjectWriter;
class MCRegisterInfo;
class MCSubtargetInfo;
class MCRelocationInfo;
class MCTargetOptions;
class Target;
class Triple;
class StringRef;
class raw_ostream;
class raw_pwrite_stream;
Target &getTheX86_32Target();
Target &getTheX86_64Target();
/// Flavour of dwarf regnumbers
///
namespace DWARFFlavour {
enum {
X86_64 = 0, X86_32_DarwinEH = 1, X86_32_Generic = 2
};
}
/// Native X86 register numbers
///
namespace N86 {
enum {
EAX = 0, ECX = 1, EDX = 2, EBX = 3, ESP = 4, EBP = 5, ESI = 6, EDI = 7
};
}
namespace X86_MC {
std::string ParseX86Triple(const Triple &TT);
unsigned getDwarfRegFlavour(const Triple &TT, bool isEH);
void initLLVMToSEHAndCVRegMapping(MCRegisterInfo *MRI);
/// Create a X86 MCSubtargetInfo instance. This is exposed so Asm parser, etc.
/// do not need to go through TargetRegistry.
MCSubtargetInfo *createX86MCSubtargetInfo(const Triple &TT, StringRef CPU,
StringRef FS);
}
MCCodeEmitter *createX86MCCodeEmitter(const MCInstrInfo &MCII,
const MCRegisterInfo &MRI,
MCContext &Ctx);
MCAsmBackend *createX86_32AsmBackend(const Target &T,
const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI,
const MCTargetOptions &Options);
MCAsmBackend *createX86_64AsmBackend(const Target &T,
const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI,
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,
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.
std::unique_ptr<MCObjectWriter> createX86MachObjectWriter(raw_pwrite_stream &OS,
bool Is64Bit,
uint32_t CPUType,
uint32_t CPUSubtype);
/// Construct an X86 ELF object writer.
std::unique_ptr<MCObjectWriter> createX86ELFObjectWriter(raw_pwrite_stream &OS,
bool IsELF64,
uint8_t OSABI,
uint16_t EMachine);
/// Construct an X86 Win COFF object writer.
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.
/// Aborts on error.
unsigned getX86SubSuperRegister(unsigned, unsigned, bool High=false);
/// Returns the sub or super register of a specific X86 register.
/// Like getX86SubSuperRegister() but returns 0 on error.
unsigned getX86SubSuperRegisterOrZero(unsigned, unsigned,
bool High = false);
} // End llvm namespace
// Defines symbolic names for X86 registers. This defines a mapping from
// register name to register number.
//
#define GET_REGINFO_ENUM
#include "X86GenRegisterInfo.inc"
// Defines symbolic names for the X86 instructions.
//
#define GET_INSTRINFO_ENUM
#include "X86GenInstrInfo.inc"
#define GET_SUBTARGETINFO_ENUM
#include "X86GenSubtargetInfo.inc"
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -0,0 +1,112 @@
//===-- X86WinCOFFObjectWriter.cpp - X86 Win COFF Writer ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/X86FixupKinds.h"
#include "MCTargetDesc/X86MCTargetDesc.h"
#include "llvm/BinaryFormat/COFF.h"
#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"
using namespace llvm;
namespace {
class X86WinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
public:
X86WinCOFFObjectWriter(bool Is64Bit);
~X86WinCOFFObjectWriter() override = default;
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
const MCFixup &Fixup, bool IsCrossSection,
const MCAsmBackend &MAB) const override;
};
} // end anonymous namespace
X86WinCOFFObjectWriter::X86WinCOFFObjectWriter(bool Is64Bit)
: MCWinCOFFObjectTargetWriter(Is64Bit ? COFF::IMAGE_FILE_MACHINE_AMD64
: COFF::IMAGE_FILE_MACHINE_I386) {}
unsigned X86WinCOFFObjectWriter::getRelocType(MCContext &Ctx,
const MCValue &Target,
const MCFixup &Fixup,
bool IsCrossSection,
const MCAsmBackend &MAB) const {
unsigned FixupKind = Fixup.getKind();
if (IsCrossSection) {
if (FixupKind != FK_Data_4 && FixupKind != llvm::X86::reloc_signed_4byte) {
Ctx.reportError(Fixup.getLoc(), "Cannot represent this expression");
return COFF::IMAGE_REL_AMD64_ADDR32;
}
FixupKind = FK_PCRel_4;
}
MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
if (getMachine() == COFF::IMAGE_FILE_MACHINE_AMD64) {
switch (FixupKind) {
case FK_PCRel_4:
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_movq_load:
case X86::reloc_riprel_4byte_relax:
case X86::reloc_riprel_4byte_relax_rex:
return COFF::IMAGE_REL_AMD64_REL32;
case FK_Data_4:
case X86::reloc_signed_4byte:
case X86::reloc_signed_4byte_relax:
if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
return COFF::IMAGE_REL_AMD64_ADDR32NB;
if (Modifier == MCSymbolRefExpr::VK_SECREL)
return COFF::IMAGE_REL_AMD64_SECREL;
return COFF::IMAGE_REL_AMD64_ADDR32;
case FK_Data_8:
return COFF::IMAGE_REL_AMD64_ADDR64;
case FK_SecRel_2:
return COFF::IMAGE_REL_AMD64_SECTION;
case FK_SecRel_4:
return COFF::IMAGE_REL_AMD64_SECREL;
default:
llvm_unreachable("unsupported relocation type");
}
} else if (getMachine() == COFF::IMAGE_FILE_MACHINE_I386) {
switch (FixupKind) {
case FK_PCRel_4:
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_movq_load:
return COFF::IMAGE_REL_I386_REL32;
case FK_Data_4:
case X86::reloc_signed_4byte:
case X86::reloc_signed_4byte_relax:
if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
return COFF::IMAGE_REL_I386_DIR32NB;
if (Modifier == MCSymbolRefExpr::VK_SECREL)
return COFF::IMAGE_REL_AMD64_SECREL;
return COFF::IMAGE_REL_I386_DIR32;
case FK_SecRel_2:
return COFF::IMAGE_REL_I386_SECTION;
case FK_SecRel_4:
return COFF::IMAGE_REL_I386_SECREL;
default:
llvm_unreachable("unsupported relocation type");
}
} else
llvm_unreachable("Unsupported COFF machine type.");
}
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);
}

View File

@@ -0,0 +1,73 @@
//===-- X86WinCOFFStreamer.cpp - X86 Target WinCOFF Streamer ----*- 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/MC/MCAsmBackend.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCWin64EH.h"
#include "llvm/MC/MCWinCOFFStreamer.h"
using namespace llvm;
namespace {
class X86WinCOFFStreamer : public MCWinCOFFStreamer {
Win64EH::UnwindEmitter EHStreamer;
public:
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(SMLoc Loc) override;
void EmitWindowsUnwindTables() override;
void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc) override;
void FinishImpl() override;
};
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!
EHStreamer.EmitUnwindInfo(*this, getCurrentWinFrameInfo());
}
void X86WinCOFFStreamer::EmitWindowsUnwindTables() {
if (!getNumWinFrameInfos())
return;
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();
MCWinCOFFStreamer::FinishImpl();
}
}
MCStreamer *llvm::createX86WinCOFFStreamer(MCContext &C,
std::unique_ptr<MCAsmBackend> &&AB,
raw_pwrite_stream &OS,
std::unique_ptr<MCCodeEmitter> &&CE,
bool RelaxAll,
bool IncrementalLinkerCompatible) {
X86WinCOFFStreamer *S =
new X86WinCOFFStreamer(C, std::move(AB), std::move(CE), OS);
S->getAssembler().setRelaxAll(RelaxAll);
S->getAssembler().setIncrementalLinkerCompatible(IncrementalLinkerCompatible);
return S;
}

View File

@@ -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);
}