1263320SdimPull in r200961 from upstream llvm trunk (by Venkatraman Govindaraju):
2263320Sdim
3263320Sdim  [Sparc] Emit correct relocations for PIC code when integrated assembler is used.
4263320Sdim
5263320SdimIntroduced here: http://svn.freebsd.org/changeset/base/262261
6263320Sdim
7263320SdimIndex: test/CodeGen/SPARC/obj-relocs.ll
8263320Sdim===================================================================
9263320Sdim--- test/CodeGen/SPARC/obj-relocs.ll
10263320Sdim+++ test/CodeGen/SPARC/obj-relocs.ll
11263320Sdim@@ -0,0 +1,33 @@
12263320Sdim+; RUN: llc < %s -march=sparcv9 -filetype=obj --relocation-model=static | llvm-readobj -r | FileCheck %s --check-prefix=CHECK-ABS
13263320Sdim+; RUN: llc < %s -march=sparcv9 -filetype=obj --relocation-model=pic    | llvm-readobj -r | FileCheck %s --check-prefix=CHECK-PIC
14263320Sdim+
15263320Sdim+;CHECK-ABS: Relocations [
16263320Sdim+;CHECK-ABS:    0x{{[0-9,A-F]+}} R_SPARC_H44 AGlobalVar 0x0
17263320Sdim+;CHECK-ABS:    0x{{[0-9,A-F]+}} R_SPARC_M44 AGlobalVar 0x0
18263320Sdim+;CHECK-ABS:    0x{{[0-9,A-F]+}} R_SPARC_L44 AGlobalVar 0x0
19263320Sdim+;CHECK-ABS:    0x{{[0-9,A-F]+}} R_SPARC_WDISP30 bar 0x0
20263320Sdim+;CHECK-ABS:]
21263320Sdim+
22263320Sdim+; CHECK-PIC: Relocations [
23263320Sdim+; CHECK-PIC:    0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4
24263320Sdim+; CHECK-PIC:    0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8
25263320Sdim+; CHECK-PIC:    0x{{[0-9,A-F]+}} R_SPARC_GOT22 AGlobalVar 0x0
26263320Sdim+; CHECK-PIC:    0x{{[0-9,A-F]+}} R_SPARC_GOT10 AGlobalVar 0x0
27263320Sdim+; CHECK-PIC:    0x{{[0-9,A-F]+}} R_SPARC_WPLT30 bar 0x0
28263320Sdim+; CHECK-PIC: ]
29263320Sdim+
30263320Sdim+
31263320Sdim+@AGlobalVar = global i64 0, align 8
32263320Sdim+
33263320Sdim+; CHECK-ASM: sethi %h44(AGlobalVar), [[R:%[goli][0-7]]]
34263320Sdim+; CHECK-ASM: add   [[R]], %m44(AGlobalVar), [[R]]
35263320Sdim+define i64 @foo(i64 %a) {
36263320Sdim+entry:
37263320Sdim+  %0 = load i64* @AGlobalVar, align 4
38263320Sdim+  %1 = add i64 %a, %0
39263320Sdim+  %2 = call i64 @bar(i64 %1)
40263320Sdim+  ret i64 %2
41263320Sdim+}
42263320Sdim+
43263320Sdim+
44263320Sdim+declare i64 @bar(i64)
45263320SdimIndex: lib/Target/Sparc/SparcISelLowering.cpp
46263320Sdim===================================================================
47263320Sdim--- lib/Target/Sparc/SparcISelLowering.cpp
48263320Sdim+++ lib/Target/Sparc/SparcISelLowering.cpp
49263320Sdim@@ -895,10 +895,12 @@ SparcTargetLowering::LowerCall_32(TargetLowering::
50263320Sdim   // If the callee is a GlobalAddress node (quite common, every direct call is)
51263320Sdim   // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
52263320Sdim   // Likewise ExternalSymbol -> TargetExternalSymbol.
53263320Sdim+  unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_)
54263320Sdim+                 ? SparcMCExpr::VK_Sparc_WPLT30 : 0);
55263320Sdim   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
56263320Sdim-    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
57263320Sdim+    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF);
58263320Sdim   else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
59263320Sdim-    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
60263320Sdim+    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF);
61263320Sdim 
62263320Sdim   // Returns a chain & a flag for retval copy to use
63263320Sdim   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
64263320Sdim@@ -1209,10 +1211,13 @@ SparcTargetLowering::LowerCall_64(TargetLowering::
65263320Sdim   // Likewise ExternalSymbol -> TargetExternalSymbol.
66263320Sdim   SDValue Callee = CLI.Callee;
67263320Sdim   bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS);
68263320Sdim+  unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_)
69263320Sdim+                 ? SparcMCExpr::VK_Sparc_WPLT30 : 0);
70263320Sdim   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
71263320Sdim-    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy());
72263320Sdim+    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy(), 0,
73263320Sdim+                                        TF);
74263320Sdim   else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
75263320Sdim-    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy());
76263320Sdim+    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy(), TF);
77263320Sdim 
78263320Sdim   // Build the operands for the call instruction itself.
79263320Sdim   SmallVector<SDValue, 8> Ops;
80263320Sdim@@ -1796,8 +1801,8 @@ SDValue SparcTargetLowering::makeAddress(SDValue O
81263320Sdim   // Handle PIC mode first.
82263320Sdim   if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
83263320Sdim     // This is the pic32 code model, the GOT is known to be smaller than 4GB.
84263320Sdim-    SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
85263320Sdim-                                SparcMCExpr::VK_Sparc_LO, DAG);
86263320Sdim+    SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22,
87263320Sdim+                                SparcMCExpr::VK_Sparc_GOT10, DAG);
88263320Sdim     SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT);
89263320Sdim     SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, HiLo);
90263320Sdim     // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this
91263320SdimIndex: lib/Target/Sparc/SparcAsmPrinter.cpp
92263320Sdim===================================================================
93263320Sdim--- lib/Target/Sparc/SparcAsmPrinter.cpp
94263320Sdim+++ lib/Target/Sparc/SparcAsmPrinter.cpp
95263320Sdim@@ -232,12 +232,12 @@ void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(co
96263320Sdim   MCOperand Callee =  createPCXCallOP(EndLabel, OutContext);
97263320Sdim   EmitCall(OutStreamer, Callee);
98263320Sdim   OutStreamer.EmitLabel(SethiLabel);
99263320Sdim-  MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_HI,
100263320Sdim+  MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22,
101263320Sdim                                        GOTLabel, StartLabel, SethiLabel,
102263320Sdim                                        OutContext);
103263320Sdim   EmitSETHI(OutStreamer, hiImm, MCRegOP);
104263320Sdim   OutStreamer.EmitLabel(EndLabel);
105263320Sdim-  MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_LO,
106263320Sdim+  MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10,
107263320Sdim                                        GOTLabel, StartLabel, EndLabel,
108263320Sdim                                        OutContext);
109263320Sdim   EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP);
110263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
111263320Sdim===================================================================
112263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
113263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
114263320Sdim@@ -26,6 +26,7 @@ static unsigned adjustFixupValue(unsigned Kind, ui
115263320Sdim   case FK_Data_4:
116263320Sdim   case FK_Data_8:
117263320Sdim     return Value;
118263320Sdim+  case Sparc::fixup_sparc_wplt30:
119263320Sdim   case Sparc::fixup_sparc_call30:
120263320Sdim     return (Value >> 2) & 0x3fffffff;
121263320Sdim   case Sparc::fixup_sparc_br22:
122263320Sdim@@ -32,8 +33,12 @@ static unsigned adjustFixupValue(unsigned Kind, ui
123263320Sdim     return (Value >> 2) & 0x3fffff;
124263320Sdim   case Sparc::fixup_sparc_br19:
125263320Sdim     return (Value >> 2) & 0x7ffff;
126263320Sdim+  case Sparc::fixup_sparc_pc22:
127263320Sdim+  case Sparc::fixup_sparc_got22:
128263320Sdim   case Sparc::fixup_sparc_hi22:
129263320Sdim     return (Value >> 10) & 0x3fffff;
130263320Sdim+  case Sparc::fixup_sparc_pc10:
131263320Sdim+  case Sparc::fixup_sparc_got10:
132263320Sdim   case Sparc::fixup_sparc_lo10:
133263320Sdim     return Value & 0x3ff;
134263320Sdim   case Sparc::fixup_sparc_h44:
135263320Sdim@@ -72,6 +77,11 @@ namespace {
136263320Sdim         { "fixup_sparc_l44",       20,     12,  0 },
137263320Sdim         { "fixup_sparc_hh",        10,     22,  0 },
138263320Sdim         { "fixup_sparc_hm",        22,     10,  0 },
139263320Sdim+        { "fixup_sparc_pc22",      10,     22,  MCFixupKindInfo::FKF_IsPCRel },
140263320Sdim+        { "fixup_sparc_pc10",      22,     10,  MCFixupKindInfo::FKF_IsPCRel },
141263320Sdim+        { "fixup_sparc_got22",     10,     22,  0 },
142263320Sdim+        { "fixup_sparc_got10",     22,     10,  0 },
143263320Sdim+        { "fixup_sparc_wplt30",     2,     30,  MCFixupKindInfo::FKF_IsPCRel }
144263320Sdim       };
145263320Sdim 
146263320Sdim       if (Kind < FirstTargetFixupKind)
147263320Sdim@@ -82,6 +92,20 @@ namespace {
148263320Sdim       return Infos[Kind - FirstTargetFixupKind];
149263320Sdim     }
150263320Sdim 
151263320Sdim+    void processFixupValue(const MCAssembler &Asm,
152263320Sdim+                           const MCAsmLayout &Layout,
153263320Sdim+                           const MCFixup &Fixup,
154263320Sdim+                           const MCFragment *DF,
155263320Sdim+                           MCValue &  Target,
156263320Sdim+                           uint64_t &Value,
157263320Sdim+                           bool &IsResolved) {
158263320Sdim+      switch ((Sparc::Fixups)Fixup.getKind()) {
159263320Sdim+      default: break;
160263320Sdim+      case Sparc::fixup_sparc_wplt30: IsResolved = false; break;
161263320Sdim+      }
162263320Sdim+    }
163263320Sdim+
164263320Sdim+
165263320Sdim     bool mayNeedRelaxation(const MCInst &Inst) const {
166263320Sdim       // FIXME.
167263320Sdim       return false;
168263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
169263320Sdim===================================================================
170263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
171263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
172263320Sdim@@ -48,6 +48,21 @@ namespace llvm {
173263320Sdim       /// fixup_sparc_hm  -  10-bit fixup corresponding to %hm(foo)
174263320Sdim       fixup_sparc_hm,
175263320Sdim 
176263320Sdim+      /// fixup_sparc_pc22 - 22-bit fixup corresponding to %pc22(foo)
177263320Sdim+      fixup_sparc_pc22,
178263320Sdim+
179263320Sdim+      /// fixup_sparc_pc10 - 10-bit fixup corresponding to %pc10(foo)
180263320Sdim+      fixup_sparc_pc10,
181263320Sdim+
182263320Sdim+      /// fixup_sparc_got22 - 22-bit fixup corresponding to %got22(foo)
183263320Sdim+      fixup_sparc_got22,
184263320Sdim+
185263320Sdim+      /// fixup_sparc_got10 - 10-bit fixup corresponding to %got10(foo)
186263320Sdim+      fixup_sparc_got10,
187263320Sdim+
188263320Sdim+      /// fixup_sparc_wplt30
189263320Sdim+      fixup_sparc_wplt30,
190263320Sdim+
191263320Sdim       // Marker
192263320Sdim       LastTargetFixupKind,
193263320Sdim       NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
194263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
195263320Sdim===================================================================
196263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
197263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
198263320Sdim@@ -7,8 +7,9 @@
199263320Sdim //
200263320Sdim //===----------------------------------------------------------------------===//
201263320Sdim 
202263320Sdim+#include "MCTargetDesc/SparcFixupKinds.h"
203263320Sdim+#include "MCTargetDesc/SparcMCExpr.h"
204263320Sdim #include "MCTargetDesc/SparcMCTargetDesc.h"
205263320Sdim-#include "MCTargetDesc/SparcFixupKinds.h"
206263320Sdim #include "llvm/ADT/STLExtras.h"
207263320Sdim #include "llvm/MC/MCELFObjectWriter.h"
208263320Sdim #include "llvm/MC/MCExpr.h"
209263320Sdim@@ -31,6 +32,11 @@ namespace {
210263320Sdim                                   bool IsPCRel, bool IsRelocWithSymbol,
211263320Sdim                                   int64_t Addend) const;
212263320Sdim 
213263320Sdim+    virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
214263320Sdim+                                           const MCValue &Target,
215263320Sdim+                                           const MCFragment &F,
216263320Sdim+                                           const MCFixup &Fixup,
217263320Sdim+                                           bool IsPCRel) const;
218263320Sdim   };
219263320Sdim }
220263320Sdim 
221263320Sdim@@ -40,6 +46,12 @@ unsigned SparcELFObjectWriter::GetRelocType(const
222263320Sdim                                             bool IsPCRel,
223263320Sdim                                             bool IsRelocWithSymbol,
224263320Sdim                                             int64_t Addend) const {
225263320Sdim+
226263320Sdim+  if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Fixup.getValue())) {
227263320Sdim+    if (SExpr->getKind() == SparcMCExpr::VK_Sparc_R_DISP32)
228263320Sdim+      return ELF::R_SPARC_DISP32;
229263320Sdim+  }
230263320Sdim+
231263320Sdim   if (IsPCRel) {
232263320Sdim     switch((unsigned)Fixup.getKind()) {
233263320Sdim     default:
234263320Sdim@@ -51,6 +63,9 @@ unsigned SparcELFObjectWriter::GetRelocType(const
235263320Sdim     case Sparc::fixup_sparc_call30:  return ELF::R_SPARC_WDISP30;
236263320Sdim     case Sparc::fixup_sparc_br22:    return ELF::R_SPARC_WDISP22;
237263320Sdim     case Sparc::fixup_sparc_br19:    return ELF::R_SPARC_WDISP19;
238263320Sdim+    case Sparc::fixup_sparc_pc22:    return ELF::R_SPARC_PC22;
239263320Sdim+    case Sparc::fixup_sparc_pc10:    return ELF::R_SPARC_PC10;
240263320Sdim+    case Sparc::fixup_sparc_wplt30:  return ELF::R_SPARC_WPLT30;
241263320Sdim     }
242263320Sdim   }
243263320Sdim 
244263320Sdim@@ -74,10 +89,30 @@ unsigned SparcELFObjectWriter::GetRelocType(const
245263320Sdim   case Sparc::fixup_sparc_l44:   return ELF::R_SPARC_L44;
246263320Sdim   case Sparc::fixup_sparc_hh:    return ELF::R_SPARC_HH22;
247263320Sdim   case Sparc::fixup_sparc_hm:    return ELF::R_SPARC_HM10;
248263320Sdim+  case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22;
249263320Sdim+  case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10;
250263320Sdim   }
251263320Sdim+
252263320Sdim   return ELF::R_SPARC_NONE;
253263320Sdim }
254263320Sdim 
255263320Sdim+const MCSymbol *SparcELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm,
256263320Sdim+                                                     const MCValue &Target,
257263320Sdim+                                                     const MCFragment &F,
258263320Sdim+                                                     const MCFixup &Fixup,
259263320Sdim+                                                     bool IsPCRel) const {
260263320Sdim+
261263320Sdim+  if (!Target.getSymA())
262263320Sdim+    return NULL;
263263320Sdim+  switch((unsigned)Fixup.getKind()) {
264263320Sdim+  default: break;
265263320Sdim+  case Sparc::fixup_sparc_got22:
266263320Sdim+  case Sparc::fixup_sparc_got10:
267263320Sdim+    return &Target.getSymA()->getSymbol().AliasedSymbol();
268263320Sdim+  }
269263320Sdim+  return NULL;
270263320Sdim+}
271263320Sdim+
272263320Sdim MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS,
273263320Sdim                                                  bool Is64Bit,
274263320Sdim                                                  uint8_t OSABI) {
275263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
276263320Sdim===================================================================
277263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
278263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
279263320Sdim@@ -17,6 +17,7 @@
280263320Sdim #include "llvm/MC/MCContext.h"
281263320Sdim #include "llvm/MC/MCAssembler.h"
282263320Sdim #include "llvm/MC/MCELF.h"
283263320Sdim+#include "llvm/MC/MCSymbol.h"
284263320Sdim #include "llvm/Object/ELF.h"
285263320Sdim 
286263320Sdim 
287263320Sdim@@ -54,6 +55,13 @@ bool SparcMCExpr::printVariantKind(raw_ostream &OS
288263320Sdim   case VK_Sparc_L44:      OS << "%l44("; break;
289263320Sdim   case VK_Sparc_HH:       OS << "%hh(";  break;
290263320Sdim   case VK_Sparc_HM:       OS << "%hm(";  break;
291263320Sdim+    // FIXME: use %pc22/%pc10, if system assembler supports them.
292263320Sdim+  case VK_Sparc_PC22:     OS << "%hi("; break;
293263320Sdim+  case VK_Sparc_PC10:     OS << "%lo("; break;
294263320Sdim+    // FIXME: use %got22/%got10, if system assembler supports them.
295263320Sdim+  case VK_Sparc_GOT22:    OS << "%hi("; break;
296263320Sdim+  case VK_Sparc_GOT10:    OS << "%lo("; break;
297263320Sdim+  case VK_Sparc_WPLT30:   closeParen = false; break;
298263320Sdim   case VK_Sparc_R_DISP32: OS << "%r_disp32("; break;
299263320Sdim   case VK_Sparc_TLS_GD_HI22:   OS << "%tgd_hi22(";   break;
300263320Sdim   case VK_Sparc_TLS_GD_LO10:   OS << "%tgd_lo10(";   break;
301263320Sdim@@ -87,6 +95,10 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariant
302263320Sdim     .Case("l44", VK_Sparc_L44)
303263320Sdim     .Case("hh",  VK_Sparc_HH)
304263320Sdim     .Case("hm",  VK_Sparc_HM)
305263320Sdim+    .Case("pc22",  VK_Sparc_PC22)
306263320Sdim+    .Case("pc10",  VK_Sparc_PC10)
307263320Sdim+    .Case("got22", VK_Sparc_GOT22)
308263320Sdim+    .Case("got10", VK_Sparc_GOT10)
309263320Sdim     .Case("r_disp32",   VK_Sparc_R_DISP32)
310263320Sdim     .Case("tgd_hi22",   VK_Sparc_TLS_GD_HI22)
311263320Sdim     .Case("tgd_lo10",   VK_Sparc_TLS_GD_LO10)
312263320Sdim@@ -109,9 +121,26 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariant
313263320Sdim     .Default(VK_Sparc_None);
314263320Sdim }
315263320Sdim 
316263320Sdim+Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) {
317263320Sdim+  switch (Kind) {
318263320Sdim+  default:           assert(0 && "Unhandled SparcMCExpr::VariantKind");
319263320Sdim+  case VK_Sparc_LO:       return Sparc::fixup_sparc_lo10;
320263320Sdim+  case VK_Sparc_HI:       return Sparc::fixup_sparc_hi22;
321263320Sdim+  case VK_Sparc_H44:      return Sparc::fixup_sparc_h44;
322263320Sdim+  case VK_Sparc_M44:      return Sparc::fixup_sparc_m44;
323263320Sdim+  case VK_Sparc_L44:      return Sparc::fixup_sparc_l44;
324263320Sdim+  case VK_Sparc_HH:       return Sparc::fixup_sparc_hh;
325263320Sdim+  case VK_Sparc_HM:       return Sparc::fixup_sparc_hm;
326263320Sdim+  case VK_Sparc_PC22:     return Sparc::fixup_sparc_pc22;
327263320Sdim+  case VK_Sparc_PC10:     return Sparc::fixup_sparc_pc10;
328263320Sdim+  case VK_Sparc_GOT22:    return Sparc::fixup_sparc_got22;
329263320Sdim+  case VK_Sparc_GOT10:    return Sparc::fixup_sparc_got10;
330263320Sdim+  }
331263320Sdim+}
332263320Sdim+
333263320Sdim bool
334263320Sdim SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
335263320Sdim-                                         const MCAsmLayout *Layout) const {
336263320Sdim+                                       const MCAsmLayout *Layout) const {
337263320Sdim   if (!Layout)
338263320Sdim     return false;
339263320Sdim   return getSubExpr()->EvaluateAsRelocatable(Res, *Layout);
340263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
341263320Sdim===================================================================
342263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
343263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
344263320Sdim@@ -15,6 +15,7 @@
345263320Sdim #ifndef LLVM_SPARCMCEXPR_H
346263320Sdim #define LLVM_SPARCMCEXPR_H
347263320Sdim 
348263320Sdim+#include "SparcFixupKinds.h"
349263320Sdim #include "llvm/MC/MCExpr.h"
350263320Sdim 
351263320Sdim namespace llvm {
352263320Sdim@@ -31,6 +32,11 @@ class SparcMCExpr : public MCTargetExpr {
353263320Sdim     VK_Sparc_L44,
354263320Sdim     VK_Sparc_HH,
355263320Sdim     VK_Sparc_HM,
356263320Sdim+    VK_Sparc_PC22,
357263320Sdim+    VK_Sparc_PC10,
358263320Sdim+    VK_Sparc_GOT22,
359263320Sdim+    VK_Sparc_GOT10,
360263320Sdim+    VK_Sparc_WPLT30,
361263320Sdim     VK_Sparc_R_DISP32,
362263320Sdim     VK_Sparc_TLS_GD_HI22,
363263320Sdim     VK_Sparc_TLS_GD_LO10,
364263320Sdim@@ -75,6 +81,9 @@ class SparcMCExpr : public MCTargetExpr {
365263320Sdim   /// getSubExpr - Get the child of this expression.
366263320Sdim   const MCExpr *getSubExpr() const { return Expr; }
367263320Sdim 
368263320Sdim+  /// getFixupKind - Get the fixup kind of this expression.
369263320Sdim+  Sparc::Fixups getFixupKind() const { return getFixupKind(Kind); }
370263320Sdim+
371263320Sdim   /// @}
372263320Sdim   void PrintImpl(raw_ostream &OS) const;
373263320Sdim   bool EvaluateAsRelocatableImpl(MCValue &Res,
374263320Sdim@@ -94,6 +103,7 @@ class SparcMCExpr : public MCTargetExpr {
375263320Sdim 
376263320Sdim   static VariantKind parseVariantKind(StringRef name);
377263320Sdim   static bool printVariantKind(raw_ostream &OS, VariantKind Kind);
378263320Sdim+  static Sparc::Fixups getFixupKind(VariantKind Kind);
379263320Sdim };
380263320Sdim 
381263320Sdim } // end namespace llvm.
382263320SdimIndex: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
383263320Sdim===================================================================
384263320Sdim--- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
385263320Sdim+++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
386263320Sdim@@ -94,37 +94,8 @@ getMachineOpValue(const MCInst &MI, const MCOperan
387263320Sdim   assert(MO.isExpr());
388263320Sdim   const MCExpr *Expr = MO.getExpr();
389263320Sdim   if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
390263320Sdim-    switch(SExpr->getKind()) {
391263320Sdim-    default: assert(0 && "Unhandled sparc expression!"); break;
392263320Sdim-    case SparcMCExpr::VK_Sparc_LO:
393263320Sdim-      Fixups.push_back(MCFixup::Create(0, Expr,
394263320Sdim-                                       (MCFixupKind)Sparc::fixup_sparc_lo10));
395263320Sdim-      break;
396263320Sdim-    case SparcMCExpr::VK_Sparc_HI:
397263320Sdim-      Fixups.push_back(MCFixup::Create(0, Expr,
398263320Sdim-                                       (MCFixupKind)Sparc::fixup_sparc_hi22));
399263320Sdim-      break;
400263320Sdim-    case SparcMCExpr::VK_Sparc_H44:
401263320Sdim-      Fixups.push_back(MCFixup::Create(0, Expr,
402263320Sdim-                                       (MCFixupKind)Sparc::fixup_sparc_h44));
403263320Sdim-      break;
404263320Sdim-    case SparcMCExpr::VK_Sparc_M44:
405263320Sdim-      Fixups.push_back(MCFixup::Create(0, Expr,
406263320Sdim-                                       (MCFixupKind)Sparc::fixup_sparc_m44));
407263320Sdim-      break;
408263320Sdim-    case SparcMCExpr::VK_Sparc_L44:
409263320Sdim-      Fixups.push_back(MCFixup::Create(0, Expr,
410263320Sdim-                                       (MCFixupKind)Sparc::fixup_sparc_l44));
411263320Sdim-      break;
412263320Sdim-    case SparcMCExpr::VK_Sparc_HH:
413263320Sdim-      Fixups.push_back(MCFixup::Create(0, Expr,
414263320Sdim-                                       (MCFixupKind)Sparc::fixup_sparc_hh));
415263320Sdim-      break;
416263320Sdim-    case SparcMCExpr::VK_Sparc_HM:
417263320Sdim-      Fixups.push_back(MCFixup::Create(0, Expr,
418263320Sdim-                                       (MCFixupKind)Sparc::fixup_sparc_hm));
419263320Sdim-      break;
420263320Sdim-    }
421263320Sdim+    MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
422263320Sdim+    Fixups.push_back(MCFixup::Create(0, Expr, Kind));
423263320Sdim     return 0;
424263320Sdim   }
425263320Sdim 
426263320Sdim@@ -143,8 +114,15 @@ getCallTargetOpValue(const MCInst &MI, unsigned Op
427263320Sdim   if (MO.isReg() || MO.isImm())
428263320Sdim     return getMachineOpValue(MI, MO, Fixups);
429263320Sdim 
430263320Sdim-  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
431263320Sdim-                                   (MCFixupKind)Sparc::fixup_sparc_call30));
432263320Sdim+  MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
433263320Sdim+
434263320Sdim+  if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
435263320Sdim+    if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
436263320Sdim+      fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
437263320Sdim+  }
438263320Sdim+
439263320Sdim+  Fixups.push_back(MCFixup::Create(0, MO.getExpr(), fixupKind));
440263320Sdim+
441263320Sdim   return 0;
442263320Sdim }
443263320Sdim 
444