1263320SdimPull in r198580 from upstream llvm trunk (by Venkatraman Govindaraju):
2263320Sdim
3263320Sdim  [Sparc] Add ELF Object Writer for Sparc. 
4263320Sdim
5269012SemasteIntroduced here: http://svnweb.freebsd.org/changeset/base/262261
6263320Sdim
7263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
8263320Sdim===================================================================
9263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
10263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
11263320Sdim@@ -12,6 +12,7 @@
12263320Sdim //===----------------------------------------------------------------------===//
13263320Sdim 
14263320Sdim #define DEBUG_TYPE "mccodeemitter"
15263320Sdim+#include "SparcMCExpr.h"
16263320Sdim #include "SparcMCTargetDesc.h"
17263320Sdim #include "MCTargetDesc/SparcFixupKinds.h"
18263320Sdim #include "llvm/MC/MCCodeEmitter.h"
19263320Sdim@@ -92,6 +93,41 @@ getMachineOpValue(const MCInst &MI, const MCOperan
20263320Sdim 
21263320Sdim   assert(MO.isExpr());
22263320Sdim   const MCExpr *Expr = MO.getExpr();
23263320Sdim+  if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
24263320Sdim+    switch(SExpr->getKind()) {
25263320Sdim+    default: assert(0 && "Unhandled sparc expression!"); break;
26263320Sdim+    case SparcMCExpr::VK_Sparc_LO:
27263320Sdim+      Fixups.push_back(MCFixup::Create(0, Expr,
28263320Sdim+                                       (MCFixupKind)Sparc::fixup_sparc_lo10));
29263320Sdim+      break;
30263320Sdim+    case SparcMCExpr::VK_Sparc_HI:
31263320Sdim+      Fixups.push_back(MCFixup::Create(0, Expr,
32263320Sdim+                                       (MCFixupKind)Sparc::fixup_sparc_hi22));
33263320Sdim+      break;
34263320Sdim+    case SparcMCExpr::VK_Sparc_H44:
35263320Sdim+      Fixups.push_back(MCFixup::Create(0, Expr,
36263320Sdim+                                       (MCFixupKind)Sparc::fixup_sparc_h44));
37263320Sdim+      break;
38263320Sdim+    case SparcMCExpr::VK_Sparc_M44:
39263320Sdim+      Fixups.push_back(MCFixup::Create(0, Expr,
40263320Sdim+                                       (MCFixupKind)Sparc::fixup_sparc_m44));
41263320Sdim+      break;
42263320Sdim+    case SparcMCExpr::VK_Sparc_L44:
43263320Sdim+      Fixups.push_back(MCFixup::Create(0, Expr,
44263320Sdim+                                       (MCFixupKind)Sparc::fixup_sparc_l44));
45263320Sdim+      break;
46263320Sdim+    case SparcMCExpr::VK_Sparc_HH:
47263320Sdim+      Fixups.push_back(MCFixup::Create(0, Expr,
48263320Sdim+                                       (MCFixupKind)Sparc::fixup_sparc_hh));
49263320Sdim+      break;
50263320Sdim+    case SparcMCExpr::VK_Sparc_HM:
51263320Sdim+      Fixups.push_back(MCFixup::Create(0, Expr,
52263320Sdim+                                       (MCFixupKind)Sparc::fixup_sparc_hm));
53263320Sdim+      break;
54263320Sdim+    }
55263320Sdim+    return 0;
56263320Sdim+  }
57263320Sdim+
58263320Sdim   int64_t Res;
59263320Sdim   if (Expr->EvaluateAsAbsolute(Res))
60263320Sdim     return Res;
61263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
62263320Sdim===================================================================
63263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
64263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
65263320Sdim@@ -89,6 +89,14 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(S
66263320Sdim   return X;
67263320Sdim }
68263320Sdim 
69263320Sdim+static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
70263320Sdim+                                    MCContext &Context, MCAsmBackend &MAB,
71263320Sdim+                                    raw_ostream &OS, MCCodeEmitter *Emitter,
72263320Sdim+                                    bool RelaxAll, bool NoExecStack) {
73263320Sdim+  SparcTargetELFStreamer *S = new SparcTargetELFStreamer();
74263320Sdim+  return createELFStreamer(Context, S, MAB, OS, Emitter, RelaxAll, NoExecStack);
75263320Sdim+}
76263320Sdim+
77263320Sdim static MCStreamer *
78263320Sdim createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
79263320Sdim                     bool isVerboseAsm, bool useLoc, bool useCFI,
80263320Sdim@@ -148,6 +156,13 @@ extern "C" void LLVMInitializeSparcTargetMC() {
81263320Sdim   TargetRegistry::RegisterMCAsmBackend(TheSparcV9Target,
82263320Sdim                                        createSparcAsmBackend);
83263320Sdim 
84263320Sdim+  // Register the object streamer.
85263320Sdim+  TargetRegistry::RegisterMCObjectStreamer(TheSparcTarget,
86263320Sdim+                                           createMCStreamer);
87263320Sdim+  TargetRegistry::RegisterMCObjectStreamer(TheSparcV9Target,
88263320Sdim+                                           createMCStreamer);
89263320Sdim+
90263320Sdim+  // Register the asm streamer.
91263320Sdim   TargetRegistry::RegisterAsmStreamer(TheSparcTarget,
92263320Sdim                                       createMCAsmStreamer);
93263320Sdim   TargetRegistry::RegisterAsmStreamer(TheSparcV9Target,
94263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
95263320Sdim===================================================================
96263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
97263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
98263320Sdim@@ -10,6 +10,7 @@
99263320Sdim #include "llvm/MC/MCAsmBackend.h"
100263320Sdim #include "MCTargetDesc/SparcMCTargetDesc.h"
101263320Sdim #include "MCTargetDesc/SparcFixupKinds.h"
102263320Sdim+#include "llvm/MC/MCELFObjectWriter.h"
103263320Sdim #include "llvm/MC/MCFixupKindInfo.h"
104263320Sdim #include "llvm/MC/MCObjectWriter.h"
105263320Sdim #include "llvm/Support/TargetRegistry.h"
106263320Sdim@@ -16,11 +17,43 @@
107263320Sdim 
108263320Sdim using namespace llvm;
109263320Sdim 
110263320Sdim+static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
111263320Sdim+  switch (Kind) {
112263320Sdim+  default:
113263320Sdim+    llvm_unreachable("Unknown fixup kind!");
114263320Sdim+  case FK_Data_1:
115263320Sdim+  case FK_Data_2:
116263320Sdim+  case FK_Data_4:
117263320Sdim+  case FK_Data_8:
118263320Sdim+    return Value;
119263320Sdim+  case Sparc::fixup_sparc_call30:
120263320Sdim+    return Value & 0x3fffffff;
121263320Sdim+  case Sparc::fixup_sparc_br22:
122263320Sdim+    return Value & 0x3fffff;
123263320Sdim+  case Sparc::fixup_sparc_br19:
124263320Sdim+    return Value & 0x1ffff;
125263320Sdim+  case Sparc::fixup_sparc_hi22:
126263320Sdim+    return (Value >> 10) & 0x3fffff;
127263320Sdim+  case Sparc::fixup_sparc_lo10:
128263320Sdim+    return Value & 0x3ff;
129263320Sdim+  case Sparc::fixup_sparc_h44:
130263320Sdim+    return (Value >> 22) & 0x3fffff;
131263320Sdim+  case Sparc::fixup_sparc_m44:
132263320Sdim+    return (Value >> 12) & 0x3ff;
133263320Sdim+  case Sparc::fixup_sparc_l44:
134263320Sdim+    return Value & 0xfff;
135263320Sdim+  case Sparc::fixup_sparc_hh:
136263320Sdim+    return (Value >> 42) & 0x3fffff;
137263320Sdim+  case Sparc::fixup_sparc_hm:
138263320Sdim+    return (Value >>32) & 0x3ff;
139263320Sdim+  }
140263320Sdim+}
141263320Sdim+
142263320Sdim namespace {
143263320Sdim   class SparcAsmBackend : public MCAsmBackend {
144263320Sdim-
145263320Sdim+    const Target &TheTarget;
146263320Sdim   public:
147263320Sdim-    SparcAsmBackend(const Target &T) : MCAsmBackend() {}
148263320Sdim+    SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {}
149263320Sdim 
150263320Sdim     unsigned getNumFixupKinds() const {
151263320Sdim       return Sparc::NumTargetFixupKinds;
152263320Sdim@@ -31,7 +64,14 @@ namespace {
153263320Sdim         // name                    offset bits  flags
154263320Sdim         { "fixup_sparc_call30",     0,     30,  MCFixupKindInfo::FKF_IsPCRel },
155263320Sdim         { "fixup_sparc_br22",       0,     22,  MCFixupKindInfo::FKF_IsPCRel },
156263320Sdim-        { "fixup_sparc_br19",       0,     19,  MCFixupKindInfo::FKF_IsPCRel }
157263320Sdim+        { "fixup_sparc_br19",       0,     19,  MCFixupKindInfo::FKF_IsPCRel },
158263320Sdim+        { "fixup_sparc_hi22",       0,     22,  0 },
159263320Sdim+        { "fixup_sparc_lo10",       0,     10,  0 },
160263320Sdim+        { "fixup_sparc_h44",        0,     22,  0 },
161263320Sdim+        { "fixup_sparc_m44",        0,     10,  0 },
162263320Sdim+        { "fixup_sparc_l44",        0,     12,  0 },
163263320Sdim+        { "fixup_sparc_hh",         0,     21,  0 },
164263320Sdim+        { "fixup_sparc_hm",         0,     10,  0 },
165263320Sdim       };
166263320Sdim 
167263320Sdim       if (Kind < FirstTargetFixupKind)
168263320Sdim@@ -68,21 +108,38 @@ namespace {
169263320Sdim         OW->Write8(0);
170263320Sdim       return true;
171263320Sdim     }
172263320Sdim+
173263320Sdim+    bool is64Bit() const {
174263320Sdim+      StringRef name = TheTarget.getName();
175263320Sdim+      return name == "sparcv9";
176263320Sdim+    }
177263320Sdim   };
178263320Sdim 
179263320Sdim   class ELFSparcAsmBackend : public SparcAsmBackend {
180263320Sdim+    Triple::OSType OSType;
181263320Sdim   public:
182263320Sdim     ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) :
183263320Sdim-      SparcAsmBackend(T) { }
184263320Sdim+      SparcAsmBackend(T), OSType(OSType) { }
185263320Sdim 
186263320Sdim     void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
187263320Sdim                     uint64_t Value) const {
188263320Sdim-      assert(0 && "applyFixup not implemented yet");
189263320Sdim+
190263320Sdim+      Value = adjustFixupValue(Fixup.getKind(), Value);
191263320Sdim+      if (!Value) return;           // Doesn't change encoding.
192263320Sdim+
193263320Sdim+      unsigned Offset = Fixup.getOffset();
194263320Sdim+
195263320Sdim+      // For each byte of the fragment that the fixup touches, mask in the bits
196263320Sdim+      // from the fixup value. The Value has been "split up" into the
197263320Sdim+      // appropriate bitfields above.
198263320Sdim+      for (unsigned i = 0; i != 4; ++i)
199263320Sdim+        Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff);
200263320Sdim+
201263320Sdim     }
202263320Sdim 
203263320Sdim     MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
204263320Sdim-      assert(0 && "Object Writer not implemented yet");
205263320Sdim-      return 0;
206263320Sdim+      uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
207263320Sdim+      return createSparcELFObjectWriter(OS, is64Bit(), OSABI);
208263320Sdim     }
209263320Sdim 
210263320Sdim     virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
211263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
212263320Sdim===================================================================
213263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
214263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
215263320Sdim@@ -22,10 +22,32 @@ namespace llvm {
216263320Sdim       /// branches
217263320Sdim       fixup_sparc_br22,
218263320Sdim 
219263320Sdim-      /// fixup_sparc_br22 - 22-bit PC relative relocation for
220263320Sdim+      /// fixup_sparc_br19 - 19-bit PC relative relocation for
221263320Sdim       /// branches on icc/xcc
222263320Sdim       fixup_sparc_br19,
223263320Sdim 
224263320Sdim+      /// fixup_sparc_hi22  - 22-bit fixup corresponding to %hi(foo)
225263320Sdim+      /// for sethi
226263320Sdim+      fixup_sparc_hi22,
227263320Sdim+
228263320Sdim+      /// fixup_sparc_lo10  - 10-bit fixup corresponding to %lo(foo)
229263320Sdim+      fixup_sparc_lo10,
230263320Sdim+
231263320Sdim+      /// fixup_sparc_h44  - 22-bit fixup corresponding to %h44(foo)
232263320Sdim+      fixup_sparc_h44,
233263320Sdim+
234263320Sdim+      /// fixup_sparc_m44  - 10-bit fixup corresponding to %m44(foo)
235263320Sdim+      fixup_sparc_m44,
236263320Sdim+
237263320Sdim+      /// fixup_sparc_l44  - 12-bit fixup corresponding to %l44(foo)
238263320Sdim+      fixup_sparc_l44,
239263320Sdim+
240263320Sdim+      /// fixup_sparc_hh  -  22-bit fixup corresponding to %hh(foo)
241263320Sdim+      fixup_sparc_hh,
242263320Sdim+
243263320Sdim+      /// fixup_sparc_hm  -  10-bit fixup corresponding to %hm(foo)
244263320Sdim+      fixup_sparc_hm,
245263320Sdim+
246263320Sdim       // Marker
247263320Sdim       LastTargetFixupKind,
248263320Sdim       NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
249263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
250263320Sdim===================================================================
251263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
252263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
253263320Sdim@@ -0,0 +1,86 @@
254263320Sdim+//===-- SparcELFObjectWriter.cpp - Sparc ELF Writer -----------------------===//
255263320Sdim+//
256263320Sdim+//                     The LLVM Compiler Infrastructure
257263320Sdim+//
258263320Sdim+// This file is distributed under the University of Illinois Open Source
259263320Sdim+// License. See LICENSE.TXT for details.
260263320Sdim+//
261263320Sdim+//===----------------------------------------------------------------------===//
262263320Sdim+
263263320Sdim+#include "MCTargetDesc/SparcMCTargetDesc.h"
264263320Sdim+#include "MCTargetDesc/SparcFixupKinds.h"
265263320Sdim+#include "llvm/ADT/STLExtras.h"
266263320Sdim+#include "llvm/MC/MCELFObjectWriter.h"
267263320Sdim+#include "llvm/MC/MCExpr.h"
268263320Sdim+#include "llvm/MC/MCValue.h"
269263320Sdim+#include "llvm/Support/ErrorHandling.h"
270263320Sdim+
271263320Sdim+using namespace llvm;
272263320Sdim+
273263320Sdim+namespace {
274263320Sdim+  class SparcELFObjectWriter : public MCELFObjectTargetWriter {
275263320Sdim+  public:
276263320Sdim+    SparcELFObjectWriter(bool Is64Bit, uint8_t OSABI)
277263320Sdim+      : MCELFObjectTargetWriter(Is64Bit, OSABI,
278263320Sdim+                                Is64Bit ?  ELF::EM_SPARCV9 : ELF::EM_SPARC,
279263320Sdim+                                /*HasRelocationAddend*/ true) {}
280263320Sdim+
281263320Sdim+    virtual ~SparcELFObjectWriter() {}
282263320Sdim+  protected:
283263320Sdim+    virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
284263320Sdim+                                  bool IsPCRel, bool IsRelocWithSymbol,
285263320Sdim+                                  int64_t Addend) const;
286263320Sdim+
287263320Sdim+  };
288263320Sdim+}
289263320Sdim+
290263320Sdim+
291263320Sdim+unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target,
292263320Sdim+                                            const MCFixup &Fixup,
293263320Sdim+                                            bool IsPCRel,
294263320Sdim+                                            bool IsRelocWithSymbol,
295263320Sdim+                                            int64_t Addend) const {
296263320Sdim+  if (IsPCRel) {
297263320Sdim+    switch((unsigned)Fixup.getKind()) {
298263320Sdim+    default:
299263320Sdim+      llvm_unreachable("Unimplemented fixup -> relocation");
300263320Sdim+    case FK_Data_1:                  return ELF::R_SPARC_DISP8;
301263320Sdim+    case FK_Data_2:                  return ELF::R_SPARC_DISP16;
302263320Sdim+    case FK_Data_4:                  return ELF::R_SPARC_DISP32;
303263320Sdim+    case FK_Data_8:                  return ELF::R_SPARC_DISP64;
304263320Sdim+    case Sparc::fixup_sparc_call30:  return ELF::R_SPARC_WDISP30;
305263320Sdim+    case Sparc::fixup_sparc_br22:    return ELF::R_SPARC_WDISP22;
306263320Sdim+    case Sparc::fixup_sparc_br19:    return ELF::R_SPARC_WDISP19;
307263320Sdim+    }
308263320Sdim+  }
309263320Sdim+
310263320Sdim+  switch((unsigned)Fixup.getKind()) {
311263320Sdim+  default:
312263320Sdim+    llvm_unreachable("Unimplemented fixup -> relocation");
313263320Sdim+  case FK_Data_1:                return ELF::R_SPARC_8;
314263320Sdim+  case FK_Data_2:                return ((Fixup.getOffset() % 2)
315263320Sdim+                                         ? ELF::R_SPARC_UA16
316263320Sdim+                                         : ELF::R_SPARC_16);
317263320Sdim+  case FK_Data_4:                return ((Fixup.getOffset() % 4)
318263320Sdim+                                         ? ELF::R_SPARC_UA32
319263320Sdim+                                         : ELF::R_SPARC_32);
320263320Sdim+  case FK_Data_8:                return ((Fixup.getOffset() % 8)
321263320Sdim+                                         ? ELF::R_SPARC_UA64
322263320Sdim+                                         : ELF::R_SPARC_64);
323263320Sdim+  case Sparc::fixup_sparc_hi22:  return ELF::R_SPARC_HI22;
324263320Sdim+  case Sparc::fixup_sparc_lo10:  return ELF::R_SPARC_LO10;
325263320Sdim+  case Sparc::fixup_sparc_h44:   return ELF::R_SPARC_H44;
326263320Sdim+  case Sparc::fixup_sparc_m44:   return ELF::R_SPARC_M44;
327263320Sdim+  case Sparc::fixup_sparc_l44:   return ELF::R_SPARC_L44;
328263320Sdim+  case Sparc::fixup_sparc_hh:    return ELF::R_SPARC_HH22;
329263320Sdim+  case Sparc::fixup_sparc_hm:    return ELF::R_SPARC_HM10;
330263320Sdim+  }
331263320Sdim+  return ELF::R_SPARC_NONE;
332263320Sdim+}
333263320Sdim+
334263320Sdim+MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS,
335263320Sdim+                                                 bool Is64Bit,
336263320Sdim+                                                 uint8_t OSABI) {
337263320Sdim+  MCELFObjectTargetWriter *MOTW = new SparcELFObjectWriter(Is64Bit, OSABI);
338263320Sdim+  return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/false);
339263320Sdim+}
340263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
341263320Sdim===================================================================
342263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
343263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
344263320Sdim@@ -14,15 +14,19 @@
345263320Sdim #ifndef SPARCMCTARGETDESC_H
346263320Sdim #define SPARCMCTARGETDESC_H
347263320Sdim 
348263320Sdim+#include "llvm/Support/DataTypes.h"
349263320Sdim+
350263320Sdim namespace llvm {
351263320Sdim class MCAsmBackend;
352263320Sdim class MCCodeEmitter;
353263320Sdim class MCContext;
354263320Sdim class MCInstrInfo;
355263320Sdim+class MCObjectWriter;
356263320Sdim class MCRegisterInfo;
357263320Sdim class MCSubtargetInfo;
358263320Sdim class Target;
359263320Sdim class StringRef;
360263320Sdim+class raw_ostream;
361263320Sdim 
362263320Sdim extern Target TheSparcTarget;
363263320Sdim extern Target TheSparcV9Target;
364263320Sdim@@ -35,7 +39,9 @@ MCAsmBackend *createSparcAsmBackend(const Target &
365263320Sdim                                     const MCRegisterInfo &MRI,
366263320Sdim                                     StringRef TT,
367263320Sdim                                     StringRef CPU);
368263320Sdim-
369263320Sdim+MCObjectWriter *createSparcELFObjectWriter(raw_ostream &OS,
370263320Sdim+                                           bool Is64Bit,
371263320Sdim+                                           uint8_t OSABI);
372263320Sdim } // End llvm namespace
373263320Sdim 
374263320Sdim // Defines symbolic names for Sparc registers.  This defines a mapping from
375263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
376263320Sdim===================================================================
377263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
378263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
379263320Sdim@@ -70,15 +70,67 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const
380263320Sdim bool
381263320Sdim SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
382263320Sdim                                          const MCAsmLayout *Layout) const {
383263320Sdim-  assert(0 && "FIXME: Implement SparcMCExpr::EvaluateAsRelocatableImpl");
384263320Sdim   return getSubExpr()->EvaluateAsRelocatable(Res, *Layout);
385263320Sdim }
386263320Sdim 
387263320Sdim+static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
388263320Sdim+  assert(0 && "Implement fixELFSymbolsInTLSFixupsImpl!");
389263320Sdim+}
390263320Sdim 
391263320Sdim void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
392263320Sdim-  assert(0 && "FIXME: Implement SparcMCExpr::fixELFSymbolsInTLSFixups");
393263320Sdim+  switch(getKind()) {
394263320Sdim+  default: return;
395263320Sdim+  case VK_Sparc_TLS_GD_HI22:
396263320Sdim+  case VK_Sparc_TLS_GD_LO10:
397263320Sdim+  case VK_Sparc_TLS_GD_ADD:
398263320Sdim+  case VK_Sparc_TLS_GD_CALL:
399263320Sdim+  case VK_Sparc_TLS_LDM_HI22:
400263320Sdim+  case VK_Sparc_TLS_LDM_LO10:
401263320Sdim+  case VK_Sparc_TLS_LDM_ADD:
402263320Sdim+  case VK_Sparc_TLS_LDM_CALL:
403263320Sdim+  case VK_Sparc_TLS_LDO_HIX22:
404263320Sdim+  case VK_Sparc_TLS_LDO_LOX10:
405263320Sdim+  case VK_Sparc_TLS_LDO_ADD:
406263320Sdim+  case VK_Sparc_TLS_IE_HI22:
407263320Sdim+  case VK_Sparc_TLS_IE_LO10:
408263320Sdim+  case VK_Sparc_TLS_IE_LD:
409263320Sdim+  case VK_Sparc_TLS_IE_LDX:
410263320Sdim+  case VK_Sparc_TLS_IE_ADD:
411263320Sdim+  case VK_Sparc_TLS_LE_HIX22:
412263320Sdim+  case VK_Sparc_TLS_LE_LOX10: break;
413263320Sdim+  }
414263320Sdim+  fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
415263320Sdim }
416263320Sdim 
417263320Sdim+// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps
418263320Sdim+// that method should be made public?
419263320Sdim+// FIXME: really do above: now that at least three other backends are using it.
420263320Sdim+static void AddValueSymbolsImpl(const MCExpr *Value, MCAssembler *Asm) {
421263320Sdim+  switch (Value->getKind()) {
422263320Sdim+  case MCExpr::Target:
423263320Sdim+    llvm_unreachable("Can't handle nested target expr!");
424263320Sdim+    break;
425263320Sdim+
426263320Sdim+  case MCExpr::Constant:
427263320Sdim+    break;
428263320Sdim+
429263320Sdim+  case MCExpr::Binary: {
430263320Sdim+    const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
431263320Sdim+    AddValueSymbolsImpl(BE->getLHS(), Asm);
432263320Sdim+    AddValueSymbolsImpl(BE->getRHS(), Asm);
433263320Sdim+    break;
434263320Sdim+  }
435263320Sdim+
436263320Sdim+  case MCExpr::SymbolRef:
437263320Sdim+    Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
438263320Sdim+    break;
439263320Sdim+
440263320Sdim+  case MCExpr::Unary:
441263320Sdim+    AddValueSymbolsImpl(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm);
442263320Sdim+    break;
443263320Sdim+  }
444263320Sdim+}
445263320Sdim+
446263320Sdim void SparcMCExpr::AddValueSymbols(MCAssembler *Asm) const {
447263320Sdim-  assert(0 && "FIXME: Implement SparcMCExpr::AddValueSymbols");
448263320Sdim+  AddValueSymbolsImpl(getSubExpr(), Asm);
449263320Sdim }
450263320SdimIndex: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
451263320Sdim===================================================================
452263320Sdim--- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
453263320Sdim+++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
454263320Sdim@@ -1,5 +1,6 @@
455263320Sdim add_llvm_library(LLVMSparcDesc
456263320Sdim   SparcAsmBackend.cpp
457263320Sdim+  SparcELFObjectWriter.cpp
458263320Sdim   SparcMCAsmInfo.cpp
459263320Sdim   SparcMCCodeEmitter.cpp
460263320Sdim   SparcMCTargetDesc.cpp
461