1//===-- RISCVMCExpr.cpp - RISC-V specific MC expression classes -----------===//
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// This file contains the implementation of the assembly expression modifiers
10// accepted by the RISC-V architecture (e.g. ":lo12:", ":gottprel_g1:", ...).
11//
12//===----------------------------------------------------------------------===//
13
14#include "RISCVMCExpr.h"
15#include "MCTargetDesc/RISCVAsmBackend.h"
16#include "RISCVFixupKinds.h"
17#include "llvm/BinaryFormat/ELF.h"
18#include "llvm/MC/MCAsmLayout.h"
19#include "llvm/MC/MCAssembler.h"
20#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCStreamer.h"
22#include "llvm/MC/MCSymbolELF.h"
23#include "llvm/MC/MCValue.h"
24#include "llvm/Support/Casting.h"
25#include "llvm/Support/ErrorHandling.h"
26
27using namespace llvm;
28
29#define DEBUG_TYPE "riscvmcexpr"
30
31const RISCVMCExpr *RISCVMCExpr::create(const MCExpr *Expr, VariantKind Kind,
32                                       MCContext &Ctx) {
33  return new (Ctx) RISCVMCExpr(Expr, Kind);
34}
35
36void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
37  VariantKind Kind = getKind();
38  bool HasVariant = ((Kind != VK_RISCV_None) && (Kind != VK_RISCV_CALL) &&
39                     (Kind != VK_RISCV_CALL_PLT));
40
41  if (HasVariant)
42    OS << '%' << getVariantKindName(getKind()) << '(';
43  Expr->print(OS, MAI);
44  if (HasVariant)
45    OS << ')';
46}
47
48const MCFixup *RISCVMCExpr::getPCRelHiFixup(const MCFragment **DFOut) const {
49  MCValue AUIPCLoc;
50  if (!getSubExpr()->evaluateAsRelocatable(AUIPCLoc, nullptr, nullptr))
51    return nullptr;
52
53  const MCSymbolRefExpr *AUIPCSRE = AUIPCLoc.getSymA();
54  if (!AUIPCSRE)
55    return nullptr;
56
57  const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol();
58  const auto *DF = dyn_cast_or_null<MCDataFragment>(AUIPCSymbol->getFragment());
59
60  if (!DF)
61    return nullptr;
62
63  uint64_t Offset = AUIPCSymbol->getOffset();
64  if (DF->getContents().size() == Offset) {
65    DF = dyn_cast_or_null<MCDataFragment>(DF->getNextNode());
66    if (!DF)
67      return nullptr;
68    Offset = 0;
69  }
70
71  for (const MCFixup &F : DF->getFixups()) {
72    if (F.getOffset() != Offset)
73      continue;
74
75    switch ((unsigned)F.getKind()) {
76    default:
77      continue;
78    case RISCV::fixup_riscv_got_hi20:
79    case RISCV::fixup_riscv_tls_got_hi20:
80    case RISCV::fixup_riscv_tls_gd_hi20:
81    case RISCV::fixup_riscv_pcrel_hi20:
82    case RISCV::fixup_riscv_tlsdesc_hi20:
83      if (DFOut)
84        *DFOut = DF;
85      return &F;
86    }
87  }
88
89  return nullptr;
90}
91
92bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
93                                            const MCAsmLayout *Layout,
94                                            const MCFixup *Fixup) const {
95  // Explicitly drop the layout and assembler to prevent any symbolic folding in
96  // the expression handling.  This is required to preserve symbolic difference
97  // expressions to emit the paired relocations.
98  if (!getSubExpr()->evaluateAsRelocatable(Res, nullptr, nullptr))
99    return false;
100
101  Res =
102      MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
103  // Custom fixup types are not valid with symbol difference expressions.
104  return Res.getSymB() ? getKind() == VK_RISCV_None : true;
105}
106
107void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
108  Streamer.visitUsedExpr(*getSubExpr());
109}
110
111RISCVMCExpr::VariantKind RISCVMCExpr::getVariantKindForName(StringRef name) {
112  return StringSwitch<RISCVMCExpr::VariantKind>(name)
113      .Case("lo", VK_RISCV_LO)
114      .Case("hi", VK_RISCV_HI)
115      .Case("pcrel_lo", VK_RISCV_PCREL_LO)
116      .Case("pcrel_hi", VK_RISCV_PCREL_HI)
117      .Case("got_pcrel_hi", VK_RISCV_GOT_HI)
118      .Case("tprel_lo", VK_RISCV_TPREL_LO)
119      .Case("tprel_hi", VK_RISCV_TPREL_HI)
120      .Case("tprel_add", VK_RISCV_TPREL_ADD)
121      .Case("tls_ie_pcrel_hi", VK_RISCV_TLS_GOT_HI)
122      .Case("tls_gd_pcrel_hi", VK_RISCV_TLS_GD_HI)
123      .Case("tlsdesc_hi", VK_RISCV_TLSDESC_HI)
124      .Case("tlsdesc_load_lo", VK_RISCV_TLSDESC_LOAD_LO)
125      .Case("tlsdesc_add_lo", VK_RISCV_TLSDESC_ADD_LO)
126      .Case("tlsdesc_call", VK_RISCV_TLSDESC_CALL)
127      .Default(VK_RISCV_Invalid);
128}
129
130StringRef RISCVMCExpr::getVariantKindName(VariantKind Kind) {
131  switch (Kind) {
132  case VK_RISCV_Invalid:
133  case VK_RISCV_None:
134    llvm_unreachable("Invalid ELF symbol kind");
135  case VK_RISCV_LO:
136    return "lo";
137  case VK_RISCV_HI:
138    return "hi";
139  case VK_RISCV_PCREL_LO:
140    return "pcrel_lo";
141  case VK_RISCV_PCREL_HI:
142    return "pcrel_hi";
143  case VK_RISCV_GOT_HI:
144    return "got_pcrel_hi";
145  case VK_RISCV_TPREL_LO:
146    return "tprel_lo";
147  case VK_RISCV_TPREL_HI:
148    return "tprel_hi";
149  case VK_RISCV_TPREL_ADD:
150    return "tprel_add";
151  case VK_RISCV_TLS_GOT_HI:
152    return "tls_ie_pcrel_hi";
153  case VK_RISCV_TLSDESC_HI:
154    return "tlsdesc_hi";
155  case VK_RISCV_TLSDESC_LOAD_LO:
156    return "tlsdesc_load_lo";
157  case VK_RISCV_TLSDESC_ADD_LO:
158    return "tlsdesc_add_lo";
159  case VK_RISCV_TLSDESC_CALL:
160    return "tlsdesc_call";
161  case VK_RISCV_TLS_GD_HI:
162    return "tls_gd_pcrel_hi";
163  case VK_RISCV_CALL:
164    return "call";
165  case VK_RISCV_CALL_PLT:
166    return "call_plt";
167  case VK_RISCV_32_PCREL:
168    return "32_pcrel";
169  }
170  llvm_unreachable("Invalid ELF symbol kind");
171}
172
173static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
174  switch (Expr->getKind()) {
175  case MCExpr::Target:
176    llvm_unreachable("Can't handle nested target expression");
177    break;
178  case MCExpr::Constant:
179    break;
180
181  case MCExpr::Binary: {
182    const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
183    fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
184    fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
185    break;
186  }
187
188  case MCExpr::SymbolRef: {
189    // We're known to be under a TLS fixup, so any symbol should be
190    // modified. There should be only one.
191    const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
192    cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
193    break;
194  }
195
196  case MCExpr::Unary:
197    fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
198    break;
199  }
200}
201
202void RISCVMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
203  switch (getKind()) {
204  default:
205    return;
206  case VK_RISCV_TPREL_HI:
207  case VK_RISCV_TLS_GOT_HI:
208  case VK_RISCV_TLS_GD_HI:
209  case VK_RISCV_TLSDESC_HI:
210    break;
211  }
212
213  fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
214}
215
216bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
217  MCValue Value;
218
219  if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
220      Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TPREL_HI ||
221      Kind == VK_RISCV_TPREL_LO || Kind == VK_RISCV_TPREL_ADD ||
222      Kind == VK_RISCV_TLS_GOT_HI || Kind == VK_RISCV_TLS_GD_HI ||
223      Kind == VK_RISCV_TLSDESC_HI || Kind == VK_RISCV_TLSDESC_LOAD_LO ||
224      Kind == VK_RISCV_TLSDESC_ADD_LO || Kind == VK_RISCV_TLSDESC_CALL ||
225      Kind == VK_RISCV_CALL || Kind == VK_RISCV_CALL_PLT)
226    return false;
227
228  if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
229    return false;
230
231  if (!Value.isAbsolute())
232    return false;
233
234  Res = evaluateAsInt64(Value.getConstant());
235  return true;
236}
237
238int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const {
239  switch (Kind) {
240  default:
241    llvm_unreachable("Invalid kind");
242  case VK_RISCV_LO:
243    return SignExtend64<12>(Value);
244  case VK_RISCV_HI:
245    // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
246    return ((Value + 0x800) >> 12) & 0xfffff;
247  }
248}
249