1 //===-- PPCMachOWriterInfo.cpp - Mach-O Writer Info for the PowerPC -------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements Mach-O writer information for the PowerPC backend.
12 //===----------------------------------------------------------------------===//
14 #include "PPCMachOWriterInfo.h"
15 #include "PPCRelocations.h"
16 #include "PPCTargetMachine.h"
17 #include "llvm/CodeGen/MachORelocation.h"
18 #include "llvm/Support/OutputBuffer.h"
19 #include "llvm/Support/ErrorHandling.h"
23 PPCMachOWriterInfo::PPCMachOWriterInfo(const PPCTargetMachine
&TM
)
24 : TargetMachOWriterInfo(TM
.getTargetData()->getPointerSizeInBits() == 64 ?
25 HDR_CPU_TYPE_POWERPC64
:
27 HDR_CPU_SUBTYPE_POWERPC_ALL
) {}
28 PPCMachOWriterInfo::~PPCMachOWriterInfo() {}
30 /// GetTargetRelocation - For the MachineRelocation MR, convert it to one or
31 /// more PowerPC MachORelocation(s), add the new relocations to the
32 /// MachOSection, and rewrite the instruction at the section offset if required
33 /// by that relocation type.
34 unsigned PPCMachOWriterInfo::GetTargetRelocation(MachineRelocation
&MR
,
38 OutputBuffer
&RelocOut
,
41 bool isExtern
) const {
42 unsigned NumRelocs
= 0;
45 // Get the address of whatever it is we're relocating, if possible.
47 Addr
= (uintptr_t)MR
.getResultPointer() + ToAddr
;
49 switch ((PPC::RelocationType
)MR
.getRelocationType()) {
50 default: llvm_unreachable("Unknown PPC relocation type!");
51 case PPC::reloc_absolute_low_ix
:
52 llvm_unreachable("Unhandled PPC relocation type!");
54 case PPC::reloc_vanilla
:
56 // FIXME: need to handle 64 bit vanilla relocs
57 MachORelocation
VANILLA(MR
.getMachineCodeOffset(), ToIdx
,
60 Scattered
, (intptr_t)MR
.getResultPointer());
64 RelocOut
.outword(VANILLA
.getPackedFields());
65 RelocOut
.outword(VANILLA
.getAddress());
67 RelocOut
.outword(VANILLA
.getAddress());
68 RelocOut
.outword(VANILLA
.getPackedFields());
71 intptr_t SymbolOffset
;
74 SymbolOffset
= Addr
+ MR
.getConstantVal();
78 printf("vanilla fixup: sec_%x[%x] = %x\n", FromIdx
,
79 unsigned(MR
.getMachineCodeOffset()),
80 unsigned(SymbolOffset
));
81 SecOut
.fixword(SymbolOffset
, MR
.getMachineCodeOffset());
84 case PPC::reloc_pcrel_bx
:
86 // FIXME: Presumably someday we will need to branch to other, non-extern
87 // functions too. Need to figure out some way to distinguish between
88 // target is BB and target is function.
90 MachORelocation
BR24(MR
.getMachineCodeOffset(), ToIdx
, true, 2,
91 isExtern
, PPC_RELOC_BR24
, Scattered
,
92 (intptr_t)MR
.getMachineCodeOffset());
93 RelocOut
.outword(BR24
.getAddress());
94 RelocOut
.outword(BR24
.getPackedFields());
98 Addr
-= MR
.getMachineCodeOffset();
102 Addr
|= (SecOut
[MR
.getMachineCodeOffset()] << 24);
103 Addr
|= (SecOut
[MR
.getMachineCodeOffset()+3] & 0x3);
104 SecOut
.fixword(Addr
, MR
.getMachineCodeOffset());
107 case PPC::reloc_pcrel_bcx
:
109 Addr
-= MR
.getMachineCodeOffset();
112 SecOut
.fixhalf(Addr
, MR
.getMachineCodeOffset() + 2);
115 case PPC::reloc_absolute_high
:
117 MachORelocation
HA16(MR
.getMachineCodeOffset(), ToIdx
, false, 2,
118 isExtern
, PPC_RELOC_HA16
);
119 MachORelocation
PAIR(Addr
& 0xFFFF, 0xFFFFFF, false, 2, isExtern
,
123 RelocOut
.outword(HA16
.getRawAddress());
124 RelocOut
.outword(HA16
.getPackedFields());
125 RelocOut
.outword(PAIR
.getRawAddress());
126 RelocOut
.outword(PAIR
.getPackedFields());
130 SecOut
.fixhalf(Addr
>> 16, MR
.getMachineCodeOffset() + 2);
133 case PPC::reloc_absolute_low
:
135 MachORelocation
LO16(MR
.getMachineCodeOffset(), ToIdx
, false, 2,
136 isExtern
, PPC_RELOC_LO16
);
137 MachORelocation
PAIR(Addr
>> 16, 0xFFFFFF, false, 2, isExtern
,
141 RelocOut
.outword(LO16
.getRawAddress());
142 RelocOut
.outword(LO16
.getPackedFields());
143 RelocOut
.outword(PAIR
.getRawAddress());
144 RelocOut
.outword(PAIR
.getPackedFields());
146 SecOut
.fixhalf(Addr
, MR
.getMachineCodeOffset() + 2);