xref: /freebsd/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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