1 //===-- CSKYMCExpr.cpp - CSKY specific MC expression classes -*- C++ -*----===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "CSKYMCExpr.h"
10 #include "CSKYFixupKinds.h"
11 #include "llvm/BinaryFormat/ELF.h"
12 #include "llvm/MC/MCAssembler.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCStreamer.h"
15 #include "llvm/MC/MCSymbolELF.h"
16 #include "llvm/Support/Casting.h"
17
18 using namespace llvm;
19
20 #define DEBUG_TYPE "csky-mc-expr"
21
create(const MCExpr * Expr,VariantKind Kind,MCContext & Ctx)22 const CSKYMCExpr *CSKYMCExpr::create(const MCExpr *Expr, VariantKind Kind,
23 MCContext &Ctx) {
24 return new (Ctx) CSKYMCExpr(Kind, Expr);
25 }
26
getVariantKindName(VariantKind Kind)27 StringRef CSKYMCExpr::getVariantKindName(VariantKind Kind) {
28 switch (Kind) {
29 default:
30 llvm_unreachable("Invalid ELF symbol kind");
31 case VK_CSKY_None:
32 case VK_CSKY_ADDR:
33 return "";
34 case VK_CSKY_ADDR_HI16:
35 return "@HI16";
36 case VK_CSKY_ADDR_LO16:
37 return "@LO16";
38 case VK_CSKY_GOT_IMM18_BY4:
39 case VK_CSKY_GOT:
40 return "@GOT";
41 case VK_CSKY_GOTPC:
42 return "@GOTPC";
43 case VK_CSKY_GOTOFF:
44 return "@GOTOFF";
45 case VK_CSKY_PLT_IMM18_BY4:
46 case VK_CSKY_PLT:
47 return "@PLT";
48 case VK_CSKY_TLSLE:
49 return "@TPOFF";
50 case VK_CSKY_TLSIE:
51 return "@GOTTPOFF";
52 case VK_CSKY_TLSGD:
53 return "@TLSGD32";
54 case VK_CSKY_TLSLDO:
55 return "@TLSLDO32";
56 case VK_CSKY_TLSLDM:
57 return "@TLSLDM32";
58 }
59 }
60
visitUsedExpr(MCStreamer & Streamer) const61 void CSKYMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
62 Streamer.visitUsedExpr(*getSubExpr());
63 }
64
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const65 void CSKYMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
66 Expr->print(OS, MAI);
67 OS << getVariantKindName(getKind());
68 }
69
fixELFSymbolsInTLSFixupsImpl(const MCExpr * Expr,MCAssembler & Asm)70 static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
71 switch (Expr->getKind()) {
72 case MCExpr::Target:
73 llvm_unreachable("Can't handle nested target expression");
74 break;
75 case MCExpr::Constant:
76 break;
77
78 case MCExpr::Binary: {
79 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
80 fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
81 fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
82 break;
83 }
84
85 case MCExpr::SymbolRef: {
86 // We're known to be under a TLS fixup, so any symbol should be
87 // modified. There should be only one.
88 const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
89 cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
90 break;
91 }
92
93 case MCExpr::Unary:
94 fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
95 break;
96 }
97 }
98
fixELFSymbolsInTLSFixups(MCAssembler & Asm) const99 void CSKYMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
100 switch (getKind()) {
101 default:
102 return;
103 case VK_CSKY_TLSLE:
104 case VK_CSKY_TLSIE:
105 case VK_CSKY_TLSGD:
106 break;
107 }
108
109 fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
110 }
111
evaluateAsRelocatableImpl(MCValue & Res,const MCAssembler * Asm,const MCFixup * Fixup) const112 bool CSKYMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
113 const MCFixup *Fixup) const {
114 if (!getSubExpr()->evaluateAsRelocatable(Res, Asm, Fixup))
115 return false;
116
117 // Some custom fixup types are not valid with symbol difference expressions
118 if (Res.getSymA() && Res.getSymB()) {
119 switch (getKind()) {
120 default:
121 return true;
122 case VK_CSKY_GOT:
123 case VK_CSKY_GOT_IMM18_BY4:
124 case VK_CSKY_GOTPC:
125 case VK_CSKY_GOTOFF:
126 case VK_CSKY_PLT:
127 case VK_CSKY_PLT_IMM18_BY4:
128 case VK_CSKY_TLSIE:
129 case VK_CSKY_TLSLE:
130 case VK_CSKY_TLSGD:
131 case VK_CSKY_TLSLDO:
132 case VK_CSKY_TLSLDM:
133 return false;
134 }
135 }
136
137 return true;
138 }
139