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/MC/MCAssembler.h"
12 #include "llvm/MC/MCContext.h"
13 #include "llvm/MC/MCStreamer.h"
14 #include "llvm/MC/MCSymbolELF.h"
15
16 using namespace llvm;
17
18 #define DEBUG_TYPE "csky-mc-expr"
19
create(const MCExpr * Expr,VariantKind Kind,MCContext & Ctx)20 const CSKYMCExpr *CSKYMCExpr::create(const MCExpr *Expr, VariantKind Kind,
21 MCContext &Ctx) {
22 return new (Ctx) CSKYMCExpr(Kind, Expr);
23 }
24
getVariantKindName(VariantKind Kind)25 StringRef CSKYMCExpr::getVariantKindName(VariantKind Kind) {
26 switch (Kind) {
27 default:
28 llvm_unreachable("Invalid ELF symbol kind");
29 case VK_CSKY_ADDR:
30 return "";
31 case VK_CSKY_PCREL:
32 return "";
33 case VK_CSKY_GOT:
34 return "@GOT";
35 case VK_CSKY_GOTPC:
36 return "@GOTPC";
37 case VK_CSKY_GOTOFF:
38 return "@GOTOFF";
39 case VK_CSKY_PLT:
40 return "@PLT";
41 case VK_CSKY_TPOFF:
42 return "@TPOFF";
43 case VK_CSKY_TLSGD:
44 return "@TLSGD";
45 }
46 }
47
visitUsedExpr(MCStreamer & Streamer) const48 void CSKYMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
49 Streamer.visitUsedExpr(*getSubExpr());
50 }
51
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const52 void CSKYMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
53 Expr->print(OS, MAI);
54 OS << getVariantKindName(getKind());
55 }
56
fixELFSymbolsInTLSFixupsImpl(const MCExpr * Expr,MCAssembler & Asm)57 static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
58 switch (Expr->getKind()) {
59 case MCExpr::Target:
60 llvm_unreachable("Can't handle nested target expression");
61 break;
62 case MCExpr::Constant:
63 break;
64
65 case MCExpr::Binary: {
66 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
67 fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
68 fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
69 break;
70 }
71
72 case MCExpr::SymbolRef: {
73 // We're known to be under a TLS fixup, so any symbol should be
74 // modified. There should be only one.
75 const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
76 cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
77 break;
78 }
79
80 case MCExpr::Unary:
81 fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
82 break;
83 }
84 }
85
fixELFSymbolsInTLSFixups(MCAssembler & Asm) const86 void CSKYMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
87 switch (getKind()) {
88 default:
89 return;
90 case VK_CSKY_TPOFF:
91 case VK_CSKY_TLSGD:
92 break;
93 }
94
95 fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
96 }
97
evaluateAsRelocatableImpl(MCValue & Res,const MCAsmLayout * Layout,const MCFixup * Fixup) const98 bool CSKYMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
99 const MCAsmLayout *Layout,
100 const MCFixup *Fixup) const {
101 if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
102 return false;
103
104 // Some custom fixup types are not valid with symbol difference expressions
105 if (Res.getSymA() && Res.getSymB()) {
106 switch (getKind()) {
107 default:
108 return true;
109
110 case VK_CSKY_ADDR:
111 case VK_CSKY_PCREL:
112 case VK_CSKY_GOT:
113 case VK_CSKY_GOTPC:
114 case VK_CSKY_GOTOFF:
115 case VK_CSKY_TPOFF:
116 case VK_CSKY_TLSGD:
117 return false;
118 }
119 }
120
121 return true;
122 }