1 Pull in r198580 from upstream llvm trunk (by Venkatraman Govindaraju):
3 [Sparc] Add ELF Object Writer for Sparc.
5 Introduced here: http://svnweb.freebsd.org/changeset/base/262261
7 Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
8 ===================================================================
9 --- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
10 +++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
12 //===----------------------------------------------------------------------===//
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
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));
30 + case SparcMCExpr::VK_Sparc_HI:
31 + Fixups.push_back(MCFixup::Create(0, Expr,
32 + (MCFixupKind)Sparc::fixup_sparc_hi22));
34 + case SparcMCExpr::VK_Sparc_H44:
35 + Fixups.push_back(MCFixup::Create(0, Expr,
36 + (MCFixupKind)Sparc::fixup_sparc_h44));
38 + case SparcMCExpr::VK_Sparc_M44:
39 + Fixups.push_back(MCFixup::Create(0, Expr,
40 + (MCFixupKind)Sparc::fixup_sparc_m44));
42 + case SparcMCExpr::VK_Sparc_L44:
43 + Fixups.push_back(MCFixup::Create(0, Expr,
44 + (MCFixupKind)Sparc::fixup_sparc_l44));
46 + case SparcMCExpr::VK_Sparc_HH:
47 + Fixups.push_back(MCFixup::Create(0, Expr,
48 + (MCFixupKind)Sparc::fixup_sparc_hh));
50 + case SparcMCExpr::VK_Sparc_HM:
51 + Fixups.push_back(MCFixup::Create(0, Expr,
52 + (MCFixupKind)Sparc::fixup_sparc_hm));
59 if (Expr->EvaluateAsAbsolute(Res))
61 Index: 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
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);
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);
84 + // Register the object streamer.
85 + TargetRegistry::RegisterMCObjectStreamer(TheSparcTarget,
87 + TargetRegistry::RegisterMCObjectStreamer(TheSparcV9Target,
90 + // Register the asm streamer.
91 TargetRegistry::RegisterAsmStreamer(TheSparcTarget,
93 TargetRegistry::RegisterAsmStreamer(TheSparcV9Target,
94 Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
95 ===================================================================
96 --- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
97 +++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
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"
108 using namespace llvm;
110 +static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
113 + llvm_unreachable("Unknown fixup kind!");
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;
143 class SparcAsmBackend : public MCAsmBackend {
145 + const Target &TheTarget;
147 - SparcAsmBackend(const Target &T) : MCAsmBackend() {}
148 + SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {}
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 },
167 if (Kind < FirstTargetFixupKind)
168 @@ -68,21 +108,38 @@ namespace {
173 + bool is64Bit() const {
174 + StringRef name = TheTarget.getName();
175 + return name == "sparcv9";
179 class ELFSparcAsmBackend : public SparcAsmBackend {
180 + Triple::OSType OSType;
182 ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) :
183 - SparcAsmBackend(T) { }
184 + SparcAsmBackend(T), OSType(OSType) { }
186 void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
187 uint64_t Value) const {
188 - assert(0 && "applyFixup not implemented yet");
190 + Value = adjustFixupValue(Fixup.getKind(), Value);
191 + if (!Value) return; // Doesn't change encoding.
193 + unsigned Offset = Fixup.getOffset();
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);
203 MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
204 - assert(0 && "Object Writer not implemented yet");
206 + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
207 + return createSparcELFObjectWriter(OS, is64Bit(), OSABI);
210 virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
211 Index: 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 {
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
224 + /// fixup_sparc_hi22 - 22-bit fixup corresponding to %hi(foo)
228 + /// fixup_sparc_lo10 - 10-bit fixup corresponding to %lo(foo)
231 + /// fixup_sparc_h44 - 22-bit fixup corresponding to %h44(foo)
234 + /// fixup_sparc_m44 - 10-bit fixup corresponding to %m44(foo)
237 + /// fixup_sparc_l44 - 12-bit fixup corresponding to %l44(foo)
240 + /// fixup_sparc_hh - 22-bit fixup corresponding to %hh(foo)
243 + /// fixup_sparc_hm - 10-bit fixup corresponding to %hm(foo)
248 NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
249 Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
250 ===================================================================
251 --- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
252 +++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
254 +//===-- SparcELFObjectWriter.cpp - Sparc ELF Writer -----------------------===//
256 +// The LLVM Compiler Infrastructure
258 +// This file is distributed under the University of Illinois Open Source
259 +// License. See LICENSE.TXT for details.
261 +//===----------------------------------------------------------------------===//
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"
271 +using namespace llvm;
274 + class SparcELFObjectWriter : public MCELFObjectTargetWriter {
276 + SparcELFObjectWriter(bool Is64Bit, uint8_t OSABI)
277 + : MCELFObjectTargetWriter(Is64Bit, OSABI,
278 + Is64Bit ? ELF::EM_SPARCV9 : ELF::EM_SPARC,
279 + /*HasRelocationAddend*/ true) {}
281 + virtual ~SparcELFObjectWriter() {}
283 + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
284 + bool IsPCRel, bool IsRelocWithSymbol,
285 + int64_t Addend) const;
291 +unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target,
292 + const MCFixup &Fixup,
294 + bool IsRelocWithSymbol,
295 + int64_t Addend) const {
297 + switch((unsigned)Fixup.getKind()) {
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;
310 + switch((unsigned)Fixup.getKind()) {
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;
331 + return ELF::R_SPARC_NONE;
334 +MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS,
337 + MCELFObjectTargetWriter *MOTW = new SparcELFObjectWriter(Is64Bit, OSABI);
338 + return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false);
340 Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
341 ===================================================================
342 --- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
343 +++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
345 #ifndef SPARCMCTARGETDESC_H
346 #define SPARCMCTARGETDESC_H
348 +#include "llvm/Support/DataTypes.h"
355 +class MCObjectWriter;
356 class MCRegisterInfo;
357 class MCSubtargetInfo;
362 extern Target TheSparcTarget;
363 extern Target TheSparcV9Target;
364 @@ -35,7 +39,9 @@ MCAsmBackend *createSparcAsmBackend(const Target &
365 const MCRegisterInfo &MRI,
369 +MCObjectWriter *createSparcELFObjectWriter(raw_ostream &OS,
372 } // End llvm namespace
374 // Defines symbolic names for Sparc registers. This defines a mapping from
375 Index: 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
381 SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
382 const MCAsmLayout *Layout) const {
383 - assert(0 && "FIXME: Implement SparcMCExpr::EvaluateAsRelocatableImpl");
384 return getSubExpr()->EvaluateAsRelocatable(Res, *Layout);
387 +static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
388 + assert(0 && "Implement fixELFSymbolsInTLSFixupsImpl!");
391 void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
392 - assert(0 && "FIXME: Implement SparcMCExpr::fixELFSymbolsInTLSFixups");
393 + switch(getKind()) {
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;
414 + fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
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!");
426 + case MCExpr::Constant:
429 + case MCExpr::Binary: {
430 + const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
431 + AddValueSymbolsImpl(BE->getLHS(), Asm);
432 + AddValueSymbolsImpl(BE->getRHS(), Asm);
436 + case MCExpr::SymbolRef:
437 + Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
440 + case MCExpr::Unary:
441 + AddValueSymbolsImpl(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm);
446 void SparcMCExpr::AddValueSymbols(MCAssembler *Asm) const {
447 - assert(0 && "FIXME: Implement SparcMCExpr::AddValueSymbols");
448 + AddValueSymbolsImpl(getSubExpr(), Asm);
450 Index: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
451 ===================================================================
452 --- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
453 +++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
455 add_llvm_library(LLVMSparcDesc
457 + SparcELFObjectWriter.cpp
459 SparcMCCodeEmitter.cpp
460 SparcMCTargetDesc.cpp