1263320SdimPull in r199775 from upstream llvm trunk (by Venkatraman Govindaraju):
2263320Sdim
3263320Sdim  [Sparc] Do not add PC to _GLOBAL_OFFSET_TABLE_ address to access GOT in absolute code.
4263320Sdim  Fixes PR#18521
5263320Sdim
6263320SdimIntroduced here: http://svn.freebsd.org/changeset/base/262261
7263320Sdim
8263320SdimIndex: lib/Target/Sparc/SparcAsmPrinter.cpp
9263320Sdim===================================================================
10263320Sdim--- lib/Target/Sparc/SparcAsmPrinter.cpp
11263320Sdim+++ lib/Target/Sparc/SparcAsmPrinter.cpp
12263320Sdim@@ -65,18 +65,24 @@ namespace {
13263320Sdim     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
14263320Sdim                                unsigned AsmVariant, const char *ExtraCode,
15263320Sdim                                raw_ostream &O);
16263320Sdim+
17263320Sdim+    void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI);
18263320Sdim+
19263320Sdim   };
20263320Sdim } // end of anonymous namespace
21263320Sdim 
22263320Sdim-static MCOperand createPCXCallOP(MCSymbol *Label,
23263320Sdim-                                 MCContext &OutContext)
24263320Sdim-{
25263320Sdim-  const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Label,
26263320Sdim+static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind,
27263320Sdim+                                      MCSymbol *Sym, MCContext &OutContext) {
28263320Sdim+  const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Sym,
29263320Sdim                                                          OutContext);
30263320Sdim-  const SparcMCExpr *expr = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_None,
31263320Sdim-                                                MCSym, OutContext);
32263320Sdim+  const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, OutContext);
33263320Sdim   return MCOperand::CreateExpr(expr);
34263320Sdim+
35263320Sdim }
36263320Sdim+static MCOperand createPCXCallOP(MCSymbol *Label,
37263320Sdim+                                 MCContext &OutContext) {
38263320Sdim+  return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext);
39263320Sdim+}
40263320Sdim 
41263320Sdim static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind,
42263320Sdim                                     MCSymbol *GOTLabel, MCSymbol *StartLabel,
43263320Sdim@@ -115,43 +121,101 @@ static void EmitSETHI(MCStreamer &OutStreamer,
44263320Sdim   OutStreamer.EmitInstruction(SETHIInst);
45263320Sdim }
46263320Sdim 
47263320Sdim-static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1,
48263320Sdim-                   MCOperand &Imm, MCOperand &RD)
49263320Sdim+static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
50263320Sdim+                       MCOperand &RS1, MCOperand &Src2, MCOperand &RD)
51263320Sdim {
52263320Sdim-  MCInst ORInst;
53263320Sdim-  ORInst.setOpcode(SP::ORri);
54263320Sdim-  ORInst.addOperand(RD);
55263320Sdim-  ORInst.addOperand(RS1);
56263320Sdim-  ORInst.addOperand(Imm);
57263320Sdim-  OutStreamer.EmitInstruction(ORInst);
58263320Sdim+  MCInst Inst;
59263320Sdim+  Inst.setOpcode(Opcode);
60263320Sdim+  Inst.addOperand(RD);
61263320Sdim+  Inst.addOperand(RS1);
62263320Sdim+  Inst.addOperand(Src2);
63263320Sdim+  OutStreamer.EmitInstruction(Inst);
64263320Sdim }
65263320Sdim 
66263320Sdim+static void EmitOR(MCStreamer &OutStreamer,
67263320Sdim+                   MCOperand &RS1, MCOperand &Imm, MCOperand &RD) {
68263320Sdim+  EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD);
69263320Sdim+}
70263320Sdim+
71263320Sdim static void EmitADD(MCStreamer &OutStreamer,
72263320Sdim-                    MCOperand &RS1, MCOperand &RS2, MCOperand &RD)
73263320Sdim-{
74263320Sdim-  MCInst ADDInst;
75263320Sdim-  ADDInst.setOpcode(SP::ADDrr);
76263320Sdim-  ADDInst.addOperand(RD);
77263320Sdim-  ADDInst.addOperand(RS1);
78263320Sdim-  ADDInst.addOperand(RS2);
79263320Sdim-  OutStreamer.EmitInstruction(ADDInst);
80263320Sdim+                    MCOperand &RS1, MCOperand &RS2, MCOperand &RD) {
81263320Sdim+  EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD);
82263320Sdim }
83263320Sdim 
84263320Sdim-static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
85263320Sdim-                                      MCStreamer &OutStreamer,
86263320Sdim-                                      MCContext &OutContext)
87263320Sdim+static void EmitSHL(MCStreamer &OutStreamer,
88263320Sdim+                    MCOperand &RS1, MCOperand &Imm, MCOperand &RD) {
89263320Sdim+  EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD);
90263320Sdim+}
91263320Sdim+
92263320Sdim+
93263320Sdim+static void EmitHiLo(MCStreamer &OutStreamer,  MCSymbol *GOTSym,
94263320Sdim+                     SparcMCExpr::VariantKind HiKind,
95263320Sdim+                     SparcMCExpr::VariantKind LoKind,
96263320Sdim+                     MCOperand &RD,
97263320Sdim+                     MCContext &OutContext) {
98263320Sdim+
99263320Sdim+  MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext);
100263320Sdim+  MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext);
101263320Sdim+  EmitSETHI(OutStreamer, hi, RD);
102263320Sdim+  EmitOR(OutStreamer, RD, lo, RD);
103263320Sdim+}
104263320Sdim+
105263320Sdim+void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI)
106263320Sdim {
107263320Sdim-  const MachineOperand &MO = MI->getOperand(0);
108263320Sdim-  MCSymbol *StartLabel = OutContext.CreateTempSymbol();
109263320Sdim-  MCSymbol *EndLabel   = OutContext.CreateTempSymbol();
110263320Sdim-  MCSymbol *SethiLabel = OutContext.CreateTempSymbol();
111263320Sdim   MCSymbol *GOTLabel   =
112263320Sdim     OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
113263320Sdim 
114263320Sdim+  const MachineOperand &MO = MI->getOperand(0);
115263320Sdim   assert(MO.getReg() != SP::O7 &&
116263320Sdim          "%o7 is assigned as destination for getpcx!");
117263320Sdim 
118263320Sdim   MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg());
119263320Sdim+
120263320Sdim+
121263320Sdim+  if (TM.getRelocationModel() != Reloc::PIC_) {
122263320Sdim+    // Just load the address of GOT to MCRegOP.
123263320Sdim+    switch(TM.getCodeModel()) {
124263320Sdim+    default:
125263320Sdim+      llvm_unreachable("Unsupported absolute code model");
126263320Sdim+    case CodeModel::Small:
127263320Sdim+      EmitHiLo(OutStreamer, GOTLabel,
128263320Sdim+               SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
129263320Sdim+               MCRegOP, OutContext);
130263320Sdim+      break;
131263320Sdim+    case CodeModel::Medium: {
132263320Sdim+      EmitHiLo(OutStreamer, GOTLabel,
133263320Sdim+               SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44,
134263320Sdim+               MCRegOP, OutContext);
135263320Sdim+      MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(12,
136263320Sdim+                                                                   OutContext));
137263320Sdim+      EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP);
138263320Sdim+      MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44,
139263320Sdim+                                          GOTLabel, OutContext);
140263320Sdim+      EmitOR(OutStreamer, MCRegOP, lo, MCRegOP);
141263320Sdim+      break;
142263320Sdim+    }
143263320Sdim+    case CodeModel::Large: {
144263320Sdim+      EmitHiLo(OutStreamer, GOTLabel,
145263320Sdim+               SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM,
146263320Sdim+               MCRegOP, OutContext);
147263320Sdim+      MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(32,
148263320Sdim+                                                                   OutContext));
149263320Sdim+      EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP);
150263320Sdim+      // Use register %o7 to load the lower 32 bits.
151263320Sdim+      MCOperand RegO7 = MCOperand::CreateReg(SP::O7);
152263320Sdim+      EmitHiLo(OutStreamer, GOTLabel,
153263320Sdim+               SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
154263320Sdim+               RegO7, OutContext);
155263320Sdim+      EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP);
156263320Sdim+    }
157263320Sdim+    }
158263320Sdim+    return;
159263320Sdim+  }
160263320Sdim+
161263320Sdim+  MCSymbol *StartLabel = OutContext.CreateTempSymbol();
162263320Sdim+  MCSymbol *EndLabel   = OutContext.CreateTempSymbol();
163263320Sdim+  MCSymbol *SethiLabel = OutContext.CreateTempSymbol();
164263320Sdim+
165263320Sdim   MCOperand RegO7   = MCOperand::CreateReg(SP::O7);
166263320Sdim 
167263320Sdim   // <StartLabel>:
168263320Sdim@@ -187,7 +251,7 @@ void SparcAsmPrinter::EmitInstruction(const Machin
169263320Sdim     // FIXME: Debug Value.
170263320Sdim     return;
171263320Sdim   case SP::GETPCX:
172263320Sdim-    LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext);
173263320Sdim+    LowerGETPCXAndEmitMCInsts(MI);
174263320Sdim     return;
175263320Sdim   }
176263320Sdim   MachineBasicBlock::const_instr_iterator I = MI;
177263320SdimIndex: test/CodeGen/SPARC/tls.ll
178263320Sdim===================================================================
179263320Sdim--- test/CodeGen/SPARC/tls.ll
180263320Sdim+++ test/CodeGen/SPARC/tls.ll
181263320Sdim@@ -38,8 +38,7 @@ entry:
182263320Sdim 
183263320Sdim 
184263320Sdim ; v8abs-LABEL:  test_tls_extern
185263320Sdim-; v8abs:        or     {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]]
186263320Sdim-; v8abs:        add    [[PC]], %o7, %[[GOTBASE:[goli][0-7]]]
187263320Sdim+; v8abs:        or     {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_), %[[GOTBASE:[goli][0-7]]]
188263320Sdim ; v8abs:        sethi  %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]]
189263320Sdim ; v8abs:        add    [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]]
190263320Sdim ; v8abs:        ld     [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ld(extern_symbol)
191263320Sdim@@ -47,8 +46,7 @@ entry:
192263320Sdim ; v8abs:        ld     [%[[R4]]]
193263320Sdim 
194263320Sdim ; v9abs-LABEL:  test_tls_extern
195263320Sdim-; v9abs:        or     {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]]
196263320Sdim-; v9abs:        add    [[PC]], %o7, %[[GOTBASE:[goli][0-7]]]
197263320Sdim+; v9abs:        or     {{%[goli][0-7]}}, %l44(_GLOBAL_OFFSET_TABLE_), %[[GOTBASE:[goli][0-7]]]
198263320Sdim ; v9abs:        sethi  %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]]
199263320Sdim ; v9abs:        add    [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]]
200263320Sdim ; v9abs:        ldx    [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ldx(extern_symbol)
201