1*9880d681SAndroid Build Coastguard Worker //===-- AArch64MCExpr.cpp - AArch64 specific MC expression classes --------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains the implementation of the assembly expression modifiers
11*9880d681SAndroid Build Coastguard Worker // accepted by the AArch64 architecture (e.g. ":lo12:", ":gottprel_g1:", ...).
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "AArch64MCExpr.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAssembler.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCStreamer.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbolELF.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCValue.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/ELF.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
23*9880d681SAndroid Build Coastguard Worker
24*9880d681SAndroid Build Coastguard Worker using namespace llvm;
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "aarch64symbolrefexpr"
27*9880d681SAndroid Build Coastguard Worker
create(const MCExpr * Expr,VariantKind Kind,MCContext & Ctx)28*9880d681SAndroid Build Coastguard Worker const AArch64MCExpr *AArch64MCExpr::create(const MCExpr *Expr, VariantKind Kind,
29*9880d681SAndroid Build Coastguard Worker MCContext &Ctx) {
30*9880d681SAndroid Build Coastguard Worker return new (Ctx) AArch64MCExpr(Expr, Kind);
31*9880d681SAndroid Build Coastguard Worker }
32*9880d681SAndroid Build Coastguard Worker
getVariantKindName() const33*9880d681SAndroid Build Coastguard Worker StringRef AArch64MCExpr::getVariantKindName() const {
34*9880d681SAndroid Build Coastguard Worker switch (static_cast<uint32_t>(getKind())) {
35*9880d681SAndroid Build Coastguard Worker case VK_CALL: return "";
36*9880d681SAndroid Build Coastguard Worker case VK_LO12: return ":lo12:";
37*9880d681SAndroid Build Coastguard Worker case VK_ABS_G3: return ":abs_g3:";
38*9880d681SAndroid Build Coastguard Worker case VK_ABS_G2: return ":abs_g2:";
39*9880d681SAndroid Build Coastguard Worker case VK_ABS_G2_S: return ":abs_g2_s:";
40*9880d681SAndroid Build Coastguard Worker case VK_ABS_G2_NC: return ":abs_g2_nc:";
41*9880d681SAndroid Build Coastguard Worker case VK_ABS_G1: return ":abs_g1:";
42*9880d681SAndroid Build Coastguard Worker case VK_ABS_G1_S: return ":abs_g1_s:";
43*9880d681SAndroid Build Coastguard Worker case VK_ABS_G1_NC: return ":abs_g1_nc:";
44*9880d681SAndroid Build Coastguard Worker case VK_ABS_G0: return ":abs_g0:";
45*9880d681SAndroid Build Coastguard Worker case VK_ABS_G0_S: return ":abs_g0_s:";
46*9880d681SAndroid Build Coastguard Worker case VK_ABS_G0_NC: return ":abs_g0_nc:";
47*9880d681SAndroid Build Coastguard Worker case VK_DTPREL_G2: return ":dtprel_g2:";
48*9880d681SAndroid Build Coastguard Worker case VK_DTPREL_G1: return ":dtprel_g1:";
49*9880d681SAndroid Build Coastguard Worker case VK_DTPREL_G1_NC: return ":dtprel_g1_nc:";
50*9880d681SAndroid Build Coastguard Worker case VK_DTPREL_G0: return ":dtprel_g0:";
51*9880d681SAndroid Build Coastguard Worker case VK_DTPREL_G0_NC: return ":dtprel_g0_nc:";
52*9880d681SAndroid Build Coastguard Worker case VK_DTPREL_HI12: return ":dtprel_hi12:";
53*9880d681SAndroid Build Coastguard Worker case VK_DTPREL_LO12: return ":dtprel_lo12:";
54*9880d681SAndroid Build Coastguard Worker case VK_DTPREL_LO12_NC: return ":dtprel_lo12_nc:";
55*9880d681SAndroid Build Coastguard Worker case VK_TPREL_G2: return ":tprel_g2:";
56*9880d681SAndroid Build Coastguard Worker case VK_TPREL_G1: return ":tprel_g1:";
57*9880d681SAndroid Build Coastguard Worker case VK_TPREL_G1_NC: return ":tprel_g1_nc:";
58*9880d681SAndroid Build Coastguard Worker case VK_TPREL_G0: return ":tprel_g0:";
59*9880d681SAndroid Build Coastguard Worker case VK_TPREL_G0_NC: return ":tprel_g0_nc:";
60*9880d681SAndroid Build Coastguard Worker case VK_TPREL_HI12: return ":tprel_hi12:";
61*9880d681SAndroid Build Coastguard Worker case VK_TPREL_LO12: return ":tprel_lo12:";
62*9880d681SAndroid Build Coastguard Worker case VK_TPREL_LO12_NC: return ":tprel_lo12_nc:";
63*9880d681SAndroid Build Coastguard Worker case VK_TLSDESC_LO12: return ":tlsdesc_lo12:";
64*9880d681SAndroid Build Coastguard Worker case VK_ABS_PAGE: return "";
65*9880d681SAndroid Build Coastguard Worker case VK_GOT_PAGE: return ":got:";
66*9880d681SAndroid Build Coastguard Worker case VK_GOT_LO12: return ":got_lo12:";
67*9880d681SAndroid Build Coastguard Worker case VK_GOTTPREL_PAGE: return ":gottprel:";
68*9880d681SAndroid Build Coastguard Worker case VK_GOTTPREL_LO12_NC: return ":gottprel_lo12:";
69*9880d681SAndroid Build Coastguard Worker case VK_GOTTPREL_G1: return ":gottprel_g1:";
70*9880d681SAndroid Build Coastguard Worker case VK_GOTTPREL_G0_NC: return ":gottprel_g0_nc:";
71*9880d681SAndroid Build Coastguard Worker case VK_TLSDESC: return "";
72*9880d681SAndroid Build Coastguard Worker case VK_TLSDESC_PAGE: return ":tlsdesc:";
73*9880d681SAndroid Build Coastguard Worker default:
74*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Invalid ELF symbol kind");
75*9880d681SAndroid Build Coastguard Worker }
76*9880d681SAndroid Build Coastguard Worker }
77*9880d681SAndroid Build Coastguard Worker
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const78*9880d681SAndroid Build Coastguard Worker void AArch64MCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
79*9880d681SAndroid Build Coastguard Worker if (getKind() != VK_NONE)
80*9880d681SAndroid Build Coastguard Worker OS << getVariantKindName();
81*9880d681SAndroid Build Coastguard Worker Expr->print(OS, MAI);
82*9880d681SAndroid Build Coastguard Worker }
83*9880d681SAndroid Build Coastguard Worker
visitUsedExpr(MCStreamer & Streamer) const84*9880d681SAndroid Build Coastguard Worker void AArch64MCExpr::visitUsedExpr(MCStreamer &Streamer) const {
85*9880d681SAndroid Build Coastguard Worker Streamer.visitUsedExpr(*getSubExpr());
86*9880d681SAndroid Build Coastguard Worker }
87*9880d681SAndroid Build Coastguard Worker
findAssociatedFragment() const88*9880d681SAndroid Build Coastguard Worker MCFragment *AArch64MCExpr::findAssociatedFragment() const {
89*9880d681SAndroid Build Coastguard Worker llvm_unreachable("FIXME: what goes here?");
90*9880d681SAndroid Build Coastguard Worker }
91*9880d681SAndroid Build Coastguard Worker
evaluateAsRelocatableImpl(MCValue & Res,const MCAsmLayout * Layout,const MCFixup * Fixup) const92*9880d681SAndroid Build Coastguard Worker bool AArch64MCExpr::evaluateAsRelocatableImpl(MCValue &Res,
93*9880d681SAndroid Build Coastguard Worker const MCAsmLayout *Layout,
94*9880d681SAndroid Build Coastguard Worker const MCFixup *Fixup) const {
95*9880d681SAndroid Build Coastguard Worker if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
96*9880d681SAndroid Build Coastguard Worker return false;
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker Res =
99*9880d681SAndroid Build Coastguard Worker MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
100*9880d681SAndroid Build Coastguard Worker
101*9880d681SAndroid Build Coastguard Worker return true;
102*9880d681SAndroid Build Coastguard Worker }
103*9880d681SAndroid Build Coastguard Worker
fixELFSymbolsInTLSFixupsImpl(const MCExpr * Expr,MCAssembler & Asm)104*9880d681SAndroid Build Coastguard Worker static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
105*9880d681SAndroid Build Coastguard Worker switch (Expr->getKind()) {
106*9880d681SAndroid Build Coastguard Worker case MCExpr::Target:
107*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Can't handle nested target expression");
108*9880d681SAndroid Build Coastguard Worker break;
109*9880d681SAndroid Build Coastguard Worker case MCExpr::Constant:
110*9880d681SAndroid Build Coastguard Worker break;
111*9880d681SAndroid Build Coastguard Worker
112*9880d681SAndroid Build Coastguard Worker case MCExpr::Binary: {
113*9880d681SAndroid Build Coastguard Worker const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
114*9880d681SAndroid Build Coastguard Worker fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
115*9880d681SAndroid Build Coastguard Worker fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
116*9880d681SAndroid Build Coastguard Worker break;
117*9880d681SAndroid Build Coastguard Worker }
118*9880d681SAndroid Build Coastguard Worker
119*9880d681SAndroid Build Coastguard Worker case MCExpr::SymbolRef: {
120*9880d681SAndroid Build Coastguard Worker // We're known to be under a TLS fixup, so any symbol should be
121*9880d681SAndroid Build Coastguard Worker // modified. There should be only one.
122*9880d681SAndroid Build Coastguard Worker const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
123*9880d681SAndroid Build Coastguard Worker cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
124*9880d681SAndroid Build Coastguard Worker break;
125*9880d681SAndroid Build Coastguard Worker }
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker case MCExpr::Unary:
128*9880d681SAndroid Build Coastguard Worker fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
129*9880d681SAndroid Build Coastguard Worker break;
130*9880d681SAndroid Build Coastguard Worker }
131*9880d681SAndroid Build Coastguard Worker }
132*9880d681SAndroid Build Coastguard Worker
fixELFSymbolsInTLSFixups(MCAssembler & Asm) const133*9880d681SAndroid Build Coastguard Worker void AArch64MCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
134*9880d681SAndroid Build Coastguard Worker switch (getSymbolLoc(Kind)) {
135*9880d681SAndroid Build Coastguard Worker default:
136*9880d681SAndroid Build Coastguard Worker return;
137*9880d681SAndroid Build Coastguard Worker case VK_DTPREL:
138*9880d681SAndroid Build Coastguard Worker case VK_GOTTPREL:
139*9880d681SAndroid Build Coastguard Worker case VK_TPREL:
140*9880d681SAndroid Build Coastguard Worker case VK_TLSDESC:
141*9880d681SAndroid Build Coastguard Worker break;
142*9880d681SAndroid Build Coastguard Worker }
143*9880d681SAndroid Build Coastguard Worker
144*9880d681SAndroid Build Coastguard Worker fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
145*9880d681SAndroid Build Coastguard Worker }
146