mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	[Sparc] Add ELF Object Writer for Sparc.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198580 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		| @@ -1,5 +1,6 @@ | ||||
| add_llvm_library(LLVMSparcDesc | ||||
|   SparcAsmBackend.cpp | ||||
|   SparcELFObjectWriter.cpp | ||||
|   SparcMCAsmInfo.cpp | ||||
|   SparcMCCodeEmitter.cpp | ||||
|   SparcMCTargetDesc.cpp | ||||
|   | ||||
| @@ -10,17 +10,50 @@ | ||||
| #include "llvm/MC/MCAsmBackend.h" | ||||
| #include "MCTargetDesc/SparcMCTargetDesc.h" | ||||
| #include "MCTargetDesc/SparcFixupKinds.h" | ||||
| #include "llvm/MC/MCELFObjectWriter.h" | ||||
| #include "llvm/MC/MCFixupKindInfo.h" | ||||
| #include "llvm/MC/MCObjectWriter.h" | ||||
| #include "llvm/Support/TargetRegistry.h" | ||||
|  | ||||
| using namespace llvm; | ||||
|  | ||||
| static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { | ||||
|   switch (Kind) { | ||||
|   default: | ||||
|     llvm_unreachable("Unknown fixup kind!"); | ||||
|   case FK_Data_1: | ||||
|   case FK_Data_2: | ||||
|   case FK_Data_4: | ||||
|   case FK_Data_8: | ||||
|     return Value; | ||||
|   case Sparc::fixup_sparc_call30: | ||||
|     return Value & 0x3fffffff; | ||||
|   case Sparc::fixup_sparc_br22: | ||||
|     return Value & 0x3fffff; | ||||
|   case Sparc::fixup_sparc_br19: | ||||
|     return Value & 0x1ffff; | ||||
|   case Sparc::fixup_sparc_hi22: | ||||
|     return (Value >> 10) & 0x3fffff; | ||||
|   case Sparc::fixup_sparc_lo10: | ||||
|     return Value & 0x3ff; | ||||
|   case Sparc::fixup_sparc_h44: | ||||
|     return (Value >> 22) & 0x3fffff; | ||||
|   case Sparc::fixup_sparc_m44: | ||||
|     return (Value >> 12) & 0x3ff; | ||||
|   case Sparc::fixup_sparc_l44: | ||||
|     return Value & 0xfff; | ||||
|   case Sparc::fixup_sparc_hh: | ||||
|     return (Value >> 42) & 0x3fffff; | ||||
|   case Sparc::fixup_sparc_hm: | ||||
|     return (Value >>32) & 0x3ff; | ||||
|   } | ||||
| } | ||||
|  | ||||
| namespace { | ||||
|   class SparcAsmBackend : public MCAsmBackend { | ||||
|  | ||||
|     const Target &TheTarget; | ||||
|   public: | ||||
|     SparcAsmBackend(const Target &T) : MCAsmBackend() {} | ||||
|     SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {} | ||||
|  | ||||
|     unsigned getNumFixupKinds() const { | ||||
|       return Sparc::NumTargetFixupKinds; | ||||
| @@ -31,7 +64,14 @@ namespace { | ||||
|         // name                    offset bits  flags | ||||
|         { "fixup_sparc_call30",     0,     30,  MCFixupKindInfo::FKF_IsPCRel }, | ||||
|         { "fixup_sparc_br22",       0,     22,  MCFixupKindInfo::FKF_IsPCRel }, | ||||
|         { "fixup_sparc_br19",       0,     19,  MCFixupKindInfo::FKF_IsPCRel } | ||||
|         { "fixup_sparc_br19",       0,     19,  MCFixupKindInfo::FKF_IsPCRel }, | ||||
|         { "fixup_sparc_hi22",       0,     22,  0 }, | ||||
|         { "fixup_sparc_lo10",       0,     10,  0 }, | ||||
|         { "fixup_sparc_h44",        0,     22,  0 }, | ||||
|         { "fixup_sparc_m44",        0,     10,  0 }, | ||||
|         { "fixup_sparc_l44",        0,     12,  0 }, | ||||
|         { "fixup_sparc_hh",         0,     21,  0 }, | ||||
|         { "fixup_sparc_hm",         0,     10,  0 }, | ||||
|       }; | ||||
|  | ||||
|       if (Kind < FirstTargetFixupKind) | ||||
| @@ -68,21 +108,38 @@ namespace { | ||||
|         OW->Write8(0); | ||||
|       return true; | ||||
|     } | ||||
|  | ||||
|     bool is64Bit() const { | ||||
|       StringRef name = TheTarget.getName(); | ||||
|       return name == "sparcv9"; | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   class ELFSparcAsmBackend : public SparcAsmBackend { | ||||
|     Triple::OSType OSType; | ||||
|   public: | ||||
|     ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) : | ||||
|       SparcAsmBackend(T) { } | ||||
|       SparcAsmBackend(T), OSType(OSType) { } | ||||
|  | ||||
|     void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, | ||||
|                     uint64_t Value) const { | ||||
|       assert(0 && "applyFixup not implemented yet"); | ||||
|  | ||||
|       Value = adjustFixupValue(Fixup.getKind(), Value); | ||||
|       if (!Value) return;           // Doesn't change encoding. | ||||
|  | ||||
|       unsigned Offset = Fixup.getOffset(); | ||||
|  | ||||
|       // For each byte of the fragment that the fixup touches, mask in the bits | ||||
|       // from the fixup value. The Value has been "split up" into the | ||||
|       // appropriate bitfields above. | ||||
|       for (unsigned i = 0; i != 4; ++i) | ||||
|         Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     MCObjectWriter *createObjectWriter(raw_ostream &OS) const { | ||||
|       assert(0 && "Object Writer not implemented yet"); | ||||
|       return 0; | ||||
|       uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType); | ||||
|       return createSparcELFObjectWriter(OS, is64Bit(), OSABI); | ||||
|     } | ||||
|  | ||||
|     virtual bool doesSectionRequireSymbols(const MCSection &Section) const { | ||||
|   | ||||
							
								
								
									
										86
									
								
								lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| //===-- SparcELFObjectWriter.cpp - Sparc ELF Writer -----------------------===// | ||||
| // | ||||
| //                     The LLVM Compiler Infrastructure | ||||
| // | ||||
| // This file is distributed under the University of Illinois Open Source | ||||
| // License. See LICENSE.TXT for details. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
|  | ||||
| #include "MCTargetDesc/SparcMCTargetDesc.h" | ||||
| #include "MCTargetDesc/SparcFixupKinds.h" | ||||
| #include "llvm/ADT/STLExtras.h" | ||||
| #include "llvm/MC/MCELFObjectWriter.h" | ||||
| #include "llvm/MC/MCExpr.h" | ||||
| #include "llvm/MC/MCValue.h" | ||||
| #include "llvm/Support/ErrorHandling.h" | ||||
|  | ||||
| using namespace llvm; | ||||
|  | ||||
| namespace { | ||||
|   class SparcELFObjectWriter : public MCELFObjectTargetWriter { | ||||
|   public: | ||||
|     SparcELFObjectWriter(bool Is64Bit, uint8_t OSABI) | ||||
|       : MCELFObjectTargetWriter(Is64Bit, OSABI, | ||||
|                                 Is64Bit ?  ELF::EM_SPARCV9 : ELF::EM_SPARC, | ||||
|                                 /*HasRelocationAddend*/ true) {} | ||||
|  | ||||
|     virtual ~SparcELFObjectWriter() {} | ||||
|   protected: | ||||
|     virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, | ||||
|                                   bool IsPCRel, bool IsRelocWithSymbol, | ||||
|                                   int64_t Addend) const; | ||||
|  | ||||
|   }; | ||||
| } | ||||
|  | ||||
|  | ||||
| unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target, | ||||
|                                             const MCFixup &Fixup, | ||||
|                                             bool IsPCRel, | ||||
|                                             bool IsRelocWithSymbol, | ||||
|                                             int64_t Addend) const { | ||||
|   if (IsPCRel) { | ||||
|     switch((unsigned)Fixup.getKind()) { | ||||
|     default: | ||||
|       llvm_unreachable("Unimplemented fixup -> relocation"); | ||||
|     case FK_Data_1:                  return ELF::R_SPARC_DISP8; | ||||
|     case FK_Data_2:                  return ELF::R_SPARC_DISP16; | ||||
|     case FK_Data_4:                  return ELF::R_SPARC_DISP32; | ||||
|     case FK_Data_8:                  return ELF::R_SPARC_DISP64; | ||||
|     case Sparc::fixup_sparc_call30:  return ELF::R_SPARC_WDISP30; | ||||
|     case Sparc::fixup_sparc_br22:    return ELF::R_SPARC_WDISP22; | ||||
|     case Sparc::fixup_sparc_br19:    return ELF::R_SPARC_WDISP19; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   switch((unsigned)Fixup.getKind()) { | ||||
|   default: | ||||
|     llvm_unreachable("Unimplemented fixup -> relocation"); | ||||
|   case FK_Data_1:                return ELF::R_SPARC_8; | ||||
|   case FK_Data_2:                return ((Fixup.getOffset() % 2) | ||||
|                                          ? ELF::R_SPARC_UA16 | ||||
|                                          : ELF::R_SPARC_16); | ||||
|   case FK_Data_4:                return ((Fixup.getOffset() % 4) | ||||
|                                          ? ELF::R_SPARC_UA32 | ||||
|                                          : ELF::R_SPARC_32); | ||||
|   case FK_Data_8:                return ((Fixup.getOffset() % 8) | ||||
|                                          ? ELF::R_SPARC_UA64 | ||||
|                                          : ELF::R_SPARC_64); | ||||
|   case Sparc::fixup_sparc_hi22:  return ELF::R_SPARC_HI22; | ||||
|   case Sparc::fixup_sparc_lo10:  return ELF::R_SPARC_LO10; | ||||
|   case Sparc::fixup_sparc_h44:   return ELF::R_SPARC_H44; | ||||
|   case Sparc::fixup_sparc_m44:   return ELF::R_SPARC_M44; | ||||
|   case Sparc::fixup_sparc_l44:   return ELF::R_SPARC_L44; | ||||
|   case Sparc::fixup_sparc_hh:    return ELF::R_SPARC_HH22; | ||||
|   case Sparc::fixup_sparc_hm:    return ELF::R_SPARC_HM10; | ||||
|   } | ||||
|   return ELF::R_SPARC_NONE; | ||||
| } | ||||
|  | ||||
| MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS, | ||||
|                                                  bool Is64Bit, | ||||
|                                                  uint8_t OSABI) { | ||||
|   MCELFObjectTargetWriter *MOTW = new SparcELFObjectWriter(Is64Bit, OSABI); | ||||
|   return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/false); | ||||
| } | ||||
| @@ -22,10 +22,32 @@ namespace llvm { | ||||
|       /// branches | ||||
|       fixup_sparc_br22, | ||||
|  | ||||
|       /// fixup_sparc_br22 - 22-bit PC relative relocation for | ||||
|       /// fixup_sparc_br19 - 19-bit PC relative relocation for | ||||
|       /// branches on icc/xcc | ||||
|       fixup_sparc_br19, | ||||
|  | ||||
|       /// fixup_sparc_hi22  - 22-bit fixup corresponding to %hi(foo) | ||||
|       /// for sethi | ||||
|       fixup_sparc_hi22, | ||||
|  | ||||
|       /// fixup_sparc_lo10  - 10-bit fixup corresponding to %lo(foo) | ||||
|       fixup_sparc_lo10, | ||||
|  | ||||
|       /// fixup_sparc_h44  - 22-bit fixup corresponding to %h44(foo) | ||||
|       fixup_sparc_h44, | ||||
|  | ||||
|       /// fixup_sparc_m44  - 10-bit fixup corresponding to %m44(foo) | ||||
|       fixup_sparc_m44, | ||||
|  | ||||
|       /// fixup_sparc_l44  - 12-bit fixup corresponding to %l44(foo) | ||||
|       fixup_sparc_l44, | ||||
|  | ||||
|       /// fixup_sparc_hh  -  22-bit fixup corresponding to %hh(foo) | ||||
|       fixup_sparc_hh, | ||||
|  | ||||
|       /// fixup_sparc_hm  -  10-bit fixup corresponding to %hm(foo) | ||||
|       fixup_sparc_hm, | ||||
|  | ||||
|       // Marker | ||||
|       LastTargetFixupKind, | ||||
|       NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
| //===----------------------------------------------------------------------===// | ||||
|  | ||||
| #define DEBUG_TYPE "mccodeemitter" | ||||
| #include "SparcMCExpr.h" | ||||
| #include "SparcMCTargetDesc.h" | ||||
| #include "MCTargetDesc/SparcFixupKinds.h" | ||||
| #include "llvm/MC/MCCodeEmitter.h" | ||||
| @@ -92,6 +93,41 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, | ||||
|  | ||||
|   assert(MO.isExpr()); | ||||
|   const MCExpr *Expr = MO.getExpr(); | ||||
|   if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) { | ||||
|     switch(SExpr->getKind()) { | ||||
|     default: assert(0 && "Unhandled sparc expression!"); break; | ||||
|     case SparcMCExpr::VK_Sparc_LO: | ||||
|       Fixups.push_back(MCFixup::Create(0, Expr, | ||||
|                                        (MCFixupKind)Sparc::fixup_sparc_lo10)); | ||||
|       break; | ||||
|     case SparcMCExpr::VK_Sparc_HI: | ||||
|       Fixups.push_back(MCFixup::Create(0, Expr, | ||||
|                                        (MCFixupKind)Sparc::fixup_sparc_hi22)); | ||||
|       break; | ||||
|     case SparcMCExpr::VK_Sparc_H44: | ||||
|       Fixups.push_back(MCFixup::Create(0, Expr, | ||||
|                                        (MCFixupKind)Sparc::fixup_sparc_h44)); | ||||
|       break; | ||||
|     case SparcMCExpr::VK_Sparc_M44: | ||||
|       Fixups.push_back(MCFixup::Create(0, Expr, | ||||
|                                        (MCFixupKind)Sparc::fixup_sparc_m44)); | ||||
|       break; | ||||
|     case SparcMCExpr::VK_Sparc_L44: | ||||
|       Fixups.push_back(MCFixup::Create(0, Expr, | ||||
|                                        (MCFixupKind)Sparc::fixup_sparc_l44)); | ||||
|       break; | ||||
|     case SparcMCExpr::VK_Sparc_HH: | ||||
|       Fixups.push_back(MCFixup::Create(0, Expr, | ||||
|                                        (MCFixupKind)Sparc::fixup_sparc_hh)); | ||||
|       break; | ||||
|     case SparcMCExpr::VK_Sparc_HM: | ||||
|       Fixups.push_back(MCFixup::Create(0, Expr, | ||||
|                                        (MCFixupKind)Sparc::fixup_sparc_hm)); | ||||
|       break; | ||||
|     } | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   int64_t Res; | ||||
|   if (Expr->EvaluateAsAbsolute(Res)) | ||||
|     return Res; | ||||
|   | ||||
| @@ -70,15 +70,67 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const | ||||
| bool | ||||
| SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, | ||||
|                                          const MCAsmLayout *Layout) const { | ||||
|   assert(0 && "FIXME: Implement SparcMCExpr::EvaluateAsRelocatableImpl"); | ||||
|   return getSubExpr()->EvaluateAsRelocatable(Res, *Layout); | ||||
| } | ||||
|  | ||||
| static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { | ||||
|   assert(0 && "Implement fixELFSymbolsInTLSFixupsImpl!"); | ||||
| } | ||||
|  | ||||
| void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { | ||||
|   assert(0 && "FIXME: Implement SparcMCExpr::fixELFSymbolsInTLSFixups"); | ||||
|   switch(getKind()) { | ||||
|   default: return; | ||||
|   case VK_Sparc_TLS_GD_HI22: | ||||
|   case VK_Sparc_TLS_GD_LO10: | ||||
|   case VK_Sparc_TLS_GD_ADD: | ||||
|   case VK_Sparc_TLS_GD_CALL: | ||||
|   case VK_Sparc_TLS_LDM_HI22: | ||||
|   case VK_Sparc_TLS_LDM_LO10: | ||||
|   case VK_Sparc_TLS_LDM_ADD: | ||||
|   case VK_Sparc_TLS_LDM_CALL: | ||||
|   case VK_Sparc_TLS_LDO_HIX22: | ||||
|   case VK_Sparc_TLS_LDO_LOX10: | ||||
|   case VK_Sparc_TLS_LDO_ADD: | ||||
|   case VK_Sparc_TLS_IE_HI22: | ||||
|   case VK_Sparc_TLS_IE_LO10: | ||||
|   case VK_Sparc_TLS_IE_LD: | ||||
|   case VK_Sparc_TLS_IE_LDX: | ||||
|   case VK_Sparc_TLS_IE_ADD: | ||||
|   case VK_Sparc_TLS_LE_HIX22: | ||||
|   case VK_Sparc_TLS_LE_LOX10: break; | ||||
|   } | ||||
|   fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); | ||||
| } | ||||
|  | ||||
| // FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps | ||||
| // that method should be made public? | ||||
| // FIXME: really do above: now that at least three other backends are using it. | ||||
| static void AddValueSymbolsImpl(const MCExpr *Value, MCAssembler *Asm) { | ||||
|   switch (Value->getKind()) { | ||||
|   case MCExpr::Target: | ||||
|     llvm_unreachable("Can't handle nested target expr!"); | ||||
|     break; | ||||
|  | ||||
|   case MCExpr::Constant: | ||||
|     break; | ||||
|  | ||||
|   case MCExpr::Binary: { | ||||
|     const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); | ||||
|     AddValueSymbolsImpl(BE->getLHS(), Asm); | ||||
|     AddValueSymbolsImpl(BE->getRHS(), Asm); | ||||
|     break; | ||||
|   } | ||||
|  | ||||
|   case MCExpr::SymbolRef: | ||||
|     Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol()); | ||||
|     break; | ||||
|  | ||||
|   case MCExpr::Unary: | ||||
|     AddValueSymbolsImpl(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm); | ||||
|     break; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void SparcMCExpr::AddValueSymbols(MCAssembler *Asm) const { | ||||
|   assert(0 && "FIXME: Implement SparcMCExpr::AddValueSymbols"); | ||||
|   AddValueSymbolsImpl(getSubExpr(), Asm); | ||||
| } | ||||
|   | ||||
| @@ -89,6 +89,14 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(StringRef TT, Reloc::Model RM, | ||||
|   return X; | ||||
| } | ||||
|  | ||||
| static MCStreamer *createMCStreamer(const Target &T, StringRef TT, | ||||
|                                     MCContext &Context, MCAsmBackend &MAB, | ||||
|                                     raw_ostream &OS, MCCodeEmitter *Emitter, | ||||
|                                     bool RelaxAll, bool NoExecStack) { | ||||
|   SparcTargetELFStreamer *S = new SparcTargetELFStreamer(); | ||||
|   return createELFStreamer(Context, S, MAB, OS, Emitter, RelaxAll, NoExecStack); | ||||
| } | ||||
|  | ||||
| static MCStreamer * | ||||
| createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, | ||||
|                     bool isVerboseAsm, bool useLoc, bool useCFI, | ||||
| @@ -148,6 +156,13 @@ extern "C" void LLVMInitializeSparcTargetMC() { | ||||
|   TargetRegistry::RegisterMCAsmBackend(TheSparcV9Target, | ||||
|                                        createSparcAsmBackend); | ||||
|  | ||||
|   // Register the object streamer. | ||||
|   TargetRegistry::RegisterMCObjectStreamer(TheSparcTarget, | ||||
|                                            createMCStreamer); | ||||
|   TargetRegistry::RegisterMCObjectStreamer(TheSparcV9Target, | ||||
|                                            createMCStreamer); | ||||
|  | ||||
|   // Register the asm streamer. | ||||
|   TargetRegistry::RegisterAsmStreamer(TheSparcTarget, | ||||
|                                       createMCAsmStreamer); | ||||
|   TargetRegistry::RegisterAsmStreamer(TheSparcV9Target, | ||||
|   | ||||
| @@ -14,15 +14,19 @@ | ||||
| #ifndef SPARCMCTARGETDESC_H | ||||
| #define SPARCMCTARGETDESC_H | ||||
|  | ||||
| #include "llvm/Support/DataTypes.h" | ||||
|  | ||||
| namespace llvm { | ||||
| class MCAsmBackend; | ||||
| class MCCodeEmitter; | ||||
| class MCContext; | ||||
| class MCInstrInfo; | ||||
| class MCObjectWriter; | ||||
| class MCRegisterInfo; | ||||
| class MCSubtargetInfo; | ||||
| class Target; | ||||
| class StringRef; | ||||
| class raw_ostream; | ||||
|  | ||||
| extern Target TheSparcTarget; | ||||
| extern Target TheSparcV9Target; | ||||
| @@ -35,7 +39,9 @@ MCAsmBackend *createSparcAsmBackend(const Target &T, | ||||
|                                     const MCRegisterInfo &MRI, | ||||
|                                     StringRef TT, | ||||
|                                     StringRef CPU); | ||||
|  | ||||
| MCObjectWriter *createSparcELFObjectWriter(raw_ostream &OS, | ||||
|                                            bool Is64Bit, | ||||
|                                            uint8_t OSABI); | ||||
| } // End llvm namespace | ||||
|  | ||||
| // Defines symbolic names for Sparc registers.  This defines a mapping from | ||||
|   | ||||
		Reference in New Issue
	
	Block a user