patch-r262261-llvm-r200961-sparc.diff revision 269012
1Pull in r200961 from upstream llvm trunk (by Venkatraman Govindaraju):
2
3  [Sparc] Emit correct relocations for PIC code when integrated assembler is used.
4
5Introduced here: http://svnweb.freebsd.org/changeset/base/262261
6
7Index: test/CodeGen/SPARC/obj-relocs.ll
8===================================================================
9--- test/CodeGen/SPARC/obj-relocs.ll
10+++ test/CodeGen/SPARC/obj-relocs.ll
11@@ -0,0 +1,33 @@
12+; RUN: llc < %s -march=sparcv9 -filetype=obj --relocation-model=static | llvm-readobj -r | FileCheck %s --check-prefix=CHECK-ABS
13+; RUN: llc < %s -march=sparcv9 -filetype=obj --relocation-model=pic    | llvm-readobj -r | FileCheck %s --check-prefix=CHECK-PIC
14+
15+;CHECK-ABS: Relocations [
16+;CHECK-ABS:    0x{{[0-9,A-F]+}} R_SPARC_H44 AGlobalVar 0x0
17+;CHECK-ABS:    0x{{[0-9,A-F]+}} R_SPARC_M44 AGlobalVar 0x0
18+;CHECK-ABS:    0x{{[0-9,A-F]+}} R_SPARC_L44 AGlobalVar 0x0
19+;CHECK-ABS:    0x{{[0-9,A-F]+}} R_SPARC_WDISP30 bar 0x0
20+;CHECK-ABS:]
21+
22+; CHECK-PIC: Relocations [
23+; CHECK-PIC:    0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4
24+; CHECK-PIC:    0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8
25+; CHECK-PIC:    0x{{[0-9,A-F]+}} R_SPARC_GOT22 AGlobalVar 0x0
26+; CHECK-PIC:    0x{{[0-9,A-F]+}} R_SPARC_GOT10 AGlobalVar 0x0
27+; CHECK-PIC:    0x{{[0-9,A-F]+}} R_SPARC_WPLT30 bar 0x0
28+; CHECK-PIC: ]
29+
30+
31+@AGlobalVar = global i64 0, align 8
32+
33+; CHECK-ASM: sethi %h44(AGlobalVar), [[R:%[goli][0-7]]]
34+; CHECK-ASM: add   [[R]], %m44(AGlobalVar), [[R]]
35+define i64 @foo(i64 %a) {
36+entry:
37+  %0 = load i64* @AGlobalVar, align 4
38+  %1 = add i64 %a, %0
39+  %2 = call i64 @bar(i64 %1)
40+  ret i64 %2
41+}
42+
43+
44+declare i64 @bar(i64)
45Index: lib/Target/Sparc/SparcISelLowering.cpp
46===================================================================
47--- lib/Target/Sparc/SparcISelLowering.cpp
48+++ lib/Target/Sparc/SparcISelLowering.cpp
49@@ -895,10 +895,12 @@ SparcTargetLowering::LowerCall_32(TargetLowering::
50   // If the callee is a GlobalAddress node (quite common, every direct call is)
51   // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
52   // Likewise ExternalSymbol -> TargetExternalSymbol.
53+  unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_)
54+                 ? SparcMCExpr::VK_Sparc_WPLT30 : 0);
55   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
56-    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
57+    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF);
58   else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
59-    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
60+    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF);
61 
62   // Returns a chain & a flag for retval copy to use
63   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
64@@ -1209,10 +1211,13 @@ SparcTargetLowering::LowerCall_64(TargetLowering::
65   // Likewise ExternalSymbol -> TargetExternalSymbol.
66   SDValue Callee = CLI.Callee;
67   bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS);
68+  unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_)
69+                 ? SparcMCExpr::VK_Sparc_WPLT30 : 0);
70   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
71-    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy());
72+    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy(), 0,
73+                                        TF);
74   else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
75-    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy());
76+    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy(), TF);
77 
78   // Build the operands for the call instruction itself.
79   SmallVector<SDValue, 8> Ops;
80@@ -1796,8 +1801,8 @@ SDValue SparcTargetLowering::makeAddress(SDValue O
81   // Handle PIC mode first.
82   if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
83     // This is the pic32 code model, the GOT is known to be smaller than 4GB.
84-    SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
85-                                SparcMCExpr::VK_Sparc_LO, DAG);
86+    SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22,
87+                                SparcMCExpr::VK_Sparc_GOT10, DAG);
88     SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT);
89     SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, HiLo);
90     // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this
91Index: lib/Target/Sparc/SparcAsmPrinter.cpp
92===================================================================
93--- lib/Target/Sparc/SparcAsmPrinter.cpp
94+++ lib/Target/Sparc/SparcAsmPrinter.cpp
95@@ -232,12 +232,12 @@ void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(co
96   MCOperand Callee =  createPCXCallOP(EndLabel, OutContext);
97   EmitCall(OutStreamer, Callee);
98   OutStreamer.EmitLabel(SethiLabel);
99-  MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_HI,
100+  MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22,
101                                        GOTLabel, StartLabel, SethiLabel,
102                                        OutContext);
103   EmitSETHI(OutStreamer, hiImm, MCRegOP);
104   OutStreamer.EmitLabel(EndLabel);
105-  MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_LO,
106+  MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10,
107                                        GOTLabel, StartLabel, EndLabel,
108                                        OutContext);
109   EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP);
110Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
111===================================================================
112--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
113+++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
114@@ -26,6 +26,7 @@ static unsigned adjustFixupValue(unsigned Kind, ui
115   case FK_Data_4:
116   case FK_Data_8:
117     return Value;
118+  case Sparc::fixup_sparc_wplt30:
119   case Sparc::fixup_sparc_call30:
120     return (Value >> 2) & 0x3fffffff;
121   case Sparc::fixup_sparc_br22:
122@@ -32,8 +33,12 @@ static unsigned adjustFixupValue(unsigned Kind, ui
123     return (Value >> 2) & 0x3fffff;
124   case Sparc::fixup_sparc_br19:
125     return (Value >> 2) & 0x7ffff;
126+  case Sparc::fixup_sparc_pc22:
127+  case Sparc::fixup_sparc_got22:
128   case Sparc::fixup_sparc_hi22:
129     return (Value >> 10) & 0x3fffff;
130+  case Sparc::fixup_sparc_pc10:
131+  case Sparc::fixup_sparc_got10:
132   case Sparc::fixup_sparc_lo10:
133     return Value & 0x3ff;
134   case Sparc::fixup_sparc_h44:
135@@ -72,6 +77,11 @@ namespace {
136         { "fixup_sparc_l44",       20,     12,  0 },
137         { "fixup_sparc_hh",        10,     22,  0 },
138         { "fixup_sparc_hm",        22,     10,  0 },
139+        { "fixup_sparc_pc22",      10,     22,  MCFixupKindInfo::FKF_IsPCRel },
140+        { "fixup_sparc_pc10",      22,     10,  MCFixupKindInfo::FKF_IsPCRel },
141+        { "fixup_sparc_got22",     10,     22,  0 },
142+        { "fixup_sparc_got10",     22,     10,  0 },
143+        { "fixup_sparc_wplt30",     2,     30,  MCFixupKindInfo::FKF_IsPCRel }
144       };
145 
146       if (Kind < FirstTargetFixupKind)
147@@ -82,6 +92,20 @@ namespace {
148       return Infos[Kind - FirstTargetFixupKind];
149     }
150 
151+    void processFixupValue(const MCAssembler &Asm,
152+                           const MCAsmLayout &Layout,
153+                           const MCFixup &Fixup,
154+                           const MCFragment *DF,
155+                           MCValue &  Target,
156+                           uint64_t &Value,
157+                           bool &IsResolved) {
158+      switch ((Sparc::Fixups)Fixup.getKind()) {
159+      default: break;
160+      case Sparc::fixup_sparc_wplt30: IsResolved = false; break;
161+      }
162+    }
163+
164+
165     bool mayNeedRelaxation(const MCInst &Inst) const {
166       // FIXME.
167       return false;
168Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
169===================================================================
170--- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
171+++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
172@@ -48,6 +48,21 @@ namespace llvm {
173       /// fixup_sparc_hm  -  10-bit fixup corresponding to %hm(foo)
174       fixup_sparc_hm,
175 
176+      /// fixup_sparc_pc22 - 22-bit fixup corresponding to %pc22(foo)
177+      fixup_sparc_pc22,
178+
179+      /// fixup_sparc_pc10 - 10-bit fixup corresponding to %pc10(foo)
180+      fixup_sparc_pc10,
181+
182+      /// fixup_sparc_got22 - 22-bit fixup corresponding to %got22(foo)
183+      fixup_sparc_got22,
184+
185+      /// fixup_sparc_got10 - 10-bit fixup corresponding to %got10(foo)
186+      fixup_sparc_got10,
187+
188+      /// fixup_sparc_wplt30
189+      fixup_sparc_wplt30,
190+
191       // Marker
192       LastTargetFixupKind,
193       NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
194Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
195===================================================================
196--- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
197+++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
198@@ -7,8 +7,9 @@
199 //
200 //===----------------------------------------------------------------------===//
201 
202+#include "MCTargetDesc/SparcFixupKinds.h"
203+#include "MCTargetDesc/SparcMCExpr.h"
204 #include "MCTargetDesc/SparcMCTargetDesc.h"
205-#include "MCTargetDesc/SparcFixupKinds.h"
206 #include "llvm/ADT/STLExtras.h"
207 #include "llvm/MC/MCELFObjectWriter.h"
208 #include "llvm/MC/MCExpr.h"
209@@ -31,6 +32,11 @@ namespace {
210                                   bool IsPCRel, bool IsRelocWithSymbol,
211                                   int64_t Addend) const;
212 
213+    virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
214+                                           const MCValue &Target,
215+                                           const MCFragment &F,
216+                                           const MCFixup &Fixup,
217+                                           bool IsPCRel) const;
218   };
219 }
220 
221@@ -40,6 +46,12 @@ unsigned SparcELFObjectWriter::GetRelocType(const
222                                             bool IsPCRel,
223                                             bool IsRelocWithSymbol,
224                                             int64_t Addend) const {
225+
226+  if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Fixup.getValue())) {
227+    if (SExpr->getKind() == SparcMCExpr::VK_Sparc_R_DISP32)
228+      return ELF::R_SPARC_DISP32;
229+  }
230+
231   if (IsPCRel) {
232     switch((unsigned)Fixup.getKind()) {
233     default:
234@@ -51,6 +63,9 @@ unsigned SparcELFObjectWriter::GetRelocType(const
235     case Sparc::fixup_sparc_call30:  return ELF::R_SPARC_WDISP30;
236     case Sparc::fixup_sparc_br22:    return ELF::R_SPARC_WDISP22;
237     case Sparc::fixup_sparc_br19:    return ELF::R_SPARC_WDISP19;
238+    case Sparc::fixup_sparc_pc22:    return ELF::R_SPARC_PC22;
239+    case Sparc::fixup_sparc_pc10:    return ELF::R_SPARC_PC10;
240+    case Sparc::fixup_sparc_wplt30:  return ELF::R_SPARC_WPLT30;
241     }
242   }
243 
244@@ -74,10 +89,30 @@ unsigned SparcELFObjectWriter::GetRelocType(const
245   case Sparc::fixup_sparc_l44:   return ELF::R_SPARC_L44;
246   case Sparc::fixup_sparc_hh:    return ELF::R_SPARC_HH22;
247   case Sparc::fixup_sparc_hm:    return ELF::R_SPARC_HM10;
248+  case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22;
249+  case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10;
250   }
251+
252   return ELF::R_SPARC_NONE;
253 }
254 
255+const MCSymbol *SparcELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm,
256+                                                     const MCValue &Target,
257+                                                     const MCFragment &F,
258+                                                     const MCFixup &Fixup,
259+                                                     bool IsPCRel) const {
260+
261+  if (!Target.getSymA())
262+    return NULL;
263+  switch((unsigned)Fixup.getKind()) {
264+  default: break;
265+  case Sparc::fixup_sparc_got22:
266+  case Sparc::fixup_sparc_got10:
267+    return &Target.getSymA()->getSymbol().AliasedSymbol();
268+  }
269+  return NULL;
270+}
271+
272 MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS,
273                                                  bool Is64Bit,
274                                                  uint8_t OSABI) {
275Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
276===================================================================
277--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
278+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
279@@ -17,6 +17,7 @@
280 #include "llvm/MC/MCContext.h"
281 #include "llvm/MC/MCAssembler.h"
282 #include "llvm/MC/MCELF.h"
283+#include "llvm/MC/MCSymbol.h"
284 #include "llvm/Object/ELF.h"
285 
286 
287@@ -54,6 +55,13 @@ bool SparcMCExpr::printVariantKind(raw_ostream &OS
288   case VK_Sparc_L44:      OS << "%l44("; break;
289   case VK_Sparc_HH:       OS << "%hh(";  break;
290   case VK_Sparc_HM:       OS << "%hm(";  break;
291+    // FIXME: use %pc22/%pc10, if system assembler supports them.
292+  case VK_Sparc_PC22:     OS << "%hi("; break;
293+  case VK_Sparc_PC10:     OS << "%lo("; break;
294+    // FIXME: use %got22/%got10, if system assembler supports them.
295+  case VK_Sparc_GOT22:    OS << "%hi("; break;
296+  case VK_Sparc_GOT10:    OS << "%lo("; break;
297+  case VK_Sparc_WPLT30:   closeParen = false; break;
298   case VK_Sparc_R_DISP32: OS << "%r_disp32("; break;
299   case VK_Sparc_TLS_GD_HI22:   OS << "%tgd_hi22(";   break;
300   case VK_Sparc_TLS_GD_LO10:   OS << "%tgd_lo10(";   break;
301@@ -87,6 +95,10 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariant
302     .Case("l44", VK_Sparc_L44)
303     .Case("hh",  VK_Sparc_HH)
304     .Case("hm",  VK_Sparc_HM)
305+    .Case("pc22",  VK_Sparc_PC22)
306+    .Case("pc10",  VK_Sparc_PC10)
307+    .Case("got22", VK_Sparc_GOT22)
308+    .Case("got10", VK_Sparc_GOT10)
309     .Case("r_disp32",   VK_Sparc_R_DISP32)
310     .Case("tgd_hi22",   VK_Sparc_TLS_GD_HI22)
311     .Case("tgd_lo10",   VK_Sparc_TLS_GD_LO10)
312@@ -109,9 +121,26 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariant
313     .Default(VK_Sparc_None);
314 }
315 
316+Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) {
317+  switch (Kind) {
318+  default:           assert(0 && "Unhandled SparcMCExpr::VariantKind");
319+  case VK_Sparc_LO:       return Sparc::fixup_sparc_lo10;
320+  case VK_Sparc_HI:       return Sparc::fixup_sparc_hi22;
321+  case VK_Sparc_H44:      return Sparc::fixup_sparc_h44;
322+  case VK_Sparc_M44:      return Sparc::fixup_sparc_m44;
323+  case VK_Sparc_L44:      return Sparc::fixup_sparc_l44;
324+  case VK_Sparc_HH:       return Sparc::fixup_sparc_hh;
325+  case VK_Sparc_HM:       return Sparc::fixup_sparc_hm;
326+  case VK_Sparc_PC22:     return Sparc::fixup_sparc_pc22;
327+  case VK_Sparc_PC10:     return Sparc::fixup_sparc_pc10;
328+  case VK_Sparc_GOT22:    return Sparc::fixup_sparc_got22;
329+  case VK_Sparc_GOT10:    return Sparc::fixup_sparc_got10;
330+  }
331+}
332+
333 bool
334 SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
335-                                         const MCAsmLayout *Layout) const {
336+                                       const MCAsmLayout *Layout) const {
337   if (!Layout)
338     return false;
339   return getSubExpr()->EvaluateAsRelocatable(Res, *Layout);
340Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
341===================================================================
342--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
343+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
344@@ -15,6 +15,7 @@
345 #ifndef LLVM_SPARCMCEXPR_H
346 #define LLVM_SPARCMCEXPR_H
347 
348+#include "SparcFixupKinds.h"
349 #include "llvm/MC/MCExpr.h"
350 
351 namespace llvm {
352@@ -31,6 +32,11 @@ class SparcMCExpr : public MCTargetExpr {
353     VK_Sparc_L44,
354     VK_Sparc_HH,
355     VK_Sparc_HM,
356+    VK_Sparc_PC22,
357+    VK_Sparc_PC10,
358+    VK_Sparc_GOT22,
359+    VK_Sparc_GOT10,
360+    VK_Sparc_WPLT30,
361     VK_Sparc_R_DISP32,
362     VK_Sparc_TLS_GD_HI22,
363     VK_Sparc_TLS_GD_LO10,
364@@ -75,6 +81,9 @@ class SparcMCExpr : public MCTargetExpr {
365   /// getSubExpr - Get the child of this expression.
366   const MCExpr *getSubExpr() const { return Expr; }
367 
368+  /// getFixupKind - Get the fixup kind of this expression.
369+  Sparc::Fixups getFixupKind() const { return getFixupKind(Kind); }
370+
371   /// @}
372   void PrintImpl(raw_ostream &OS) const;
373   bool EvaluateAsRelocatableImpl(MCValue &Res,
374@@ -94,6 +103,7 @@ class SparcMCExpr : public MCTargetExpr {
375 
376   static VariantKind parseVariantKind(StringRef name);
377   static bool printVariantKind(raw_ostream &OS, VariantKind Kind);
378+  static Sparc::Fixups getFixupKind(VariantKind Kind);
379 };
380 
381 } // end namespace llvm.
382Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
383===================================================================
384--- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
385+++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
386@@ -94,37 +94,8 @@ getMachineOpValue(const MCInst &MI, const MCOperan
387   assert(MO.isExpr());
388   const MCExpr *Expr = MO.getExpr();
389   if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
390-    switch(SExpr->getKind()) {
391-    default: assert(0 && "Unhandled sparc expression!"); break;
392-    case SparcMCExpr::VK_Sparc_LO:
393-      Fixups.push_back(MCFixup::Create(0, Expr,
394-                                       (MCFixupKind)Sparc::fixup_sparc_lo10));
395-      break;
396-    case SparcMCExpr::VK_Sparc_HI:
397-      Fixups.push_back(MCFixup::Create(0, Expr,
398-                                       (MCFixupKind)Sparc::fixup_sparc_hi22));
399-      break;
400-    case SparcMCExpr::VK_Sparc_H44:
401-      Fixups.push_back(MCFixup::Create(0, Expr,
402-                                       (MCFixupKind)Sparc::fixup_sparc_h44));
403-      break;
404-    case SparcMCExpr::VK_Sparc_M44:
405-      Fixups.push_back(MCFixup::Create(0, Expr,
406-                                       (MCFixupKind)Sparc::fixup_sparc_m44));
407-      break;
408-    case SparcMCExpr::VK_Sparc_L44:
409-      Fixups.push_back(MCFixup::Create(0, Expr,
410-                                       (MCFixupKind)Sparc::fixup_sparc_l44));
411-      break;
412-    case SparcMCExpr::VK_Sparc_HH:
413-      Fixups.push_back(MCFixup::Create(0, Expr,
414-                                       (MCFixupKind)Sparc::fixup_sparc_hh));
415-      break;
416-    case SparcMCExpr::VK_Sparc_HM:
417-      Fixups.push_back(MCFixup::Create(0, Expr,
418-                                       (MCFixupKind)Sparc::fixup_sparc_hm));
419-      break;
420-    }
421+    MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
422+    Fixups.push_back(MCFixup::Create(0, Expr, Kind));
423     return 0;
424   }
425 
426@@ -143,8 +114,15 @@ getCallTargetOpValue(const MCInst &MI, unsigned Op
427   if (MO.isReg() || MO.isImm())
428     return getMachineOpValue(MI, MO, Fixups);
429 
430-  Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
431-                                   (MCFixupKind)Sparc::fixup_sparc_call30));
432+  MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
433+
434+  if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
435+    if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
436+      fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
437+  }
438+
439+  Fixups.push_back(MCFixup::Create(0, MO.getExpr(), fixupKind));
440+
441   return 0;
442 }
443 
444