patch-r262261-llvm-r198580-sparc.diff revision 269012
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