1Pull in r199775 from upstream llvm trunk (by Venkatraman Govindaraju):
2
3  [Sparc] Do not add PC to _GLOBAL_OFFSET_TABLE_ address to access GOT in absolute code.
4  Fixes PR#18521
5
6Introduced here: http://svn.freebsd.org/changeset/base/262261
7
8Index: lib/Target/Sparc/SparcAsmPrinter.cpp
9===================================================================
10--- lib/Target/Sparc/SparcAsmPrinter.cpp
11+++ lib/Target/Sparc/SparcAsmPrinter.cpp
12@@ -65,18 +65,24 @@ namespace {
13     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
14                                unsigned AsmVariant, const char *ExtraCode,
15                                raw_ostream &O);
16+
17+    void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI);
18+
19   };
20 } // end of anonymous namespace
21 
22-static MCOperand createPCXCallOP(MCSymbol *Label,
23-                                 MCContext &OutContext)
24-{
25-  const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Label,
26+static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind,
27+                                      MCSymbol *Sym, MCContext &OutContext) {
28+  const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Sym,
29                                                          OutContext);
30-  const SparcMCExpr *expr = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_None,
31-                                                MCSym, OutContext);
32+  const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, OutContext);
33   return MCOperand::CreateExpr(expr);
34+
35 }
36+static MCOperand createPCXCallOP(MCSymbol *Label,
37+                                 MCContext &OutContext) {
38+  return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext);
39+}
40 
41 static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind,
42                                     MCSymbol *GOTLabel, MCSymbol *StartLabel,
43@@ -115,43 +121,101 @@ static void EmitSETHI(MCStreamer &OutStreamer,
44   OutStreamer.EmitInstruction(SETHIInst);
45 }
46 
47-static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1,
48-                   MCOperand &Imm, MCOperand &RD)
49+static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
50+                       MCOperand &RS1, MCOperand &Src2, MCOperand &RD)
51 {
52-  MCInst ORInst;
53-  ORInst.setOpcode(SP::ORri);
54-  ORInst.addOperand(RD);
55-  ORInst.addOperand(RS1);
56-  ORInst.addOperand(Imm);
57-  OutStreamer.EmitInstruction(ORInst);
58+  MCInst Inst;
59+  Inst.setOpcode(Opcode);
60+  Inst.addOperand(RD);
61+  Inst.addOperand(RS1);
62+  Inst.addOperand(Src2);
63+  OutStreamer.EmitInstruction(Inst);
64 }
65 
66+static void EmitOR(MCStreamer &OutStreamer,
67+                   MCOperand &RS1, MCOperand &Imm, MCOperand &RD) {
68+  EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD);
69+}
70+
71 static void EmitADD(MCStreamer &OutStreamer,
72-                    MCOperand &RS1, MCOperand &RS2, MCOperand &RD)
73-{
74-  MCInst ADDInst;
75-  ADDInst.setOpcode(SP::ADDrr);
76-  ADDInst.addOperand(RD);
77-  ADDInst.addOperand(RS1);
78-  ADDInst.addOperand(RS2);
79-  OutStreamer.EmitInstruction(ADDInst);
80+                    MCOperand &RS1, MCOperand &RS2, MCOperand &RD) {
81+  EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD);
82 }
83 
84-static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
85-                                      MCStreamer &OutStreamer,
86-                                      MCContext &OutContext)
87+static void EmitSHL(MCStreamer &OutStreamer,
88+                    MCOperand &RS1, MCOperand &Imm, MCOperand &RD) {
89+  EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD);
90+}
91+
92+
93+static void EmitHiLo(MCStreamer &OutStreamer,  MCSymbol *GOTSym,
94+                     SparcMCExpr::VariantKind HiKind,
95+                     SparcMCExpr::VariantKind LoKind,
96+                     MCOperand &RD,
97+                     MCContext &OutContext) {
98+
99+  MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext);
100+  MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext);
101+  EmitSETHI(OutStreamer, hi, RD);
102+  EmitOR(OutStreamer, RD, lo, RD);
103+}
104+
105+void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI)
106 {
107-  const MachineOperand &MO = MI->getOperand(0);
108-  MCSymbol *StartLabel = OutContext.CreateTempSymbol();
109-  MCSymbol *EndLabel   = OutContext.CreateTempSymbol();
110-  MCSymbol *SethiLabel = OutContext.CreateTempSymbol();
111   MCSymbol *GOTLabel   =
112     OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
113 
114+  const MachineOperand &MO = MI->getOperand(0);
115   assert(MO.getReg() != SP::O7 &&
116          "%o7 is assigned as destination for getpcx!");
117 
118   MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg());
119+
120+
121+  if (TM.getRelocationModel() != Reloc::PIC_) {
122+    // Just load the address of GOT to MCRegOP.
123+    switch(TM.getCodeModel()) {
124+    default:
125+      llvm_unreachable("Unsupported absolute code model");
126+    case CodeModel::Small:
127+      EmitHiLo(OutStreamer, GOTLabel,
128+               SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
129+               MCRegOP, OutContext);
130+      break;
131+    case CodeModel::Medium: {
132+      EmitHiLo(OutStreamer, GOTLabel,
133+               SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44,
134+               MCRegOP, OutContext);
135+      MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(12,
136+                                                                   OutContext));
137+      EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP);
138+      MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44,
139+                                          GOTLabel, OutContext);
140+      EmitOR(OutStreamer, MCRegOP, lo, MCRegOP);
141+      break;
142+    }
143+    case CodeModel::Large: {
144+      EmitHiLo(OutStreamer, GOTLabel,
145+               SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM,
146+               MCRegOP, OutContext);
147+      MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(32,
148+                                                                   OutContext));
149+      EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP);
150+      // Use register %o7 to load the lower 32 bits.
151+      MCOperand RegO7 = MCOperand::CreateReg(SP::O7);
152+      EmitHiLo(OutStreamer, GOTLabel,
153+               SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
154+               RegO7, OutContext);
155+      EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP);
156+    }
157+    }
158+    return;
159+  }
160+
161+  MCSymbol *StartLabel = OutContext.CreateTempSymbol();
162+  MCSymbol *EndLabel   = OutContext.CreateTempSymbol();
163+  MCSymbol *SethiLabel = OutContext.CreateTempSymbol();
164+
165   MCOperand RegO7   = MCOperand::CreateReg(SP::O7);
166 
167   // <StartLabel>:
168@@ -187,7 +251,7 @@ void SparcAsmPrinter::EmitInstruction(const Machin
169     // FIXME: Debug Value.
170     return;
171   case SP::GETPCX:
172-    LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext);
173+    LowerGETPCXAndEmitMCInsts(MI);
174     return;
175   }
176   MachineBasicBlock::const_instr_iterator I = MI;
177Index: test/CodeGen/SPARC/tls.ll
178===================================================================
179--- test/CodeGen/SPARC/tls.ll
180+++ test/CodeGen/SPARC/tls.ll
181@@ -38,8 +38,7 @@ entry:
182 
183 
184 ; v8abs-LABEL:  test_tls_extern
185-; v8abs:        or     {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]]
186-; v8abs:        add    [[PC]], %o7, %[[GOTBASE:[goli][0-7]]]
187+; v8abs:        or     {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_), %[[GOTBASE:[goli][0-7]]]
188 ; v8abs:        sethi  %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]]
189 ; v8abs:        add    [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]]
190 ; v8abs:        ld     [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ld(extern_symbol)
191@@ -47,8 +46,7 @@ entry:
192 ; v8abs:        ld     [%[[R4]]]
193 
194 ; v9abs-LABEL:  test_tls_extern
195-; v9abs:        or     {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]]
196-; v9abs:        add    [[PC]], %o7, %[[GOTBASE:[goli][0-7]]]
197+; v9abs:        or     {{%[goli][0-7]}}, %l44(_GLOBAL_OFFSET_TABLE_), %[[GOTBASE:[goli][0-7]]]
198 ; v9abs:        sethi  %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]]
199 ; v9abs:        add    [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]]
200 ; v9abs:        ldx    [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ldx(extern_symbol)
201