1Pull in r198580 from upstream llvm trunk (by Venkatraman Govindaraju): 2 3 [Sparc] Add ELF Object Writer for Sparc. 4 5Introduced here: http://svnweb.freebsd.org/changeset/base/262261 6 7Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp 8=================================================================== 9--- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp 10+++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp 11@@ -12,6 +12,7 @@ 12 //===----------------------------------------------------------------------===// 13 14 #define DEBUG_TYPE "mccodeemitter" 15+#include "SparcMCExpr.h" 16 #include "SparcMCTargetDesc.h" 17 #include "MCTargetDesc/SparcFixupKinds.h" 18 #include "llvm/MC/MCCodeEmitter.h" 19@@ -92,6 +93,41 @@ getMachineOpValue(const MCInst &MI, const MCOperan 20 21 assert(MO.isExpr()); 22 const MCExpr *Expr = MO.getExpr(); 23+ if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) { 24+ switch(SExpr->getKind()) { 25+ default: assert(0 && "Unhandled sparc expression!"); break; 26+ case SparcMCExpr::VK_Sparc_LO: 27+ Fixups.push_back(MCFixup::Create(0, Expr, 28+ (MCFixupKind)Sparc::fixup_sparc_lo10)); 29+ break; 30+ case SparcMCExpr::VK_Sparc_HI: 31+ Fixups.push_back(MCFixup::Create(0, Expr, 32+ (MCFixupKind)Sparc::fixup_sparc_hi22)); 33+ break; 34+ case SparcMCExpr::VK_Sparc_H44: 35+ Fixups.push_back(MCFixup::Create(0, Expr, 36+ (MCFixupKind)Sparc::fixup_sparc_h44)); 37+ break; 38+ case SparcMCExpr::VK_Sparc_M44: 39+ Fixups.push_back(MCFixup::Create(0, Expr, 40+ (MCFixupKind)Sparc::fixup_sparc_m44)); 41+ break; 42+ case SparcMCExpr::VK_Sparc_L44: 43+ Fixups.push_back(MCFixup::Create(0, Expr, 44+ (MCFixupKind)Sparc::fixup_sparc_l44)); 45+ break; 46+ case SparcMCExpr::VK_Sparc_HH: 47+ Fixups.push_back(MCFixup::Create(0, Expr, 48+ (MCFixupKind)Sparc::fixup_sparc_hh)); 49+ break; 50+ case SparcMCExpr::VK_Sparc_HM: 51+ Fixups.push_back(MCFixup::Create(0, Expr, 52+ (MCFixupKind)Sparc::fixup_sparc_hm)); 53+ break; 54+ } 55+ return 0; 56+ } 57+ 58 int64_t Res; 59 if (Expr->EvaluateAsAbsolute(Res)) 60 return Res; 61Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp 62=================================================================== 63--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp 64+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp 65@@ -89,6 +89,14 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(S 66 return X; 67 } 68 69+static MCStreamer *createMCStreamer(const Target &T, StringRef TT, 70+ MCContext &Context, MCAsmBackend &MAB, 71+ raw_ostream &OS, MCCodeEmitter *Emitter, 72+ bool RelaxAll, bool NoExecStack) { 73+ SparcTargetELFStreamer *S = new SparcTargetELFStreamer(); 74+ return createELFStreamer(Context, S, MAB, OS, Emitter, RelaxAll, NoExecStack); 75+} 76+ 77 static MCStreamer * 78 createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, 79 bool isVerboseAsm, bool useLoc, bool useCFI, 80@@ -148,6 +156,13 @@ extern "C" void LLVMInitializeSparcTargetMC() { 81 TargetRegistry::RegisterMCAsmBackend(TheSparcV9Target, 82 createSparcAsmBackend); 83 84+ // Register the object streamer. 85+ TargetRegistry::RegisterMCObjectStreamer(TheSparcTarget, 86+ createMCStreamer); 87+ TargetRegistry::RegisterMCObjectStreamer(TheSparcV9Target, 88+ createMCStreamer); 89+ 90+ // Register the asm streamer. 91 TargetRegistry::RegisterAsmStreamer(TheSparcTarget, 92 createMCAsmStreamer); 93 TargetRegistry::RegisterAsmStreamer(TheSparcV9Target, 94Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp 95=================================================================== 96--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp 97+++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp 98@@ -10,6 +10,7 @@ 99 #include "llvm/MC/MCAsmBackend.h" 100 #include "MCTargetDesc/SparcMCTargetDesc.h" 101 #include "MCTargetDesc/SparcFixupKinds.h" 102+#include "llvm/MC/MCELFObjectWriter.h" 103 #include "llvm/MC/MCFixupKindInfo.h" 104 #include "llvm/MC/MCObjectWriter.h" 105 #include "llvm/Support/TargetRegistry.h" 106@@ -16,11 +17,43 @@ 107 108 using namespace llvm; 109 110+static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { 111+ switch (Kind) { 112+ default: 113+ llvm_unreachable("Unknown fixup kind!"); 114+ case FK_Data_1: 115+ case FK_Data_2: 116+ case FK_Data_4: 117+ case FK_Data_8: 118+ return Value; 119+ case Sparc::fixup_sparc_call30: 120+ return Value & 0x3fffffff; 121+ case Sparc::fixup_sparc_br22: 122+ return Value & 0x3fffff; 123+ case Sparc::fixup_sparc_br19: 124+ return Value & 0x1ffff; 125+ case Sparc::fixup_sparc_hi22: 126+ return (Value >> 10) & 0x3fffff; 127+ case Sparc::fixup_sparc_lo10: 128+ return Value & 0x3ff; 129+ case Sparc::fixup_sparc_h44: 130+ return (Value >> 22) & 0x3fffff; 131+ case Sparc::fixup_sparc_m44: 132+ return (Value >> 12) & 0x3ff; 133+ case Sparc::fixup_sparc_l44: 134+ return Value & 0xfff; 135+ case Sparc::fixup_sparc_hh: 136+ return (Value >> 42) & 0x3fffff; 137+ case Sparc::fixup_sparc_hm: 138+ return (Value >>32) & 0x3ff; 139+ } 140+} 141+ 142 namespace { 143 class SparcAsmBackend : public MCAsmBackend { 144- 145+ const Target &TheTarget; 146 public: 147- SparcAsmBackend(const Target &T) : MCAsmBackend() {} 148+ SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {} 149 150 unsigned getNumFixupKinds() const { 151 return Sparc::NumTargetFixupKinds; 152@@ -31,7 +64,14 @@ namespace { 153 // name offset bits flags 154 { "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel }, 155 { "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel }, 156- { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel } 157+ { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel }, 158+ { "fixup_sparc_hi22", 0, 22, 0 }, 159+ { "fixup_sparc_lo10", 0, 10, 0 }, 160+ { "fixup_sparc_h44", 0, 22, 0 }, 161+ { "fixup_sparc_m44", 0, 10, 0 }, 162+ { "fixup_sparc_l44", 0, 12, 0 }, 163+ { "fixup_sparc_hh", 0, 21, 0 }, 164+ { "fixup_sparc_hm", 0, 10, 0 }, 165 }; 166 167 if (Kind < FirstTargetFixupKind) 168@@ -68,21 +108,38 @@ namespace { 169 OW->Write8(0); 170 return true; 171 } 172+ 173+ bool is64Bit() const { 174+ StringRef name = TheTarget.getName(); 175+ return name == "sparcv9"; 176+ } 177 }; 178 179 class ELFSparcAsmBackend : public SparcAsmBackend { 180+ Triple::OSType OSType; 181 public: 182 ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) : 183- SparcAsmBackend(T) { } 184+ SparcAsmBackend(T), OSType(OSType) { } 185 186 void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 187 uint64_t Value) const { 188- assert(0 && "applyFixup not implemented yet"); 189+ 190+ Value = adjustFixupValue(Fixup.getKind(), Value); 191+ if (!Value) return; // Doesn't change encoding. 192+ 193+ unsigned Offset = Fixup.getOffset(); 194+ 195+ // For each byte of the fragment that the fixup touches, mask in the bits 196+ // from the fixup value. The Value has been "split up" into the 197+ // appropriate bitfields above. 198+ for (unsigned i = 0; i != 4; ++i) 199+ Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff); 200+ 201 } 202 203 MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 204- assert(0 && "Object Writer not implemented yet"); 205- return 0; 206+ uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType); 207+ return createSparcELFObjectWriter(OS, is64Bit(), OSABI); 208 } 209 210 virtual bool doesSectionRequireSymbols(const MCSection &Section) const { 211Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h 212=================================================================== 213--- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h 214+++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h 215@@ -22,10 +22,32 @@ namespace llvm { 216 /// branches 217 fixup_sparc_br22, 218 219- /// fixup_sparc_br22 - 22-bit PC relative relocation for 220+ /// fixup_sparc_br19 - 19-bit PC relative relocation for 221 /// branches on icc/xcc 222 fixup_sparc_br19, 223 224+ /// fixup_sparc_hi22 - 22-bit fixup corresponding to %hi(foo) 225+ /// for sethi 226+ fixup_sparc_hi22, 227+ 228+ /// fixup_sparc_lo10 - 10-bit fixup corresponding to %lo(foo) 229+ fixup_sparc_lo10, 230+ 231+ /// fixup_sparc_h44 - 22-bit fixup corresponding to %h44(foo) 232+ fixup_sparc_h44, 233+ 234+ /// fixup_sparc_m44 - 10-bit fixup corresponding to %m44(foo) 235+ fixup_sparc_m44, 236+ 237+ /// fixup_sparc_l44 - 12-bit fixup corresponding to %l44(foo) 238+ fixup_sparc_l44, 239+ 240+ /// fixup_sparc_hh - 22-bit fixup corresponding to %hh(foo) 241+ fixup_sparc_hh, 242+ 243+ /// fixup_sparc_hm - 10-bit fixup corresponding to %hm(foo) 244+ fixup_sparc_hm, 245+ 246 // Marker 247 LastTargetFixupKind, 248 NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind 249Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp 250=================================================================== 251--- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp 252+++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp 253@@ -0,0 +1,86 @@ 254+//===-- SparcELFObjectWriter.cpp - Sparc ELF Writer -----------------------===// 255+// 256+// The LLVM Compiler Infrastructure 257+// 258+// This file is distributed under the University of Illinois Open Source 259+// License. See LICENSE.TXT for details. 260+// 261+//===----------------------------------------------------------------------===// 262+ 263+#include "MCTargetDesc/SparcMCTargetDesc.h" 264+#include "MCTargetDesc/SparcFixupKinds.h" 265+#include "llvm/ADT/STLExtras.h" 266+#include "llvm/MC/MCELFObjectWriter.h" 267+#include "llvm/MC/MCExpr.h" 268+#include "llvm/MC/MCValue.h" 269+#include "llvm/Support/ErrorHandling.h" 270+ 271+using namespace llvm; 272+ 273+namespace { 274+ class SparcELFObjectWriter : public MCELFObjectTargetWriter { 275+ public: 276+ SparcELFObjectWriter(bool Is64Bit, uint8_t OSABI) 277+ : MCELFObjectTargetWriter(Is64Bit, OSABI, 278+ Is64Bit ? ELF::EM_SPARCV9 : ELF::EM_SPARC, 279+ /*HasRelocationAddend*/ true) {} 280+ 281+ virtual ~SparcELFObjectWriter() {} 282+ protected: 283+ virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 284+ bool IsPCRel, bool IsRelocWithSymbol, 285+ int64_t Addend) const; 286+ 287+ }; 288+} 289+ 290+ 291+unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target, 292+ const MCFixup &Fixup, 293+ bool IsPCRel, 294+ bool IsRelocWithSymbol, 295+ int64_t Addend) const { 296+ if (IsPCRel) { 297+ switch((unsigned)Fixup.getKind()) { 298+ default: 299+ llvm_unreachable("Unimplemented fixup -> relocation"); 300+ case FK_Data_1: return ELF::R_SPARC_DISP8; 301+ case FK_Data_2: return ELF::R_SPARC_DISP16; 302+ case FK_Data_4: return ELF::R_SPARC_DISP32; 303+ case FK_Data_8: return ELF::R_SPARC_DISP64; 304+ case Sparc::fixup_sparc_call30: return ELF::R_SPARC_WDISP30; 305+ case Sparc::fixup_sparc_br22: return ELF::R_SPARC_WDISP22; 306+ case Sparc::fixup_sparc_br19: return ELF::R_SPARC_WDISP19; 307+ } 308+ } 309+ 310+ switch((unsigned)Fixup.getKind()) { 311+ default: 312+ llvm_unreachable("Unimplemented fixup -> relocation"); 313+ case FK_Data_1: return ELF::R_SPARC_8; 314+ case FK_Data_2: return ((Fixup.getOffset() % 2) 315+ ? ELF::R_SPARC_UA16 316+ : ELF::R_SPARC_16); 317+ case FK_Data_4: return ((Fixup.getOffset() % 4) 318+ ? ELF::R_SPARC_UA32 319+ : ELF::R_SPARC_32); 320+ case FK_Data_8: return ((Fixup.getOffset() % 8) 321+ ? ELF::R_SPARC_UA64 322+ : ELF::R_SPARC_64); 323+ case Sparc::fixup_sparc_hi22: return ELF::R_SPARC_HI22; 324+ case Sparc::fixup_sparc_lo10: return ELF::R_SPARC_LO10; 325+ case Sparc::fixup_sparc_h44: return ELF::R_SPARC_H44; 326+ case Sparc::fixup_sparc_m44: return ELF::R_SPARC_M44; 327+ case Sparc::fixup_sparc_l44: return ELF::R_SPARC_L44; 328+ case Sparc::fixup_sparc_hh: return ELF::R_SPARC_HH22; 329+ case Sparc::fixup_sparc_hm: return ELF::R_SPARC_HM10; 330+ } 331+ return ELF::R_SPARC_NONE; 332+} 333+ 334+MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS, 335+ bool Is64Bit, 336+ uint8_t OSABI) { 337+ MCELFObjectTargetWriter *MOTW = new SparcELFObjectWriter(Is64Bit, OSABI); 338+ return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); 339+} 340Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h 341=================================================================== 342--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h 343+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h 344@@ -14,15 +14,19 @@ 345 #ifndef SPARCMCTARGETDESC_H 346 #define SPARCMCTARGETDESC_H 347 348+#include "llvm/Support/DataTypes.h" 349+ 350 namespace llvm { 351 class MCAsmBackend; 352 class MCCodeEmitter; 353 class MCContext; 354 class MCInstrInfo; 355+class MCObjectWriter; 356 class MCRegisterInfo; 357 class MCSubtargetInfo; 358 class Target; 359 class StringRef; 360+class raw_ostream; 361 362 extern Target TheSparcTarget; 363 extern Target TheSparcV9Target; 364@@ -35,7 +39,9 @@ MCAsmBackend *createSparcAsmBackend(const Target & 365 const MCRegisterInfo &MRI, 366 StringRef TT, 367 StringRef CPU); 368- 369+MCObjectWriter *createSparcELFObjectWriter(raw_ostream &OS, 370+ bool Is64Bit, 371+ uint8_t OSABI); 372 } // End llvm namespace 373 374 // Defines symbolic names for Sparc registers. This defines a mapping from 375Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp 376=================================================================== 377--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp 378+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp 379@@ -70,15 +70,67 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const 380 bool 381 SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, 382 const MCAsmLayout *Layout) const { 383- assert(0 && "FIXME: Implement SparcMCExpr::EvaluateAsRelocatableImpl"); 384 return getSubExpr()->EvaluateAsRelocatable(Res, *Layout); 385 } 386 387+static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { 388+ assert(0 && "Implement fixELFSymbolsInTLSFixupsImpl!"); 389+} 390 391 void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { 392- assert(0 && "FIXME: Implement SparcMCExpr::fixELFSymbolsInTLSFixups"); 393+ switch(getKind()) { 394+ default: return; 395+ case VK_Sparc_TLS_GD_HI22: 396+ case VK_Sparc_TLS_GD_LO10: 397+ case VK_Sparc_TLS_GD_ADD: 398+ case VK_Sparc_TLS_GD_CALL: 399+ case VK_Sparc_TLS_LDM_HI22: 400+ case VK_Sparc_TLS_LDM_LO10: 401+ case VK_Sparc_TLS_LDM_ADD: 402+ case VK_Sparc_TLS_LDM_CALL: 403+ case VK_Sparc_TLS_LDO_HIX22: 404+ case VK_Sparc_TLS_LDO_LOX10: 405+ case VK_Sparc_TLS_LDO_ADD: 406+ case VK_Sparc_TLS_IE_HI22: 407+ case VK_Sparc_TLS_IE_LO10: 408+ case VK_Sparc_TLS_IE_LD: 409+ case VK_Sparc_TLS_IE_LDX: 410+ case VK_Sparc_TLS_IE_ADD: 411+ case VK_Sparc_TLS_LE_HIX22: 412+ case VK_Sparc_TLS_LE_LOX10: break; 413+ } 414+ fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); 415 } 416 417+// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps 418+// that method should be made public? 419+// FIXME: really do above: now that at least three other backends are using it. 420+static void AddValueSymbolsImpl(const MCExpr *Value, MCAssembler *Asm) { 421+ switch (Value->getKind()) { 422+ case MCExpr::Target: 423+ llvm_unreachable("Can't handle nested target expr!"); 424+ break; 425+ 426+ case MCExpr::Constant: 427+ break; 428+ 429+ case MCExpr::Binary: { 430+ const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); 431+ AddValueSymbolsImpl(BE->getLHS(), Asm); 432+ AddValueSymbolsImpl(BE->getRHS(), Asm); 433+ break; 434+ } 435+ 436+ case MCExpr::SymbolRef: 437+ Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol()); 438+ break; 439+ 440+ case MCExpr::Unary: 441+ AddValueSymbolsImpl(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm); 442+ break; 443+ } 444+} 445+ 446 void SparcMCExpr::AddValueSymbols(MCAssembler *Asm) const { 447- assert(0 && "FIXME: Implement SparcMCExpr::AddValueSymbols"); 448+ AddValueSymbolsImpl(getSubExpr(), Asm); 449 } 450Index: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt 451=================================================================== 452--- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt 453+++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt 454@@ -1,5 +1,6 @@ 455 add_llvm_library(LLVMSparcDesc 456 SparcAsmBackend.cpp 457+ SparcELFObjectWriter.cpp 458 SparcMCAsmInfo.cpp 459 SparcMCCodeEmitter.cpp 460 SparcMCTargetDesc.cpp 461