X86WinCOFFObjectWriter.cpp revision 276479
1234285Sdim//===-- X86WinCOFFObjectWriter.cpp - X86 Win COFF Writer ------------------===//
2234285Sdim//
3234285Sdim//                     The LLVM Compiler Infrastructure
4234285Sdim//
5234285Sdim// This file is distributed under the University of Illinois Open Source
6234285Sdim// License. See LICENSE.TXT for details.
7234285Sdim//
8234285Sdim//===----------------------------------------------------------------------===//
9234285Sdim
10234285Sdim#include "MCTargetDesc/X86FixupKinds.h"
11234285Sdim#include "MCTargetDesc/X86MCTargetDesc.h"
12251662Sdim#include "llvm/MC/MCExpr.h"
13251662Sdim#include "llvm/MC/MCValue.h"
14234285Sdim#include "llvm/MC/MCWinCOFFObjectWriter.h"
15234285Sdim#include "llvm/Support/COFF.h"
16234285Sdim#include "llvm/Support/ErrorHandling.h"
17234285Sdim
18234285Sdimusing namespace llvm;
19234285Sdim
20234285Sdimnamespace llvm {
21234285Sdim  class MCObjectWriter;
22234285Sdim}
23234285Sdim
24234285Sdimnamespace {
25234285Sdim  class X86WinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
26234285Sdim  public:
27276479Sdim    X86WinCOFFObjectWriter(bool Is64Bit);
28261991Sdim    virtual ~X86WinCOFFObjectWriter();
29234285Sdim
30276479Sdim    unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
31276479Sdim                          bool IsCrossSection) const override;
32234285Sdim  };
33234285Sdim}
34234285Sdim
35276479SdimX86WinCOFFObjectWriter::X86WinCOFFObjectWriter(bool Is64Bit)
36276479Sdim    : MCWinCOFFObjectTargetWriter(Is64Bit ? COFF::IMAGE_FILE_MACHINE_AMD64
37276479Sdim                                          : COFF::IMAGE_FILE_MACHINE_I386) {}
38234285Sdim
39234285SdimX86WinCOFFObjectWriter::~X86WinCOFFObjectWriter() {}
40234285Sdim
41251662Sdimunsigned X86WinCOFFObjectWriter::getRelocType(const MCValue &Target,
42251662Sdim                                              const MCFixup &Fixup,
43251662Sdim                                              bool IsCrossSection) const {
44251662Sdim  unsigned FixupKind = IsCrossSection ? FK_PCRel_4 : Fixup.getKind();
45251662Sdim
46251662Sdim  MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
47251662Sdim    MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
48251662Sdim
49276479Sdim  if (getMachine() == COFF::IMAGE_FILE_MACHINE_AMD64) {
50276479Sdim    switch (FixupKind) {
51276479Sdim    case FK_PCRel_4:
52276479Sdim    case X86::reloc_riprel_4byte:
53276479Sdim    case X86::reloc_riprel_4byte_movq_load:
54276479Sdim      return COFF::IMAGE_REL_AMD64_REL32;
55276479Sdim    case FK_Data_4:
56276479Sdim    case X86::reloc_signed_4byte:
57276479Sdim      if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
58276479Sdim        return COFF::IMAGE_REL_AMD64_ADDR32NB;
59276479Sdim      return COFF::IMAGE_REL_AMD64_ADDR32;
60276479Sdim    case FK_Data_8:
61234285Sdim      return COFF::IMAGE_REL_AMD64_ADDR64;
62276479Sdim    case FK_SecRel_2:
63276479Sdim      return COFF::IMAGE_REL_AMD64_SECTION;
64276479Sdim    case FK_SecRel_4:
65276479Sdim      return COFF::IMAGE_REL_AMD64_SECREL;
66276479Sdim    default:
67276479Sdim      llvm_unreachable("unsupported relocation type");
68276479Sdim    }
69276479Sdim  } else if (getMachine() == COFF::IMAGE_FILE_MACHINE_I386) {
70276479Sdim    switch (FixupKind) {
71276479Sdim    case FK_PCRel_4:
72276479Sdim    case X86::reloc_riprel_4byte:
73276479Sdim    case X86::reloc_riprel_4byte_movq_load:
74276479Sdim      return COFF::IMAGE_REL_I386_REL32;
75276479Sdim    case FK_Data_4:
76276479Sdim    case X86::reloc_signed_4byte:
77276479Sdim      if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
78276479Sdim        return COFF::IMAGE_REL_I386_DIR32NB;
79276479Sdim      return COFF::IMAGE_REL_I386_DIR32;
80276479Sdim    case FK_SecRel_2:
81276479Sdim      return COFF::IMAGE_REL_I386_SECTION;
82276479Sdim    case FK_SecRel_4:
83276479Sdim      return COFF::IMAGE_REL_I386_SECREL;
84276479Sdim    default:
85276479Sdim      llvm_unreachable("unsupported relocation type");
86276479Sdim    }
87276479Sdim  } else
88276479Sdim    llvm_unreachable("Unsupported COFF machine type.");
89234285Sdim}
90234285Sdim
91234285SdimMCObjectWriter *llvm::createX86WinCOFFObjectWriter(raw_ostream &OS,
92234285Sdim                                                   bool Is64Bit) {
93234285Sdim  MCWinCOFFObjectTargetWriter *MOTW = new X86WinCOFFObjectWriter(Is64Bit);
94234285Sdim  return createWinCOFFObjectWriter(MOTW, OS);
95234285Sdim}
96