1 //===-- VEMCExpr.cpp - VE 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 VE architecture (e.g. "%hi", "%lo", ...).
12 //===----------------------------------------------------------------------===//
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/MC/MCValue.h"
21 #include "llvm/Support/Casting.h"
25 #define DEBUG_TYPE "vemcexpr"
27 const VEMCExpr
*VEMCExpr::create(VariantKind Kind
, const MCExpr
*Expr
,
29 return new (Ctx
) VEMCExpr(Kind
, Expr
);
32 void VEMCExpr::printImpl(raw_ostream
&OS
, const MCAsmInfo
*MAI
) const {
34 bool closeParen
= printVariantKind(OS
, Kind
);
36 const MCExpr
*Expr
= getSubExpr();
41 printVariantKindSuffix(OS
, Kind
);
44 bool VEMCExpr::printVariantKind(raw_ostream
&OS
, VariantKind Kind
) {
56 case VK_VE_GOTOFF_HI32
:
57 case VK_VE_GOTOFF_LO32
:
60 case VK_VE_TLS_GD_HI32
:
61 case VK_VE_TLS_GD_LO32
:
62 case VK_VE_TPOFF_HI32
:
63 case VK_VE_TPOFF_LO32
:
64 // Use suffix for these variant kinds
70 void VEMCExpr::printVariantKindSuffix(raw_ostream
&OS
, VariantKind Kind
) {
93 case VK_VE_GOTOFF_HI32
:
96 case VK_VE_GOTOFF_LO32
:
105 case VK_VE_TLS_GD_HI32
:
108 case VK_VE_TLS_GD_LO32
:
111 case VK_VE_TPOFF_HI32
:
114 case VK_VE_TPOFF_LO32
:
120 VEMCExpr::VariantKind
VEMCExpr::parseVariantKind(StringRef name
) {
121 return StringSwitch
<VEMCExpr::VariantKind
>(name
)
122 .Case("hi", VK_VE_HI32
)
123 .Case("lo", VK_VE_LO32
)
124 .Case("pc_hi", VK_VE_PC_HI32
)
125 .Case("pc_lo", VK_VE_PC_LO32
)
126 .Case("got_hi", VK_VE_GOT_HI32
)
127 .Case("got_lo", VK_VE_GOT_LO32
)
128 .Case("gotoff_hi", VK_VE_GOTOFF_HI32
)
129 .Case("gotoff_lo", VK_VE_GOTOFF_LO32
)
130 .Case("plt_hi", VK_VE_PLT_HI32
)
131 .Case("plt_lo", VK_VE_PLT_LO32
)
132 .Case("tls_gd_hi", VK_VE_TLS_GD_HI32
)
133 .Case("tls_gd_lo", VK_VE_TLS_GD_LO32
)
134 .Case("tpoff_hi", VK_VE_TPOFF_HI32
)
135 .Case("tpoff_lo", VK_VE_TPOFF_LO32
)
136 .Default(VK_VE_None
);
139 VE::Fixups
VEMCExpr::getFixupKind(VEMCExpr::VariantKind Kind
) {
142 llvm_unreachable("Unhandled VEMCExpr::VariantKind");
144 return VE::fixup_ve_reflong
;
146 return VE::fixup_ve_hi32
;
148 return VE::fixup_ve_lo32
;
150 return VE::fixup_ve_pc_hi32
;
152 return VE::fixup_ve_pc_lo32
;
154 return VE::fixup_ve_got_hi32
;
156 return VE::fixup_ve_got_lo32
;
157 case VK_VE_GOTOFF_HI32
:
158 return VE::fixup_ve_gotoff_hi32
;
159 case VK_VE_GOTOFF_LO32
:
160 return VE::fixup_ve_gotoff_lo32
;
162 return VE::fixup_ve_plt_hi32
;
164 return VE::fixup_ve_plt_lo32
;
165 case VK_VE_TLS_GD_HI32
:
166 return VE::fixup_ve_tls_gd_hi32
;
167 case VK_VE_TLS_GD_LO32
:
168 return VE::fixup_ve_tls_gd_lo32
;
169 case VK_VE_TPOFF_HI32
:
170 return VE::fixup_ve_tpoff_hi32
;
171 case VK_VE_TPOFF_LO32
:
172 return VE::fixup_ve_tpoff_lo32
;
176 bool VEMCExpr::evaluateAsRelocatableImpl(MCValue
&Res
, const MCAssembler
*Asm
,
177 const MCFixup
*Fixup
) const {
178 if (!getSubExpr()->evaluateAsRelocatable(Res
, Asm
, Fixup
))
182 MCValue::get(Res
.getSymA(), Res
.getSymB(), Res
.getConstant(), getKind());
187 static void fixELFSymbolsInTLSFixupsImpl(const MCExpr
*Expr
, MCAssembler
&Asm
) {
188 switch (Expr
->getKind()) {
190 llvm_unreachable("Can't handle nested target expr!");
193 case MCExpr::Constant
:
196 case MCExpr::Binary
: {
197 const MCBinaryExpr
*BE
= cast
<MCBinaryExpr
>(Expr
);
198 fixELFSymbolsInTLSFixupsImpl(BE
->getLHS(), Asm
);
199 fixELFSymbolsInTLSFixupsImpl(BE
->getRHS(), Asm
);
203 case MCExpr::SymbolRef
: {
204 // We're known to be under a TLS fixup, so any symbol should be
205 // modified. There should be only one.
206 const MCSymbolRefExpr
&SymRef
= *cast
<MCSymbolRefExpr
>(Expr
);
207 cast
<MCSymbolELF
>(SymRef
.getSymbol()).setType(ELF::STT_TLS
);
212 fixELFSymbolsInTLSFixupsImpl(cast
<MCUnaryExpr
>(Expr
)->getSubExpr(), Asm
);
217 void VEMCExpr::visitUsedExpr(MCStreamer
&Streamer
) const {
218 Streamer
.visitUsedExpr(*getSubExpr());
221 void VEMCExpr::fixELFSymbolsInTLSFixups(MCAssembler
&Asm
) const {
225 case VK_VE_TLS_GD_HI32
:
226 case VK_VE_TLS_GD_LO32
:
227 case VK_VE_TPOFF_HI32
:
228 case VK_VE_TPOFF_LO32
:
231 fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm
);