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://svnweb.freebsd.org/changeset/base/262261 6263320Sdim 7269012SemasteIndex: 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+ 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