X86WinCOFFObjectWriter.cpp revision 276479
1//===-- X86WinCOFFObjectWriter.cpp - X86 Win COFF Writer ------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/X86FixupKinds.h"
11#include "MCTargetDesc/X86MCTargetDesc.h"
12#include "llvm/MC/MCExpr.h"
13#include "llvm/MC/MCValue.h"
14#include "llvm/MC/MCWinCOFFObjectWriter.h"
15#include "llvm/Support/COFF.h"
16#include "llvm/Support/ErrorHandling.h"
17
18using namespace llvm;
19
20namespace llvm {
21  class MCObjectWriter;
22}
23
24namespace {
25  class X86WinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
26  public:
27    X86WinCOFFObjectWriter(bool Is64Bit);
28    virtual ~X86WinCOFFObjectWriter();
29
30    unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
31                          bool IsCrossSection) const override;
32  };
33}
34
35X86WinCOFFObjectWriter::X86WinCOFFObjectWriter(bool Is64Bit)
36    : MCWinCOFFObjectTargetWriter(Is64Bit ? COFF::IMAGE_FILE_MACHINE_AMD64
37                                          : COFF::IMAGE_FILE_MACHINE_I386) {}
38
39X86WinCOFFObjectWriter::~X86WinCOFFObjectWriter() {}
40
41unsigned X86WinCOFFObjectWriter::getRelocType(const MCValue &Target,
42                                              const MCFixup &Fixup,
43                                              bool IsCrossSection) const {
44  unsigned FixupKind = IsCrossSection ? FK_PCRel_4 : Fixup.getKind();
45
46  MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
47    MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
48
49  if (getMachine() == COFF::IMAGE_FILE_MACHINE_AMD64) {
50    switch (FixupKind) {
51    case FK_PCRel_4:
52    case X86::reloc_riprel_4byte:
53    case X86::reloc_riprel_4byte_movq_load:
54      return COFF::IMAGE_REL_AMD64_REL32;
55    case FK_Data_4:
56    case X86::reloc_signed_4byte:
57      if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
58        return COFF::IMAGE_REL_AMD64_ADDR32NB;
59      return COFF::IMAGE_REL_AMD64_ADDR32;
60    case FK_Data_8:
61      return COFF::IMAGE_REL_AMD64_ADDR64;
62    case FK_SecRel_2:
63      return COFF::IMAGE_REL_AMD64_SECTION;
64    case FK_SecRel_4:
65      return COFF::IMAGE_REL_AMD64_SECREL;
66    default:
67      llvm_unreachable("unsupported relocation type");
68    }
69  } else if (getMachine() == COFF::IMAGE_FILE_MACHINE_I386) {
70    switch (FixupKind) {
71    case FK_PCRel_4:
72    case X86::reloc_riprel_4byte:
73    case X86::reloc_riprel_4byte_movq_load:
74      return COFF::IMAGE_REL_I386_REL32;
75    case FK_Data_4:
76    case X86::reloc_signed_4byte:
77      if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
78        return COFF::IMAGE_REL_I386_DIR32NB;
79      return COFF::IMAGE_REL_I386_DIR32;
80    case FK_SecRel_2:
81      return COFF::IMAGE_REL_I386_SECTION;
82    case FK_SecRel_4:
83      return COFF::IMAGE_REL_I386_SECREL;
84    default:
85      llvm_unreachable("unsupported relocation type");
86    }
87  } else
88    llvm_unreachable("Unsupported COFF machine type.");
89}
90
91MCObjectWriter *llvm::createX86WinCOFFObjectWriter(raw_ostream &OS,
92                                                   bool Is64Bit) {
93  MCWinCOFFObjectTargetWriter *MOTW = new X86WinCOFFObjectWriter(Is64Bit);
94  return createWinCOFFObjectWriter(MOTW, OS);
95}
96