AArch64MCExpr.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===-- AArch64MCExpr.cpp - AArch64 specific MC expression classes --------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the implementation of the assembly expression modifiers
11// accepted by the AArch64 architecture (e.g. ":lo12:", ":gottprel_g1:", ...).
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "aarch64mcexpr"
16#include "AArch64MCExpr.h"
17#include "llvm/MC/MCAssembler.h"
18#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCELF.h"
20#include "llvm/Object/ELF.h"
21
22using namespace llvm;
23
24const AArch64MCExpr*
25AArch64MCExpr::Create(VariantKind Kind, const MCExpr *Expr,
26                      MCContext &Ctx) {
27  return new (Ctx) AArch64MCExpr(Kind, Expr);
28}
29
30void AArch64MCExpr::PrintImpl(raw_ostream &OS) const {
31  switch (Kind) {
32  default: llvm_unreachable("Invalid kind!");
33  case VK_AARCH64_GOT:              OS << ":got:"; break;
34  case VK_AARCH64_GOT_LO12:         OS << ":got_lo12:"; break;
35  case VK_AARCH64_LO12:             OS << ":lo12:"; break;
36  case VK_AARCH64_ABS_G0:           OS << ":abs_g0:"; break;
37  case VK_AARCH64_ABS_G0_NC:        OS << ":abs_g0_nc:"; break;
38  case VK_AARCH64_ABS_G1:           OS << ":abs_g1:"; break;
39  case VK_AARCH64_ABS_G1_NC:        OS << ":abs_g1_nc:"; break;
40  case VK_AARCH64_ABS_G2:           OS << ":abs_g2:"; break;
41  case VK_AARCH64_ABS_G2_NC:        OS << ":abs_g2_nc:"; break;
42  case VK_AARCH64_ABS_G3:           OS << ":abs_g3:"; break;
43  case VK_AARCH64_SABS_G0:          OS << ":abs_g0_s:"; break;
44  case VK_AARCH64_SABS_G1:          OS << ":abs_g1_s:"; break;
45  case VK_AARCH64_SABS_G2:          OS << ":abs_g2_s:"; break;
46  case VK_AARCH64_DTPREL_G2:        OS << ":dtprel_g2:"; break;
47  case VK_AARCH64_DTPREL_G1:        OS << ":dtprel_g1:"; break;
48  case VK_AARCH64_DTPREL_G1_NC:     OS << ":dtprel_g1_nc:"; break;
49  case VK_AARCH64_DTPREL_G0:        OS << ":dtprel_g0:"; break;
50  case VK_AARCH64_DTPREL_G0_NC:     OS << ":dtprel_g0_nc:"; break;
51  case VK_AARCH64_DTPREL_HI12:      OS << ":dtprel_hi12:"; break;
52  case VK_AARCH64_DTPREL_LO12:      OS << ":dtprel_lo12:"; break;
53  case VK_AARCH64_DTPREL_LO12_NC:   OS << ":dtprel_lo12_nc:"; break;
54  case VK_AARCH64_GOTTPREL_G1:      OS << ":gottprel_g1:"; break;
55  case VK_AARCH64_GOTTPREL_G0_NC:   OS << ":gottprel_g0_nc:"; break;
56  case VK_AARCH64_GOTTPREL:         OS << ":gottprel:"; break;
57  case VK_AARCH64_GOTTPREL_LO12:    OS << ":gottprel_lo12:"; break;
58  case VK_AARCH64_TPREL_G2:         OS << ":tprel_g2:"; break;
59  case VK_AARCH64_TPREL_G1:         OS << ":tprel_g1:"; break;
60  case VK_AARCH64_TPREL_G1_NC:      OS << ":tprel_g1_nc:"; break;
61  case VK_AARCH64_TPREL_G0:         OS << ":tprel_g0:"; break;
62  case VK_AARCH64_TPREL_G0_NC:      OS << ":tprel_g0_nc:"; break;
63  case VK_AARCH64_TPREL_HI12:       OS << ":tprel_hi12:"; break;
64  case VK_AARCH64_TPREL_LO12:       OS << ":tprel_lo12:"; break;
65  case VK_AARCH64_TPREL_LO12_NC:    OS << ":tprel_lo12_nc:"; break;
66  case VK_AARCH64_TLSDESC:          OS << ":tlsdesc:"; break;
67  case VK_AARCH64_TLSDESC_LO12:     OS << ":tlsdesc_lo12:"; break;
68
69  }
70
71  const MCExpr *Expr = getSubExpr();
72  if (Expr->getKind() != MCExpr::SymbolRef)
73    OS << '(';
74  Expr->print(OS);
75  if (Expr->getKind() != MCExpr::SymbolRef)
76    OS << ')';
77}
78
79bool
80AArch64MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
81                                         const MCAsmLayout *Layout) const {
82  return getSubExpr()->EvaluateAsRelocatable(Res, Layout);
83}
84
85static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
86  switch (Expr->getKind()) {
87  case MCExpr::Target:
88    llvm_unreachable("Can't handle nested target expression");
89    break;
90  case MCExpr::Constant:
91    break;
92
93  case MCExpr::Binary: {
94    const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
95    fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
96    fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
97    break;
98  }
99
100  case MCExpr::SymbolRef: {
101    // We're known to be under a TLS fixup, so any symbol should be
102    // modified. There should be only one.
103    const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
104    MCSymbolData &SD = Asm.getOrCreateSymbolData(SymRef.getSymbol());
105    MCELF::SetType(SD, ELF::STT_TLS);
106    break;
107  }
108
109  case MCExpr::Unary:
110    fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
111    break;
112  }
113}
114
115void AArch64MCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
116  switch (getKind()) {
117  default:
118    return;
119  case VK_AARCH64_DTPREL_G2:
120  case VK_AARCH64_DTPREL_G1:
121  case VK_AARCH64_DTPREL_G1_NC:
122  case VK_AARCH64_DTPREL_G0:
123  case VK_AARCH64_DTPREL_G0_NC:
124  case VK_AARCH64_DTPREL_HI12:
125  case VK_AARCH64_DTPREL_LO12:
126  case VK_AARCH64_DTPREL_LO12_NC:
127  case VK_AARCH64_GOTTPREL_G1:
128  case VK_AARCH64_GOTTPREL_G0_NC:
129  case VK_AARCH64_GOTTPREL:
130  case VK_AARCH64_GOTTPREL_LO12:
131  case VK_AARCH64_TPREL_G2:
132  case VK_AARCH64_TPREL_G1:
133  case VK_AARCH64_TPREL_G1_NC:
134  case VK_AARCH64_TPREL_G0:
135  case VK_AARCH64_TPREL_G0_NC:
136  case VK_AARCH64_TPREL_HI12:
137  case VK_AARCH64_TPREL_LO12:
138  case VK_AARCH64_TPREL_LO12_NC:
139  case VK_AARCH64_TLSDESC:
140  case VK_AARCH64_TLSDESC_LO12:
141    break;
142  }
143
144  fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
145}
146
147// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps
148// that method should be made public?
149// FIXME: really do above: now that two backends are using it.
150static void AddValueSymbolsImpl(const MCExpr *Value, MCAssembler *Asm) {
151  switch (Value->getKind()) {
152  case MCExpr::Target:
153    llvm_unreachable("Can't handle nested target expr!");
154    break;
155
156  case MCExpr::Constant:
157    break;
158
159  case MCExpr::Binary: {
160    const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
161    AddValueSymbolsImpl(BE->getLHS(), Asm);
162    AddValueSymbolsImpl(BE->getRHS(), Asm);
163    break;
164  }
165
166  case MCExpr::SymbolRef:
167    Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
168    break;
169
170  case MCExpr::Unary:
171    AddValueSymbolsImpl(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm);
172    break;
173  }
174}
175
176void AArch64MCExpr::AddValueSymbols(MCAssembler *Asm) const {
177  AddValueSymbolsImpl(getSubExpr(), Asm);
178}
179