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