LLVM API Documentation
00001 //===-- PPCAsmBackend.cpp - PPC Assembler Backend -------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "MCTargetDesc/PPCMCTargetDesc.h" 00011 #include "MCTargetDesc/PPCFixupKinds.h" 00012 #include "llvm/MC/MCAsmBackend.h" 00013 #include "llvm/MC/MCELFObjectWriter.h" 00014 #include "llvm/MC/MCFixupKindInfo.h" 00015 #include "llvm/MC/MCMachObjectWriter.h" 00016 #include "llvm/MC/MCObjectWriter.h" 00017 #include "llvm/MC/MCSectionMachO.h" 00018 #include "llvm/MC/MCValue.h" 00019 #include "llvm/Object/MachOFormat.h" 00020 #include "llvm/Support/ELF.h" 00021 #include "llvm/Support/ErrorHandling.h" 00022 #include "llvm/Support/TargetRegistry.h" 00023 using namespace llvm; 00024 00025 static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) { 00026 switch (Kind) { 00027 default: 00028 llvm_unreachable("Unknown fixup kind!"); 00029 case FK_Data_1: 00030 case FK_Data_2: 00031 case FK_Data_4: 00032 case FK_Data_8: 00033 case PPC::fixup_ppc_tlsreg: 00034 case PPC::fixup_ppc_nofixup: 00035 return Value; 00036 case PPC::fixup_ppc_brcond14: 00037 return Value & 0xfffc; 00038 case PPC::fixup_ppc_br24: 00039 return Value & 0x3fffffc; 00040 case PPC::fixup_ppc_half16: 00041 return Value & 0xffff; 00042 case PPC::fixup_ppc_half16ds: 00043 return Value & 0xfffc; 00044 } 00045 } 00046 00047 static unsigned getFixupKindNumBytes(unsigned Kind) { 00048 switch (Kind) { 00049 default: 00050 llvm_unreachable("Unknown fixup kind!"); 00051 case FK_Data_1: 00052 return 1; 00053 case FK_Data_2: 00054 case PPC::fixup_ppc_half16: 00055 case PPC::fixup_ppc_half16ds: 00056 return 2; 00057 case FK_Data_4: 00058 case PPC::fixup_ppc_brcond14: 00059 case PPC::fixup_ppc_br24: 00060 return 4; 00061 case FK_Data_8: 00062 return 8; 00063 case PPC::fixup_ppc_tlsreg: 00064 case PPC::fixup_ppc_nofixup: 00065 return 0; 00066 } 00067 } 00068 00069 namespace { 00070 class PPCMachObjectWriter : public MCMachObjectTargetWriter { 00071 public: 00072 PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, 00073 uint32_t CPUSubtype) 00074 : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {} 00075 00076 void RecordRelocation(MachObjectWriter *Writer, 00077 const MCAssembler &Asm, const MCAsmLayout &Layout, 00078 const MCFragment *Fragment, const MCFixup &Fixup, 00079 MCValue Target, uint64_t &FixedValue) { 00080 llvm_unreachable("Relocation emission for MachO/PPC unimplemented!"); 00081 } 00082 }; 00083 00084 class PPCAsmBackend : public MCAsmBackend { 00085 const Target &TheTarget; 00086 public: 00087 PPCAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {} 00088 00089 unsigned getNumFixupKinds() const { return PPC::NumTargetFixupKinds; } 00090 00091 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { 00092 const static MCFixupKindInfo Infos[PPC::NumTargetFixupKinds] = { 00093 // name offset bits flags 00094 { "fixup_ppc_br24", 6, 24, MCFixupKindInfo::FKF_IsPCRel }, 00095 { "fixup_ppc_brcond14", 16, 14, MCFixupKindInfo::FKF_IsPCRel }, 00096 { "fixup_ppc_half16", 0, 16, 0 }, 00097 { "fixup_ppc_half16ds", 0, 14, 0 }, 00098 { "fixup_ppc_tlsreg", 0, 0, 0 }, 00099 { "fixup_ppc_nofixup", 0, 0, 0 } 00100 }; 00101 00102 if (Kind < FirstTargetFixupKind) 00103 return MCAsmBackend::getFixupKindInfo(Kind); 00104 00105 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 00106 "Invalid kind!"); 00107 return Infos[Kind - FirstTargetFixupKind]; 00108 } 00109 00110 void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 00111 uint64_t Value) const { 00112 Value = adjustFixupValue(Fixup.getKind(), Value); 00113 if (!Value) return; // Doesn't change encoding. 00114 00115 unsigned Offset = Fixup.getOffset(); 00116 unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); 00117 00118 // For each byte of the fragment that the fixup touches, mask in the bits 00119 // from the fixup value. The Value has been "split up" into the appropriate 00120 // bitfields above. 00121 for (unsigned i = 0; i != NumBytes; ++i) 00122 Data[Offset + i] |= uint8_t((Value >> ((NumBytes - i - 1)*8)) & 0xff); 00123 } 00124 00125 bool mayNeedRelaxation(const MCInst &Inst) const { 00126 // FIXME. 00127 return false; 00128 } 00129 00130 bool fixupNeedsRelaxation(const MCFixup &Fixup, 00131 uint64_t Value, 00132 const MCRelaxableFragment *DF, 00133 const MCAsmLayout &Layout) const { 00134 // FIXME. 00135 llvm_unreachable("relaxInstruction() unimplemented"); 00136 } 00137 00138 00139 void relaxInstruction(const MCInst &Inst, MCInst &Res) const { 00140 // FIXME. 00141 llvm_unreachable("relaxInstruction() unimplemented"); 00142 } 00143 00144 bool writeNopData(uint64_t Count, MCObjectWriter *OW) const { 00145 // FIXME: Zero fill for now. That's not right, but at least will get the 00146 // section size right. 00147 for (uint64_t i = 0; i != Count; ++i) 00148 OW->Write8(0); 00149 return true; 00150 } 00151 00152 unsigned getPointerSize() const { 00153 StringRef Name = TheTarget.getName(); 00154 if (Name == "ppc64") return 8; 00155 assert(Name == "ppc32" && "Unknown target name!"); 00156 return 4; 00157 } 00158 }; 00159 } // end anonymous namespace 00160 00161 00162 // FIXME: This should be in a separate file. 00163 namespace { 00164 class DarwinPPCAsmBackend : public PPCAsmBackend { 00165 public: 00166 DarwinPPCAsmBackend(const Target &T) : PPCAsmBackend(T) { } 00167 00168 MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 00169 bool is64 = getPointerSize() == 8; 00170 return createMachObjectWriter(new PPCMachObjectWriter( 00171 /*Is64Bit=*/is64, 00172 (is64 ? object::mach::CTM_PowerPC64 : 00173 object::mach::CTM_PowerPC), 00174 object::mach::CSPPC_ALL), 00175 OS, /*IsLittleEndian=*/false); 00176 } 00177 00178 virtual bool doesSectionRequireSymbols(const MCSection &Section) const { 00179 return false; 00180 } 00181 }; 00182 00183 class ELFPPCAsmBackend : public PPCAsmBackend { 00184 uint8_t OSABI; 00185 public: 00186 ELFPPCAsmBackend(const Target &T, uint8_t OSABI) : 00187 PPCAsmBackend(T), OSABI(OSABI) { } 00188 00189 00190 MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 00191 bool is64 = getPointerSize() == 8; 00192 return createPPCELFObjectWriter(OS, is64, OSABI); 00193 } 00194 00195 virtual bool doesSectionRequireSymbols(const MCSection &Section) const { 00196 return false; 00197 } 00198 }; 00199 00200 } // end anonymous namespace 00201 00202 00203 00204 00205 MCAsmBackend *llvm::createPPCAsmBackend(const Target &T, StringRef TT, StringRef CPU) { 00206 if (Triple(TT).isOSDarwin()) 00207 return new DarwinPPCAsmBackend(T); 00208 00209 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); 00210 return new ELFPPCAsmBackend(T, OSABI); 00211 }