1 //===-- SparcMCExpr.cpp - Sparc specific MC expression classes --------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains the implementation of the assembly expression modifiers
10 // accepted by the Sparc architecture (e.g. "%hi", "%lo", ...).
12 //===----------------------------------------------------------------------===//
14 #include "SparcMCExpr.h"
15 #include "llvm/BinaryFormat/ELF.h"
16 #include "llvm/MC/MCAssembler.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCObjectStreamer.h"
19 #include "llvm/MC/MCSymbolELF.h"
20 #include "llvm/Support/Casting.h"
24 #define DEBUG_TYPE "sparcmcexpr"
27 SparcMCExpr::create(VariantKind Kind
, const MCExpr
*Expr
,
29 return new (Ctx
) SparcMCExpr(Kind
, Expr
);
32 void SparcMCExpr::printImpl(raw_ostream
&OS
, const MCAsmInfo
*MAI
) const {
34 bool closeParen
= printVariantKind(OS
, Kind
);
36 const MCExpr
*Expr
= getSubExpr();
43 bool SparcMCExpr::printVariantKind(raw_ostream
&OS
, VariantKind Kind
)
46 case VK_Sparc_None
: return false;
47 case VK_Sparc_LO
: OS
<< "%lo("; return true;
48 case VK_Sparc_HI
: OS
<< "%hi("; return true;
49 case VK_Sparc_H44
: OS
<< "%h44("; return true;
50 case VK_Sparc_M44
: OS
<< "%m44("; return true;
51 case VK_Sparc_L44
: OS
<< "%l44("; return true;
52 case VK_Sparc_HH
: OS
<< "%hh("; return true;
53 case VK_Sparc_HM
: OS
<< "%hm("; return true;
54 case VK_Sparc_LM
: OS
<< "%lm("; return true;
55 // FIXME: use %pc22/%pc10, if system assembler supports them.
56 case VK_Sparc_PC22
: OS
<< "%hi("; return true;
57 case VK_Sparc_PC10
: OS
<< "%lo("; return true;
58 // FIXME: use %got22/%got10, if system assembler supports them.
59 case VK_Sparc_GOT22
: OS
<< "%hi("; return true;
60 case VK_Sparc_GOT10
: OS
<< "%lo("; return true;
61 case VK_Sparc_GOT13
: return false;
62 case VK_Sparc_13
: return false;
63 case VK_Sparc_WDISP30
: return false;
64 case VK_Sparc_WPLT30
: return false;
65 case VK_Sparc_R_DISP32
: OS
<< "%r_disp32("; return true;
66 case VK_Sparc_TLS_GD_HI22
: OS
<< "%tgd_hi22("; return true;
67 case VK_Sparc_TLS_GD_LO10
: OS
<< "%tgd_lo10("; return true;
68 case VK_Sparc_TLS_GD_ADD
: OS
<< "%tgd_add("; return true;
69 case VK_Sparc_TLS_GD_CALL
: OS
<< "%tgd_call("; return true;
70 case VK_Sparc_TLS_LDM_HI22
: OS
<< "%tldm_hi22("; return true;
71 case VK_Sparc_TLS_LDM_LO10
: OS
<< "%tldm_lo10("; return true;
72 case VK_Sparc_TLS_LDM_ADD
: OS
<< "%tldm_add("; return true;
73 case VK_Sparc_TLS_LDM_CALL
: OS
<< "%tldm_call("; return true;
74 case VK_Sparc_TLS_LDO_HIX22
: OS
<< "%tldo_hix22("; return true;
75 case VK_Sparc_TLS_LDO_LOX10
: OS
<< "%tldo_lox10("; return true;
76 case VK_Sparc_TLS_LDO_ADD
: OS
<< "%tldo_add("; return true;
77 case VK_Sparc_TLS_IE_HI22
: OS
<< "%tie_hi22("; return true;
78 case VK_Sparc_TLS_IE_LO10
: OS
<< "%tie_lo10("; return true;
79 case VK_Sparc_TLS_IE_LD
: OS
<< "%tie_ld("; return true;
80 case VK_Sparc_TLS_IE_LDX
: OS
<< "%tie_ldx("; return true;
81 case VK_Sparc_TLS_IE_ADD
: OS
<< "%tie_add("; return true;
82 case VK_Sparc_TLS_LE_HIX22
: OS
<< "%tle_hix22("; return true;
83 case VK_Sparc_TLS_LE_LOX10
: OS
<< "%tle_lox10("; return true;
84 case VK_Sparc_HIX22
: OS
<< "%hix("; return true;
85 case VK_Sparc_LOX10
: OS
<< "%lox("; return true;
86 case VK_Sparc_GOTDATA_HIX22
: OS
<< "%gdop_hix22("; return true;
87 case VK_Sparc_GOTDATA_LOX10
: OS
<< "%gdop_lox10("; return true;
88 case VK_Sparc_GOTDATA_OP
: OS
<< "%gdop("; return true;
90 llvm_unreachable("Unhandled SparcMCExpr::VariantKind");
93 SparcMCExpr::VariantKind
SparcMCExpr::parseVariantKind(StringRef name
)
95 return StringSwitch
<SparcMCExpr::VariantKind
>(name
)
96 .Case("lo", VK_Sparc_LO
)
97 .Case("hi", VK_Sparc_HI
)
98 .Case("h44", VK_Sparc_H44
)
99 .Case("m44", VK_Sparc_M44
)
100 .Case("l44", VK_Sparc_L44
)
101 .Case("hh", VK_Sparc_HH
)
102 .Case("uhi", VK_Sparc_HH
) // Nonstandard GNU extension
103 .Case("hm", VK_Sparc_HM
)
104 .Case("ulo", VK_Sparc_HM
) // Nonstandard GNU extension
105 .Case("lm", VK_Sparc_LM
)
106 .Case("pc22", VK_Sparc_PC22
)
107 .Case("pc10", VK_Sparc_PC10
)
108 .Case("got22", VK_Sparc_GOT22
)
109 .Case("got10", VK_Sparc_GOT10
)
110 .Case("got13", VK_Sparc_GOT13
)
111 .Case("r_disp32", VK_Sparc_R_DISP32
)
112 .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22
)
113 .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10
)
114 .Case("tgd_add", VK_Sparc_TLS_GD_ADD
)
115 .Case("tgd_call", VK_Sparc_TLS_GD_CALL
)
116 .Case("tldm_hi22", VK_Sparc_TLS_LDM_HI22
)
117 .Case("tldm_lo10", VK_Sparc_TLS_LDM_LO10
)
118 .Case("tldm_add", VK_Sparc_TLS_LDM_ADD
)
119 .Case("tldm_call", VK_Sparc_TLS_LDM_CALL
)
120 .Case("tldo_hix22", VK_Sparc_TLS_LDO_HIX22
)
121 .Case("tldo_lox10", VK_Sparc_TLS_LDO_LOX10
)
122 .Case("tldo_add", VK_Sparc_TLS_LDO_ADD
)
123 .Case("tie_hi22", VK_Sparc_TLS_IE_HI22
)
124 .Case("tie_lo10", VK_Sparc_TLS_IE_LO10
)
125 .Case("tie_ld", VK_Sparc_TLS_IE_LD
)
126 .Case("tie_ldx", VK_Sparc_TLS_IE_LDX
)
127 .Case("tie_add", VK_Sparc_TLS_IE_ADD
)
128 .Case("tle_hix22", VK_Sparc_TLS_LE_HIX22
)
129 .Case("tle_lox10", VK_Sparc_TLS_LE_LOX10
)
130 .Case("hix", VK_Sparc_HIX22
)
131 .Case("lox", VK_Sparc_LOX10
)
132 .Case("gdop_hix22", VK_Sparc_GOTDATA_HIX22
)
133 .Case("gdop_lox10", VK_Sparc_GOTDATA_LOX10
)
134 .Case("gdop", VK_Sparc_GOTDATA_OP
)
135 .Default(VK_Sparc_None
);
138 Sparc::Fixups
SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind
) {
140 default: llvm_unreachable("Unhandled SparcMCExpr::VariantKind");
141 case VK_Sparc_LO
: return Sparc::fixup_sparc_lo10
;
142 case VK_Sparc_HI
: return Sparc::fixup_sparc_hi22
;
143 case VK_Sparc_H44
: return Sparc::fixup_sparc_h44
;
144 case VK_Sparc_M44
: return Sparc::fixup_sparc_m44
;
145 case VK_Sparc_L44
: return Sparc::fixup_sparc_l44
;
146 case VK_Sparc_HH
: return Sparc::fixup_sparc_hh
;
147 case VK_Sparc_HM
: return Sparc::fixup_sparc_hm
;
148 case VK_Sparc_LM
: return Sparc::fixup_sparc_lm
;
149 case VK_Sparc_PC22
: return Sparc::fixup_sparc_pc22
;
150 case VK_Sparc_PC10
: return Sparc::fixup_sparc_pc10
;
151 case VK_Sparc_GOT22
: return Sparc::fixup_sparc_got22
;
152 case VK_Sparc_GOT10
: return Sparc::fixup_sparc_got10
;
153 case VK_Sparc_GOT13
: return Sparc::fixup_sparc_got13
;
154 case VK_Sparc_13
: return Sparc::fixup_sparc_13
;
155 case VK_Sparc_WPLT30
: return Sparc::fixup_sparc_wplt30
;
156 case VK_Sparc_WDISP30
: return Sparc::fixup_sparc_call30
;
157 case VK_Sparc_TLS_GD_HI22
: return Sparc::fixup_sparc_tls_gd_hi22
;
158 case VK_Sparc_TLS_GD_LO10
: return Sparc::fixup_sparc_tls_gd_lo10
;
159 case VK_Sparc_TLS_GD_ADD
: return Sparc::fixup_sparc_tls_gd_add
;
160 case VK_Sparc_TLS_GD_CALL
: return Sparc::fixup_sparc_tls_gd_call
;
161 case VK_Sparc_TLS_LDM_HI22
: return Sparc::fixup_sparc_tls_ldm_hi22
;
162 case VK_Sparc_TLS_LDM_LO10
: return Sparc::fixup_sparc_tls_ldm_lo10
;
163 case VK_Sparc_TLS_LDM_ADD
: return Sparc::fixup_sparc_tls_ldm_add
;
164 case VK_Sparc_TLS_LDM_CALL
: return Sparc::fixup_sparc_tls_ldm_call
;
165 case VK_Sparc_TLS_LDO_HIX22
: return Sparc::fixup_sparc_tls_ldo_hix22
;
166 case VK_Sparc_TLS_LDO_LOX10
: return Sparc::fixup_sparc_tls_ldo_lox10
;
167 case VK_Sparc_TLS_LDO_ADD
: return Sparc::fixup_sparc_tls_ldo_add
;
168 case VK_Sparc_TLS_IE_HI22
: return Sparc::fixup_sparc_tls_ie_hi22
;
169 case VK_Sparc_TLS_IE_LO10
: return Sparc::fixup_sparc_tls_ie_lo10
;
170 case VK_Sparc_TLS_IE_LD
: return Sparc::fixup_sparc_tls_ie_ld
;
171 case VK_Sparc_TLS_IE_LDX
: return Sparc::fixup_sparc_tls_ie_ldx
;
172 case VK_Sparc_TLS_IE_ADD
: return Sparc::fixup_sparc_tls_ie_add
;
173 case VK_Sparc_TLS_LE_HIX22
: return Sparc::fixup_sparc_tls_le_hix22
;
174 case VK_Sparc_TLS_LE_LOX10
: return Sparc::fixup_sparc_tls_le_lox10
;
175 case VK_Sparc_HIX22
: return Sparc::fixup_sparc_hix22
;
176 case VK_Sparc_LOX10
: return Sparc::fixup_sparc_lox10
;
177 case VK_Sparc_GOTDATA_HIX22
: return Sparc::fixup_sparc_gotdata_hix22
;
178 case VK_Sparc_GOTDATA_LOX10
: return Sparc::fixup_sparc_gotdata_lox10
;
179 case VK_Sparc_GOTDATA_OP
: return Sparc::fixup_sparc_gotdata_op
;
183 bool SparcMCExpr::evaluateAsRelocatableImpl(MCValue
&Res
,
184 const MCAssembler
*Asm
,
185 const MCFixup
*Fixup
) const {
186 return getSubExpr()->evaluateAsRelocatable(Res
, Asm
, Fixup
);
189 static void fixELFSymbolsInTLSFixupsImpl(const MCExpr
*Expr
, MCAssembler
&Asm
) {
190 switch (Expr
->getKind()) {
192 llvm_unreachable("Can't handle nested target expr!");
195 case MCExpr::Constant
:
198 case MCExpr::Binary
: {
199 const MCBinaryExpr
*BE
= cast
<MCBinaryExpr
>(Expr
);
200 fixELFSymbolsInTLSFixupsImpl(BE
->getLHS(), Asm
);
201 fixELFSymbolsInTLSFixupsImpl(BE
->getRHS(), Asm
);
205 case MCExpr::SymbolRef
: {
206 const MCSymbolRefExpr
&SymRef
= *cast
<MCSymbolRefExpr
>(Expr
);
207 cast
<MCSymbolELF
>(SymRef
.getSymbol()).setType(ELF::STT_TLS
);
212 fixELFSymbolsInTLSFixupsImpl(cast
<MCUnaryExpr
>(Expr
)->getSubExpr(), Asm
);
218 void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler
&Asm
) const {
221 case VK_Sparc_TLS_GD_CALL
:
222 case VK_Sparc_TLS_LDM_CALL
: {
223 // The corresponding relocations reference __tls_get_addr, as they call it,
224 // but this is only implicit; we must explicitly add it to our symbol table
225 // to bind it for these uses.
226 MCSymbol
*Symbol
= Asm
.getContext().getOrCreateSymbol("__tls_get_addr");
227 Asm
.registerSymbol(*Symbol
);
228 auto ELFSymbol
= cast
<MCSymbolELF
>(Symbol
);
229 if (!ELFSymbol
->isBindingSet())
230 ELFSymbol
->setBinding(ELF::STB_GLOBAL
);
233 case VK_Sparc_TLS_GD_HI22
:
234 case VK_Sparc_TLS_GD_LO10
:
235 case VK_Sparc_TLS_GD_ADD
:
236 case VK_Sparc_TLS_LDM_HI22
:
237 case VK_Sparc_TLS_LDM_LO10
:
238 case VK_Sparc_TLS_LDM_ADD
:
239 case VK_Sparc_TLS_LDO_HIX22
:
240 case VK_Sparc_TLS_LDO_LOX10
:
241 case VK_Sparc_TLS_LDO_ADD
:
242 case VK_Sparc_TLS_IE_HI22
:
243 case VK_Sparc_TLS_IE_LO10
:
244 case VK_Sparc_TLS_IE_LD
:
245 case VK_Sparc_TLS_IE_LDX
:
246 case VK_Sparc_TLS_IE_ADD
:
247 case VK_Sparc_TLS_LE_HIX22
:
248 case VK_Sparc_TLS_LE_LOX10
: break;
250 fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm
);
253 void SparcMCExpr::visitUsedExpr(MCStreamer
&Streamer
) const {
254 Streamer
.visitUsedExpr(*getSubExpr());