]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
MFC r234353:
[FreeBSD/stable/9.git] / contrib / llvm / lib / Target / PowerPC / MCTargetDesc / PPCELFObjectWriter.cpp
1 //===-- PPCELFObjectWriter.cpp - PPC ELF 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/PPCFixupKinds.h"
11 #include "MCTargetDesc/PPCMCTargetDesc.h"
12 #include "llvm/MC/MCELFObjectWriter.h"
13 #include "llvm/Support/ErrorHandling.h"
14
15 using namespace llvm;
16
17 namespace {
18   class PPCELFObjectWriter : public MCELFObjectTargetWriter {
19   public:
20     PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
21
22     virtual ~PPCELFObjectWriter();
23   protected:
24     virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
25                                   bool IsPCRel, bool IsRelocWithSymbol,
26                                   int64_t Addend) const;
27     virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset);
28   };
29 }
30
31 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
32   : MCELFObjectTargetWriter(Is64Bit, OSABI,
33                             Is64Bit ?  ELF::EM_PPC64 : ELF::EM_PPC,
34                             /*HasRelocationAddend*/ true) {}
35
36 PPCELFObjectWriter::~PPCELFObjectWriter() {
37 }
38
39 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
40                                              const MCFixup &Fixup,
41                                              bool IsPCRel,
42                                              bool IsRelocWithSymbol,
43                                              int64_t Addend) const {
44   // determine the type of the relocation
45   unsigned Type;
46   if (IsPCRel) {
47     switch ((unsigned)Fixup.getKind()) {
48     default:
49       llvm_unreachable("Unimplemented");
50     case PPC::fixup_ppc_br24:
51       Type = ELF::R_PPC_REL24;
52       break;
53     case FK_PCRel_4:
54       Type = ELF::R_PPC_REL32;
55       break;
56     }
57   } else {
58     switch ((unsigned)Fixup.getKind()) {
59       default: llvm_unreachable("invalid fixup kind!");
60     case PPC::fixup_ppc_br24:
61       Type = ELF::R_PPC_ADDR24;
62       break;
63     case PPC::fixup_ppc_brcond14:
64       Type = ELF::R_PPC_ADDR14_BRTAKEN; // XXX: or BRNTAKEN?_
65       break;
66     case PPC::fixup_ppc_ha16:
67       Type = ELF::R_PPC_ADDR16_HA;
68       break;
69     case PPC::fixup_ppc_lo16:
70       Type = ELF::R_PPC_ADDR16_LO;
71       break;
72     case PPC::fixup_ppc_lo14:
73       Type = ELF::R_PPC_ADDR14;
74       break;
75     case FK_Data_4:
76       Type = ELF::R_PPC_ADDR32;
77       break;
78     case FK_Data_2:
79       Type = ELF::R_PPC_ADDR16;
80       break;
81     }
82   }
83   return Type;
84 }
85
86 void PPCELFObjectWriter::
87 adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) {
88   switch ((unsigned)Fixup.getKind()) {
89     case PPC::fixup_ppc_ha16:
90     case PPC::fixup_ppc_lo16:
91       RelocOffset += 2;
92       break;
93     default:
94       break;
95   }
96 }
97
98 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS,
99                                                bool Is64Bit,
100                                                uint8_t OSABI) {
101   MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
102   return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/false);
103 }