Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 1 | //===-- PPCMachOWriter.cpp - Emit a Mach-O file for the PowerPC backend ---===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by Nate Begeman and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file implements a Mach-O writer for the PowerPC backend. The public |
| 11 | // interface to this file is the createPPCMachOObjectWriterPass function. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 15 | #include "PPCRelocations.h" |
Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 16 | #include "PPCTargetMachine.h" |
| 17 | #include "llvm/PassManager.h" |
| 18 | #include "llvm/CodeGen/MachOWriter.h" |
Chris Lattner | a4f0b3a | 2006-08-27 12:54:02 +0000 | [diff] [blame] | 19 | #include "llvm/Support/Compiler.h" |
Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 20 | using namespace llvm; |
| 21 | |
| 22 | namespace { |
| 23 | class VISIBILITY_HIDDEN PPCMachOWriter : public MachOWriter { |
| 24 | public: |
| 25 | PPCMachOWriter(std::ostream &O, PPCTargetMachine &TM) : MachOWriter(O, TM) { |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 26 | if (TM.getTargetData()->getPointerSizeInBits() == 64) { |
| 27 | Header.cputype = MachOHeader::CPU_TYPE_POWERPC64; |
| 28 | } else { |
| 29 | Header.cputype = MachOHeader::CPU_TYPE_POWERPC; |
| 30 | } |
Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 31 | Header.cpusubtype = MachOHeader::CPU_SUBTYPE_POWERPC_ALL; |
| 32 | } |
| 33 | |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 34 | virtual void GetTargetRelocation(MachineRelocation &MR, MachOSection &MOS, |
| 35 | unsigned ToIndex); |
| 36 | virtual MachineRelocation GetJTRelocation(unsigned Offset, |
| 37 | MachineBasicBlock *MBB); |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 38 | |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 39 | virtual const char *getPassName() const { |
| 40 | return "PowerPC Mach-O Writer"; |
| 41 | } |
| 42 | |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 43 | // Constants for the relocation r_type field. |
| 44 | // see <mach-o/ppc/reloc.h> |
| 45 | enum { PPC_RELOC_VANILLA, // generic relocation |
| 46 | PPC_RELOC_PAIR, // the second relocation entry of a pair |
| 47 | PPC_RELOC_BR14, // 14 bit branch displacement to word address |
| 48 | PPC_RELOC_BR24, // 24 bit branch displacement to word address |
| 49 | PPC_RELOC_HI16, // a PAIR follows with the low 16 bits |
| 50 | PPC_RELOC_LO16, // a PAIR follows with the high 16 bits |
| 51 | PPC_RELOC_HA16, // a PAIR follows, which is sign extended to 32b |
| 52 | PPC_RELOC_LO14 // LO16 with low 2 bits implicitly zero |
| 53 | }; |
Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 54 | }; |
| 55 | } |
| 56 | |
| 57 | /// addPPCMachOObjectWriterPass - Returns a pass that outputs the generated code |
| 58 | /// as a Mach-O object file. |
| 59 | /// |
Chris Lattner | 1911fd4 | 2006-09-04 04:14:57 +0000 | [diff] [blame] | 60 | void llvm::addPPCMachOObjectWriterPass(FunctionPassManager &FPM, |
Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 61 | std::ostream &O, PPCTargetMachine &TM) { |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 62 | PPCMachOWriter *MOW = new PPCMachOWriter(O, TM); |
| 63 | FPM.add(MOW); |
| 64 | FPM.add(createPPCCodeEmitterPass(TM, MOW->getMachineCodeEmitter())); |
Nate Begeman | eb883af | 2006-08-23 21:08:52 +0000 | [diff] [blame] | 65 | } |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 66 | |
| 67 | /// GetTargetRelocation - For the MachineRelocation MR, convert it to one or |
| 68 | /// more PowerPC MachORelocation(s), add the new relocations to the |
| 69 | /// MachOSection, and rewrite the instruction at the section offset if required |
| 70 | /// by that relocation type. |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 71 | void PPCMachOWriter::GetTargetRelocation(MachineRelocation &MR, |
| 72 | MachOSection &MOS, |
| 73 | unsigned ToIndex) { |
| 74 | uint64_t Addr = 0; |
| 75 | |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 76 | // Keep track of whether or not this is an externally defined relocation. |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 77 | bool isExtern = false; |
| 78 | |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 79 | // Get the address of whatever it is we're relocating, if possible. |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 80 | if (!isExtern) |
| 81 | Addr = (uintptr_t)MR.getResultPointer(); |
| 82 | |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 83 | switch ((PPC::RelocationType)MR.getRelocationType()) { |
| 84 | default: assert(0 && "Unknown PPC relocation type!"); |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 85 | case PPC::reloc_absolute_low_ix: |
| 86 | assert(0 && "Unhandled PPC relocation type!"); |
| 87 | break; |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 88 | case PPC::reloc_vanilla: |
| 89 | { |
| 90 | // FIXME: need to handle 64 bit vanilla relocs |
| 91 | MachORelocation VANILLA(MR.getMachineCodeOffset(), ToIndex, false, 2, |
| 92 | isExtern, PPC_RELOC_VANILLA); |
| 93 | outword(MOS.RelocBuffer, VANILLA.r_address); |
| 94 | outword(MOS.RelocBuffer, VANILLA.getPackedFields()); |
| 95 | } |
| 96 | MOS.nreloc += 1; |
| 97 | fixword(MOS.SectionData, Addr, MR.getMachineCodeOffset()); |
| 98 | break; |
| 99 | case PPC::reloc_pcrel_bx: |
| 100 | Addr -= MR.getMachineCodeOffset(); |
| 101 | Addr >>= 2; |
| 102 | Addr & 0xFFFFFF; |
| 103 | Addr <<= 2; |
| 104 | Addr |= (MOS.SectionData[MR.getMachineCodeOffset()] << 24); |
| 105 | fixword(MOS.SectionData, Addr, MR.getMachineCodeOffset()); |
| 106 | break; |
| 107 | case PPC::reloc_pcrel_bcx: |
| 108 | Addr -= MR.getMachineCodeOffset(); |
| 109 | Addr &= 0xFFFC; |
| 110 | fixhalf(MOS.SectionData, Addr, MR.getMachineCodeOffset() + 2); |
| 111 | break; |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 112 | case PPC::reloc_absolute_high: |
| 113 | { |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 114 | MachORelocation HA16(MR.getMachineCodeOffset(), ToIndex, false, 2, |
| 115 | isExtern, PPC_RELOC_HA16); |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 116 | MachORelocation PAIR(Addr & 0xFFFF, 0xFFFFFF, false, 2, isExtern, |
| 117 | PPC_RELOC_PAIR); |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 118 | outword(MOS.RelocBuffer, HA16.r_address); |
| 119 | outword(MOS.RelocBuffer, HA16.getPackedFields()); |
| 120 | outword(MOS.RelocBuffer, PAIR.r_address); |
| 121 | outword(MOS.RelocBuffer, PAIR.getPackedFields()); |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 122 | } |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 123 | printf("ha16: %x\n", (unsigned)Addr); |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 124 | MOS.nreloc += 2; |
| 125 | Addr += 0x8000; |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 126 | fixhalf(MOS.SectionData, Addr >> 16, MR.getMachineCodeOffset() + 2); |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 127 | break; |
| 128 | case PPC::reloc_absolute_low: |
| 129 | { |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 130 | MachORelocation LO16(MR.getMachineCodeOffset(), ToIndex, false, 2, |
| 131 | isExtern, PPC_RELOC_LO16); |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 132 | MachORelocation PAIR(Addr >> 16, 0xFFFFFF, false, 2, isExtern, |
| 133 | PPC_RELOC_PAIR); |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 134 | outword(MOS.RelocBuffer, LO16.r_address); |
| 135 | outword(MOS.RelocBuffer, LO16.getPackedFields()); |
| 136 | outword(MOS.RelocBuffer, PAIR.r_address); |
| 137 | outword(MOS.RelocBuffer, PAIR.getPackedFields()); |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 138 | } |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 139 | printf("lo16: %x\n", (unsigned)Addr); |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 140 | MOS.nreloc += 2; |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 141 | fixhalf(MOS.SectionData, Addr, MR.getMachineCodeOffset() + 2); |
Nate Begeman | 94be248 | 2006-09-08 22:42:09 +0000 | [diff] [blame] | 142 | break; |
| 143 | } |
| 144 | } |
Nate Begeman | 019f851 | 2006-09-10 23:03:44 +0000 | [diff] [blame] | 145 | |
| 146 | MachineRelocation PPCMachOWriter::GetJTRelocation(unsigned Offset, |
| 147 | MachineBasicBlock *MBB) { |
| 148 | // FIXME: do something about PIC |
| 149 | return MachineRelocation::getBB(Offset, PPC::reloc_vanilla, MBB); |
| 150 | } |
| 151 | |