1fe6060f1SDimitry Andric //===-- CSKYMCExpr.cpp - CSKY specific MC expression classes -*- C++ -*----===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric
9fe6060f1SDimitry Andric #include "CSKYMCExpr.h"
10fe6060f1SDimitry Andric #include "CSKYFixupKinds.h"
1181ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
12fe6060f1SDimitry Andric #include "llvm/MC/MCAssembler.h"
13fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h"
14fe6060f1SDimitry Andric #include "llvm/MC/MCStreamer.h"
15fe6060f1SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
1681ad6265SDimitry Andric #include "llvm/Support/Casting.h"
17fe6060f1SDimitry Andric
18fe6060f1SDimitry Andric using namespace llvm;
19fe6060f1SDimitry Andric
20fe6060f1SDimitry Andric #define DEBUG_TYPE "csky-mc-expr"
21fe6060f1SDimitry Andric
create(const MCExpr * Expr,VariantKind Kind,MCContext & Ctx)22fe6060f1SDimitry Andric const CSKYMCExpr *CSKYMCExpr::create(const MCExpr *Expr, VariantKind Kind,
23fe6060f1SDimitry Andric MCContext &Ctx) {
24fe6060f1SDimitry Andric return new (Ctx) CSKYMCExpr(Kind, Expr);
25fe6060f1SDimitry Andric }
26fe6060f1SDimitry Andric
getVariantKindName(VariantKind Kind)27fe6060f1SDimitry Andric StringRef CSKYMCExpr::getVariantKindName(VariantKind Kind) {
28fe6060f1SDimitry Andric switch (Kind) {
29fe6060f1SDimitry Andric default:
30fe6060f1SDimitry Andric llvm_unreachable("Invalid ELF symbol kind");
31349cc55cSDimitry Andric case VK_CSKY_None:
32fe6060f1SDimitry Andric case VK_CSKY_ADDR:
33fe6060f1SDimitry Andric return "";
34349cc55cSDimitry Andric case VK_CSKY_ADDR_HI16:
35349cc55cSDimitry Andric return "@HI16";
36349cc55cSDimitry Andric case VK_CSKY_ADDR_LO16:
37349cc55cSDimitry Andric return "@LO16";
38349cc55cSDimitry Andric case VK_CSKY_GOT_IMM18_BY4:
39fe6060f1SDimitry Andric case VK_CSKY_GOT:
40fe6060f1SDimitry Andric return "@GOT";
41fe6060f1SDimitry Andric case VK_CSKY_GOTPC:
42fe6060f1SDimitry Andric return "@GOTPC";
43fe6060f1SDimitry Andric case VK_CSKY_GOTOFF:
44fe6060f1SDimitry Andric return "@GOTOFF";
45349cc55cSDimitry Andric case VK_CSKY_PLT_IMM18_BY4:
46fe6060f1SDimitry Andric case VK_CSKY_PLT:
47fe6060f1SDimitry Andric return "@PLT";
48349cc55cSDimitry Andric case VK_CSKY_TLSLE:
49fe6060f1SDimitry Andric return "@TPOFF";
50349cc55cSDimitry Andric case VK_CSKY_TLSIE:
51349cc55cSDimitry Andric return "@GOTTPOFF";
52fe6060f1SDimitry Andric case VK_CSKY_TLSGD:
53349cc55cSDimitry Andric return "@TLSGD32";
54349cc55cSDimitry Andric case VK_CSKY_TLSLDO:
55349cc55cSDimitry Andric return "@TLSLDO32";
56349cc55cSDimitry Andric case VK_CSKY_TLSLDM:
57349cc55cSDimitry Andric return "@TLSLDM32";
58fe6060f1SDimitry Andric }
59fe6060f1SDimitry Andric }
60fe6060f1SDimitry Andric
visitUsedExpr(MCStreamer & Streamer) const61fe6060f1SDimitry Andric void CSKYMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
62fe6060f1SDimitry Andric Streamer.visitUsedExpr(*getSubExpr());
63fe6060f1SDimitry Andric }
64fe6060f1SDimitry Andric
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const65fe6060f1SDimitry Andric void CSKYMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
66fe6060f1SDimitry Andric Expr->print(OS, MAI);
67fe6060f1SDimitry Andric OS << getVariantKindName(getKind());
68fe6060f1SDimitry Andric }
69fe6060f1SDimitry Andric
fixELFSymbolsInTLSFixupsImpl(const MCExpr * Expr,MCAssembler & Asm)70fe6060f1SDimitry Andric static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
71fe6060f1SDimitry Andric switch (Expr->getKind()) {
72fe6060f1SDimitry Andric case MCExpr::Target:
73fe6060f1SDimitry Andric llvm_unreachable("Can't handle nested target expression");
74fe6060f1SDimitry Andric break;
75fe6060f1SDimitry Andric case MCExpr::Constant:
76fe6060f1SDimitry Andric break;
77fe6060f1SDimitry Andric
78fe6060f1SDimitry Andric case MCExpr::Binary: {
79fe6060f1SDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
80fe6060f1SDimitry Andric fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
81fe6060f1SDimitry Andric fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
82fe6060f1SDimitry Andric break;
83fe6060f1SDimitry Andric }
84fe6060f1SDimitry Andric
85fe6060f1SDimitry Andric case MCExpr::SymbolRef: {
86fe6060f1SDimitry Andric // We're known to be under a TLS fixup, so any symbol should be
87fe6060f1SDimitry Andric // modified. There should be only one.
88fe6060f1SDimitry Andric const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
89fe6060f1SDimitry Andric cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
90fe6060f1SDimitry Andric break;
91fe6060f1SDimitry Andric }
92fe6060f1SDimitry Andric
93fe6060f1SDimitry Andric case MCExpr::Unary:
94fe6060f1SDimitry Andric fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
95fe6060f1SDimitry Andric break;
96fe6060f1SDimitry Andric }
97fe6060f1SDimitry Andric }
98fe6060f1SDimitry Andric
fixELFSymbolsInTLSFixups(MCAssembler & Asm) const99fe6060f1SDimitry Andric void CSKYMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
100fe6060f1SDimitry Andric switch (getKind()) {
101fe6060f1SDimitry Andric default:
102fe6060f1SDimitry Andric return;
103349cc55cSDimitry Andric case VK_CSKY_TLSLE:
104349cc55cSDimitry Andric case VK_CSKY_TLSIE:
105fe6060f1SDimitry Andric case VK_CSKY_TLSGD:
106fe6060f1SDimitry Andric break;
107fe6060f1SDimitry Andric }
108fe6060f1SDimitry Andric
109fe6060f1SDimitry Andric fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
110fe6060f1SDimitry Andric }
111fe6060f1SDimitry Andric
evaluateAsRelocatableImpl(MCValue & Res,const MCAssembler * Asm,const MCFixup * Fixup) const112*0fca6ea1SDimitry Andric bool CSKYMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
113fe6060f1SDimitry Andric const MCFixup *Fixup) const {
114*0fca6ea1SDimitry Andric if (!getSubExpr()->evaluateAsRelocatable(Res, Asm, Fixup))
115fe6060f1SDimitry Andric return false;
116fe6060f1SDimitry Andric
117fe6060f1SDimitry Andric // Some custom fixup types are not valid with symbol difference expressions
118fe6060f1SDimitry Andric if (Res.getSymA() && Res.getSymB()) {
119fe6060f1SDimitry Andric switch (getKind()) {
120fe6060f1SDimitry Andric default:
121fe6060f1SDimitry Andric return true;
122fe6060f1SDimitry Andric case VK_CSKY_GOT:
123349cc55cSDimitry Andric case VK_CSKY_GOT_IMM18_BY4:
124fe6060f1SDimitry Andric case VK_CSKY_GOTPC:
125fe6060f1SDimitry Andric case VK_CSKY_GOTOFF:
126349cc55cSDimitry Andric case VK_CSKY_PLT:
127349cc55cSDimitry Andric case VK_CSKY_PLT_IMM18_BY4:
128349cc55cSDimitry Andric case VK_CSKY_TLSIE:
129349cc55cSDimitry Andric case VK_CSKY_TLSLE:
130fe6060f1SDimitry Andric case VK_CSKY_TLSGD:
131349cc55cSDimitry Andric case VK_CSKY_TLSLDO:
132349cc55cSDimitry Andric case VK_CSKY_TLSLDM:
133fe6060f1SDimitry Andric return false;
134fe6060f1SDimitry Andric }
135fe6060f1SDimitry Andric }
136fe6060f1SDimitry Andric
137fe6060f1SDimitry Andric return true;
138fe6060f1SDimitry Andric }
139