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