MC: Add TargetAsmBackend::createObjectWriter.
[oota-llvm.git] / lib / Target / X86 / X86AsmBackend.cpp
1 //===-- X86AsmBackend.cpp - X86 Assembler Backend -------------------------===//
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 "llvm/Target/TargetAsmBackend.h"
11 #include "X86.h"
12 #include "X86FixupKinds.h"
13 #include "llvm/MC/MCAssembler.h"
14 #include "llvm/MC/MCSectionELF.h"
15 #include "llvm/MC/MCSectionMachO.h"
16 #include "llvm/MC/MachObjectWriter.h"
17 #include "llvm/Target/TargetRegistry.h"
18 #include "llvm/Target/TargetAsmBackend.h"
19 using namespace llvm;
20
21 namespace {
22
23 static unsigned getFixupKindLog2Size(unsigned Kind) {
24   switch (Kind) {
25   default: assert(0 && "invalid fixup kind!");
26   case X86::reloc_pcrel_1byte:
27   case FK_Data_1: return 0;
28   case FK_Data_2: return 1;
29   case X86::reloc_pcrel_4byte:
30   case X86::reloc_riprel_4byte:
31   case X86::reloc_riprel_4byte_movq_load:
32   case FK_Data_4: return 2;
33   case FK_Data_8: return 3;
34   }
35 }
36
37 class X86AsmBackend : public TargetAsmBackend {
38 public:
39   X86AsmBackend(const Target &T)
40     : TargetAsmBackend(T) {}
41
42   void ApplyFixup(const MCAsmFixup &Fixup, MCDataFragment &DF,
43                   uint64_t Value) const {
44     unsigned Size = 1 << getFixupKindLog2Size(Fixup.Kind);
45
46     assert(Fixup.Offset + Size <= DF.getContents().size() &&
47            "Invalid fixup offset!");
48     for (unsigned i = 0; i != Size; ++i)
49       DF.getContents()[Fixup.Offset + i] = uint8_t(Value >> (i * 8));
50   }
51 };
52
53 class ELFX86AsmBackend : public X86AsmBackend {
54 public:
55   ELFX86AsmBackend(const Target &T)
56     : X86AsmBackend(T) {
57     HasAbsolutizedSet = true;
58     HasScatteredSymbols = true;
59   }
60
61   MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
62     return 0;
63   }
64
65   bool isVirtualSection(const MCSection &Section) const {
66     const MCSectionELF &SE = static_cast<const MCSectionELF&>(Section);
67     return SE.getType() == MCSectionELF::SHT_NOBITS;;
68   }
69 };
70
71 class DarwinX86AsmBackend : public X86AsmBackend {
72 public:
73   DarwinX86AsmBackend(const Target &T)
74     : X86AsmBackend(T) {
75     HasAbsolutizedSet = true;
76     HasScatteredSymbols = true;
77   }
78
79   bool isVirtualSection(const MCSection &Section) const {
80     const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
81     return (SMO.getType() == MCSectionMachO::S_ZEROFILL ||
82             SMO.getType() == MCSectionMachO::S_GB_ZEROFILL);
83   }
84 };
85
86 class DarwinX86_32AsmBackend : public DarwinX86AsmBackend {
87 public:
88   DarwinX86_32AsmBackend(const Target &T)
89     : DarwinX86AsmBackend(T) {}
90
91   MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
92     return new MachObjectWriter(OS, /*Is64Bit=*/false);
93   }
94 };
95
96 class DarwinX86_64AsmBackend : public DarwinX86AsmBackend {
97 public:
98   DarwinX86_64AsmBackend(const Target &T)
99     : DarwinX86AsmBackend(T) {
100     HasReliableSymbolDifference = true;
101   }
102
103   MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
104     return new MachObjectWriter(OS, /*Is64Bit=*/true);
105   }
106
107   virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
108     // Temporary labels in the string literals sections require symbols. The
109     // issue is that the x86_64 relocation format does not allow symbol +
110     // offset, and so the linker does not have enough information to resolve the
111     // access to the appropriate atom unless an external relocation is used. For
112     // non-cstring sections, we expect the compiler to use a non-temporary label
113     // for anything that could have an addend pointing outside the symbol.
114     //
115     // See <rdar://problem/4765733>.
116     const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
117     return SMO.getType() == MCSectionMachO::S_CSTRING_LITERALS;
118   }
119 };
120
121 }
122
123 TargetAsmBackend *llvm::createX86_32AsmBackend(const Target &T,
124                                                const std::string &TT) {
125   switch (Triple(TT).getOS()) {
126   case Triple::Darwin:
127     return new DarwinX86_32AsmBackend(T);
128   default:
129     return new ELFX86AsmBackend(T);
130   }
131 }
132
133 TargetAsmBackend *llvm::createX86_64AsmBackend(const Target &T,
134                                                const std::string &TT) {
135   switch (Triple(TT).getOS()) {
136   case Triple::Darwin:
137     return new DarwinX86_64AsmBackend(T);
138   default:
139     return new ELFX86AsmBackend(T);
140   }
141 }