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"
23 #define DEBUG_TYPE "sparcmcexpr"
26 SparcMCExpr::create(VariantKind Kind
, const MCExpr
*Expr
,
28 return new (Ctx
) SparcMCExpr(Kind
, Expr
);
31 void SparcMCExpr::printImpl(raw_ostream
&OS
, const MCAsmInfo
*MAI
) const {
33 bool closeParen
= printVariantKind(OS
, Kind
);
35 const MCExpr
*Expr
= getSubExpr();
42 bool SparcMCExpr::printVariantKind(raw_ostream
&OS
, VariantKind Kind
)
44 bool closeParen
= true;
46 case VK_Sparc_None
: closeParen
= false; break;
47 case VK_Sparc_LO
: OS
<< "%lo("; break;
48 case VK_Sparc_HI
: OS
<< "%hi("; break;
49 case VK_Sparc_H44
: OS
<< "%h44("; break;
50 case VK_Sparc_M44
: OS
<< "%m44("; break;
51 case VK_Sparc_L44
: OS
<< "%l44("; break;
52 case VK_Sparc_HH
: OS
<< "%hh("; break;
53 case VK_Sparc_HM
: OS
<< "%hm("; break;
54 // FIXME: use %pc22/%pc10, if system assembler supports them.
55 case VK_Sparc_PC22
: OS
<< "%hi("; break;
56 case VK_Sparc_PC10
: OS
<< "%lo("; break;
57 // FIXME: use %got22/%got10, if system assembler supports them.
58 case VK_Sparc_GOT22
: OS
<< "%hi("; break;
59 case VK_Sparc_GOT10
: OS
<< "%lo("; break;
60 case VK_Sparc_GOT13
: closeParen
= false; break;
61 case VK_Sparc_13
: closeParen
= false; break;
62 case VK_Sparc_WPLT30
: closeParen
= false; break;
63 case VK_Sparc_R_DISP32
: OS
<< "%r_disp32("; break;
64 case VK_Sparc_TLS_GD_HI22
: OS
<< "%tgd_hi22("; break;
65 case VK_Sparc_TLS_GD_LO10
: OS
<< "%tgd_lo10("; break;
66 case VK_Sparc_TLS_GD_ADD
: OS
<< "%tgd_add("; break;
67 case VK_Sparc_TLS_GD_CALL
: OS
<< "%tgd_call("; break;
68 case VK_Sparc_TLS_LDM_HI22
: OS
<< "%tldm_hi22("; break;
69 case VK_Sparc_TLS_LDM_LO10
: OS
<< "%tldm_lo10("; break;
70 case VK_Sparc_TLS_LDM_ADD
: OS
<< "%tldm_add("; break;
71 case VK_Sparc_TLS_LDM_CALL
: OS
<< "%tldm_call("; break;
72 case VK_Sparc_TLS_LDO_HIX22
: OS
<< "%tldo_hix22("; break;
73 case VK_Sparc_TLS_LDO_LOX10
: OS
<< "%tldo_lox10("; break;
74 case VK_Sparc_TLS_LDO_ADD
: OS
<< "%tldo_add("; break;
75 case VK_Sparc_TLS_IE_HI22
: OS
<< "%tie_hi22("; break;
76 case VK_Sparc_TLS_IE_LO10
: OS
<< "%tie_lo10("; break;
77 case VK_Sparc_TLS_IE_LD
: OS
<< "%tie_ld("; break;
78 case VK_Sparc_TLS_IE_LDX
: OS
<< "%tie_ldx("; break;
79 case VK_Sparc_TLS_IE_ADD
: OS
<< "%tie_add("; break;
80 case VK_Sparc_TLS_LE_HIX22
: OS
<< "%tle_hix22("; break;
81 case VK_Sparc_TLS_LE_LOX10
: OS
<< "%tle_lox10("; break;
86 SparcMCExpr::VariantKind
SparcMCExpr::parseVariantKind(StringRef name
)
88 return StringSwitch
<SparcMCExpr::VariantKind
>(name
)
89 .Case("lo", VK_Sparc_LO
)
90 .Case("hi", VK_Sparc_HI
)
91 .Case("h44", VK_Sparc_H44
)
92 .Case("m44", VK_Sparc_M44
)
93 .Case("l44", VK_Sparc_L44
)
94 .Case("hh", VK_Sparc_HH
)
95 .Case("hm", VK_Sparc_HM
)
96 .Case("pc22", VK_Sparc_PC22
)
97 .Case("pc10", VK_Sparc_PC10
)
98 .Case("got22", VK_Sparc_GOT22
)
99 .Case("got10", VK_Sparc_GOT10
)
100 .Case("got13", VK_Sparc_GOT13
)
101 .Case("r_disp32", VK_Sparc_R_DISP32
)
102 .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22
)
103 .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10
)
104 .Case("tgd_add", VK_Sparc_TLS_GD_ADD
)
105 .Case("tgd_call", VK_Sparc_TLS_GD_CALL
)
106 .Case("tldm_hi22", VK_Sparc_TLS_LDM_HI22
)
107 .Case("tldm_lo10", VK_Sparc_TLS_LDM_LO10
)
108 .Case("tldm_add", VK_Sparc_TLS_LDM_ADD
)
109 .Case("tldm_call", VK_Sparc_TLS_LDM_CALL
)
110 .Case("tldo_hix22", VK_Sparc_TLS_LDO_HIX22
)
111 .Case("tldo_lox10", VK_Sparc_TLS_LDO_LOX10
)
112 .Case("tldo_add", VK_Sparc_TLS_LDO_ADD
)
113 .Case("tie_hi22", VK_Sparc_TLS_IE_HI22
)
114 .Case("tie_lo10", VK_Sparc_TLS_IE_LO10
)
115 .Case("tie_ld", VK_Sparc_TLS_IE_LD
)
116 .Case("tie_ldx", VK_Sparc_TLS_IE_LDX
)
117 .Case("tie_add", VK_Sparc_TLS_IE_ADD
)
118 .Case("tle_hix22", VK_Sparc_TLS_LE_HIX22
)
119 .Case("tle_lox10", VK_Sparc_TLS_LE_LOX10
)
120 .Default(VK_Sparc_None
);
123 Sparc::Fixups
SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind
) {
125 default: llvm_unreachable("Unhandled SparcMCExpr::VariantKind");
126 case VK_Sparc_LO
: return Sparc::fixup_sparc_lo10
;
127 case VK_Sparc_HI
: return Sparc::fixup_sparc_hi22
;
128 case VK_Sparc_H44
: return Sparc::fixup_sparc_h44
;
129 case VK_Sparc_M44
: return Sparc::fixup_sparc_m44
;
130 case VK_Sparc_L44
: return Sparc::fixup_sparc_l44
;
131 case VK_Sparc_HH
: return Sparc::fixup_sparc_hh
;
132 case VK_Sparc_HM
: return Sparc::fixup_sparc_hm
;
133 case VK_Sparc_PC22
: return Sparc::fixup_sparc_pc22
;
134 case VK_Sparc_PC10
: return Sparc::fixup_sparc_pc10
;
135 case VK_Sparc_GOT22
: return Sparc::fixup_sparc_got22
;
136 case VK_Sparc_GOT10
: return Sparc::fixup_sparc_got10
;
137 case VK_Sparc_GOT13
: return Sparc::fixup_sparc_got13
;
138 case VK_Sparc_13
: return Sparc::fixup_sparc_13
;
139 case VK_Sparc_WPLT30
: return Sparc::fixup_sparc_wplt30
;
140 case VK_Sparc_TLS_GD_HI22
: return Sparc::fixup_sparc_tls_gd_hi22
;
141 case VK_Sparc_TLS_GD_LO10
: return Sparc::fixup_sparc_tls_gd_lo10
;
142 case VK_Sparc_TLS_GD_ADD
: return Sparc::fixup_sparc_tls_gd_add
;
143 case VK_Sparc_TLS_GD_CALL
: return Sparc::fixup_sparc_tls_gd_call
;
144 case VK_Sparc_TLS_LDM_HI22
: return Sparc::fixup_sparc_tls_ldm_hi22
;
145 case VK_Sparc_TLS_LDM_LO10
: return Sparc::fixup_sparc_tls_ldm_lo10
;
146 case VK_Sparc_TLS_LDM_ADD
: return Sparc::fixup_sparc_tls_ldm_add
;
147 case VK_Sparc_TLS_LDM_CALL
: return Sparc::fixup_sparc_tls_ldm_call
;
148 case VK_Sparc_TLS_LDO_HIX22
: return Sparc::fixup_sparc_tls_ldo_hix22
;
149 case VK_Sparc_TLS_LDO_LOX10
: return Sparc::fixup_sparc_tls_ldo_lox10
;
150 case VK_Sparc_TLS_LDO_ADD
: return Sparc::fixup_sparc_tls_ldo_add
;
151 case VK_Sparc_TLS_IE_HI22
: return Sparc::fixup_sparc_tls_ie_hi22
;
152 case VK_Sparc_TLS_IE_LO10
: return Sparc::fixup_sparc_tls_ie_lo10
;
153 case VK_Sparc_TLS_IE_LD
: return Sparc::fixup_sparc_tls_ie_ld
;
154 case VK_Sparc_TLS_IE_LDX
: return Sparc::fixup_sparc_tls_ie_ldx
;
155 case VK_Sparc_TLS_IE_ADD
: return Sparc::fixup_sparc_tls_ie_add
;
156 case VK_Sparc_TLS_LE_HIX22
: return Sparc::fixup_sparc_tls_le_hix22
;
157 case VK_Sparc_TLS_LE_LOX10
: return Sparc::fixup_sparc_tls_le_lox10
;
162 SparcMCExpr::evaluateAsRelocatableImpl(MCValue
&Res
,
163 const MCAsmLayout
*Layout
,
164 const MCFixup
*Fixup
) const {
165 return getSubExpr()->evaluateAsRelocatable(Res
, Layout
, Fixup
);
168 static void fixELFSymbolsInTLSFixupsImpl(const MCExpr
*Expr
, MCAssembler
&Asm
) {
169 switch (Expr
->getKind()) {
171 llvm_unreachable("Can't handle nested target expr!");
174 case MCExpr::Constant
:
177 case MCExpr::Binary
: {
178 const MCBinaryExpr
*BE
= cast
<MCBinaryExpr
>(Expr
);
179 fixELFSymbolsInTLSFixupsImpl(BE
->getLHS(), Asm
);
180 fixELFSymbolsInTLSFixupsImpl(BE
->getRHS(), Asm
);
184 case MCExpr::SymbolRef
: {
185 const MCSymbolRefExpr
&SymRef
= *cast
<MCSymbolRefExpr
>(Expr
);
186 cast
<MCSymbolELF
>(SymRef
.getSymbol()).setType(ELF::STT_TLS
);
191 fixELFSymbolsInTLSFixupsImpl(cast
<MCUnaryExpr
>(Expr
)->getSubExpr(), Asm
);
197 void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler
&Asm
) const {
200 case VK_Sparc_TLS_GD_CALL
:
201 case VK_Sparc_TLS_LDM_CALL
: {
202 // The corresponding relocations reference __tls_get_addr, as they call it,
203 // but this is only implicit; we must explicitly add it to our symbol table
204 // to bind it for these uses.
205 MCSymbol
*Symbol
= Asm
.getContext().getOrCreateSymbol("__tls_get_addr");
206 Asm
.registerSymbol(*Symbol
);
207 auto ELFSymbol
= cast
<MCSymbolELF
>(Symbol
);
208 if (!ELFSymbol
->isBindingSet()) {
209 ELFSymbol
->setBinding(ELF::STB_GLOBAL
);
210 ELFSymbol
->setExternal(true);
214 case VK_Sparc_TLS_GD_HI22
:
215 case VK_Sparc_TLS_GD_LO10
:
216 case VK_Sparc_TLS_GD_ADD
:
217 case VK_Sparc_TLS_LDM_HI22
:
218 case VK_Sparc_TLS_LDM_LO10
:
219 case VK_Sparc_TLS_LDM_ADD
:
220 case VK_Sparc_TLS_LDO_HIX22
:
221 case VK_Sparc_TLS_LDO_LOX10
:
222 case VK_Sparc_TLS_LDO_ADD
:
223 case VK_Sparc_TLS_IE_HI22
:
224 case VK_Sparc_TLS_IE_LO10
:
225 case VK_Sparc_TLS_IE_LD
:
226 case VK_Sparc_TLS_IE_LDX
:
227 case VK_Sparc_TLS_IE_ADD
:
228 case VK_Sparc_TLS_LE_HIX22
:
229 case VK_Sparc_TLS_LE_LOX10
: break;
231 fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm
);
234 void SparcMCExpr::visitUsedExpr(MCStreamer
&Streamer
) const {
235 Streamer
.visitUsedExpr(*getSubExpr());