xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===-- RISCVMCExpr.cpp - RISC-V specific MC expression classes -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains the implementation of the assembly expression modifiers
1006c3fb27SDimitry Andric // accepted by the RISC-V architecture (e.g. ":lo12:", ":gottprel_g1:", ...).
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "RISCVMCExpr.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/RISCVAsmBackend.h"
160b57cec5SDimitry Andric #include "RISCVFixupKinds.h"
170b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
2381ad6265SDimitry Andric #include "llvm/Support/Casting.h"
240b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric using namespace llvm;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric #define DEBUG_TYPE "riscvmcexpr"
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric const RISCVMCExpr *RISCVMCExpr::create(const MCExpr *Expr, VariantKind Kind,
310b57cec5SDimitry Andric                                        MCContext &Ctx) {
320b57cec5SDimitry Andric   return new (Ctx) RISCVMCExpr(Expr, Kind);
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
360b57cec5SDimitry Andric   VariantKind Kind = getKind();
370b57cec5SDimitry Andric   bool HasVariant = ((Kind != VK_RISCV_None) && (Kind != VK_RISCV_CALL) &&
380b57cec5SDimitry Andric                      (Kind != VK_RISCV_CALL_PLT));
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   if (HasVariant)
410b57cec5SDimitry Andric     OS << '%' << getVariantKindName(getKind()) << '(';
420b57cec5SDimitry Andric   Expr->print(OS, MAI);
430b57cec5SDimitry Andric   if (HasVariant)
440b57cec5SDimitry Andric     OS << ')';
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric 
4755e4f9d5SDimitry Andric const MCFixup *RISCVMCExpr::getPCRelHiFixup(const MCFragment **DFOut) const {
480b57cec5SDimitry Andric   MCValue AUIPCLoc;
490b57cec5SDimitry Andric   if (!getSubExpr()->evaluateAsRelocatable(AUIPCLoc, nullptr, nullptr))
500b57cec5SDimitry Andric     return nullptr;
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   const MCSymbolRefExpr *AUIPCSRE = AUIPCLoc.getSymA();
530b57cec5SDimitry Andric   if (!AUIPCSRE)
540b57cec5SDimitry Andric     return nullptr;
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol();
570b57cec5SDimitry Andric   const auto *DF = dyn_cast_or_null<MCDataFragment>(AUIPCSymbol->getFragment());
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   if (!DF)
600b57cec5SDimitry Andric     return nullptr;
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   uint64_t Offset = AUIPCSymbol->getOffset();
630b57cec5SDimitry Andric   if (DF->getContents().size() == Offset) {
64*0fca6ea1SDimitry Andric     DF = dyn_cast_or_null<MCDataFragment>(DF->getNext());
650b57cec5SDimitry Andric     if (!DF)
660b57cec5SDimitry Andric       return nullptr;
670b57cec5SDimitry Andric     Offset = 0;
680b57cec5SDimitry Andric   }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   for (const MCFixup &F : DF->getFixups()) {
710b57cec5SDimitry Andric     if (F.getOffset() != Offset)
720b57cec5SDimitry Andric       continue;
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric     switch ((unsigned)F.getKind()) {
750b57cec5SDimitry Andric     default:
760b57cec5SDimitry Andric       continue;
770b57cec5SDimitry Andric     case RISCV::fixup_riscv_got_hi20:
780b57cec5SDimitry Andric     case RISCV::fixup_riscv_tls_got_hi20:
790b57cec5SDimitry Andric     case RISCV::fixup_riscv_tls_gd_hi20:
800b57cec5SDimitry Andric     case RISCV::fixup_riscv_pcrel_hi20:
817a6dacacSDimitry Andric     case RISCV::fixup_riscv_tlsdesc_hi20:
8255e4f9d5SDimitry Andric       if (DFOut)
8355e4f9d5SDimitry Andric         *DFOut = DF;
840b57cec5SDimitry Andric       return &F;
850b57cec5SDimitry Andric     }
860b57cec5SDimitry Andric   }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   return nullptr;
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
92*0fca6ea1SDimitry Andric                                             const MCAssembler *Asm,
930b57cec5SDimitry Andric                                             const MCFixup *Fixup) const {
94fe6060f1SDimitry Andric   // Explicitly drop the layout and assembler to prevent any symbolic folding in
95fe6060f1SDimitry Andric   // the expression handling.  This is required to preserve symbolic difference
96fe6060f1SDimitry Andric   // expressions to emit the paired relocations.
97fe6060f1SDimitry Andric   if (!getSubExpr()->evaluateAsRelocatable(Res, nullptr, nullptr))
980b57cec5SDimitry Andric     return false;
990b57cec5SDimitry Andric 
100fe6060f1SDimitry Andric   Res =
101fe6060f1SDimitry Andric       MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
102fe6060f1SDimitry Andric   // Custom fixup types are not valid with symbol difference expressions.
103fe6060f1SDimitry Andric   return Res.getSymB() ? getKind() == VK_RISCV_None : true;
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
1070b57cec5SDimitry Andric   Streamer.visitUsedExpr(*getSubExpr());
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric RISCVMCExpr::VariantKind RISCVMCExpr::getVariantKindForName(StringRef name) {
1110b57cec5SDimitry Andric   return StringSwitch<RISCVMCExpr::VariantKind>(name)
1120b57cec5SDimitry Andric       .Case("lo", VK_RISCV_LO)
1130b57cec5SDimitry Andric       .Case("hi", VK_RISCV_HI)
1140b57cec5SDimitry Andric       .Case("pcrel_lo", VK_RISCV_PCREL_LO)
1150b57cec5SDimitry Andric       .Case("pcrel_hi", VK_RISCV_PCREL_HI)
1160b57cec5SDimitry Andric       .Case("got_pcrel_hi", VK_RISCV_GOT_HI)
1170b57cec5SDimitry Andric       .Case("tprel_lo", VK_RISCV_TPREL_LO)
1180b57cec5SDimitry Andric       .Case("tprel_hi", VK_RISCV_TPREL_HI)
1190b57cec5SDimitry Andric       .Case("tprel_add", VK_RISCV_TPREL_ADD)
1200b57cec5SDimitry Andric       .Case("tls_ie_pcrel_hi", VK_RISCV_TLS_GOT_HI)
1210b57cec5SDimitry Andric       .Case("tls_gd_pcrel_hi", VK_RISCV_TLS_GD_HI)
1227a6dacacSDimitry Andric       .Case("tlsdesc_hi", VK_RISCV_TLSDESC_HI)
1237a6dacacSDimitry Andric       .Case("tlsdesc_load_lo", VK_RISCV_TLSDESC_LOAD_LO)
1247a6dacacSDimitry Andric       .Case("tlsdesc_add_lo", VK_RISCV_TLSDESC_ADD_LO)
1257a6dacacSDimitry Andric       .Case("tlsdesc_call", VK_RISCV_TLSDESC_CALL)
1260b57cec5SDimitry Andric       .Default(VK_RISCV_Invalid);
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric StringRef RISCVMCExpr::getVariantKindName(VariantKind Kind) {
1300b57cec5SDimitry Andric   switch (Kind) {
131fe6060f1SDimitry Andric   case VK_RISCV_Invalid:
132fe6060f1SDimitry Andric   case VK_RISCV_None:
1330b57cec5SDimitry Andric     llvm_unreachable("Invalid ELF symbol kind");
1340b57cec5SDimitry Andric   case VK_RISCV_LO:
1350b57cec5SDimitry Andric     return "lo";
1360b57cec5SDimitry Andric   case VK_RISCV_HI:
1370b57cec5SDimitry Andric     return "hi";
1380b57cec5SDimitry Andric   case VK_RISCV_PCREL_LO:
1390b57cec5SDimitry Andric     return "pcrel_lo";
1400b57cec5SDimitry Andric   case VK_RISCV_PCREL_HI:
1410b57cec5SDimitry Andric     return "pcrel_hi";
1420b57cec5SDimitry Andric   case VK_RISCV_GOT_HI:
1430b57cec5SDimitry Andric     return "got_pcrel_hi";
1440b57cec5SDimitry Andric   case VK_RISCV_TPREL_LO:
1450b57cec5SDimitry Andric     return "tprel_lo";
1460b57cec5SDimitry Andric   case VK_RISCV_TPREL_HI:
1470b57cec5SDimitry Andric     return "tprel_hi";
1480b57cec5SDimitry Andric   case VK_RISCV_TPREL_ADD:
1490b57cec5SDimitry Andric     return "tprel_add";
1500b57cec5SDimitry Andric   case VK_RISCV_TLS_GOT_HI:
1510b57cec5SDimitry Andric     return "tls_ie_pcrel_hi";
1527a6dacacSDimitry Andric   case VK_RISCV_TLSDESC_HI:
1537a6dacacSDimitry Andric     return "tlsdesc_hi";
1547a6dacacSDimitry Andric   case VK_RISCV_TLSDESC_LOAD_LO:
1557a6dacacSDimitry Andric     return "tlsdesc_load_lo";
1567a6dacacSDimitry Andric   case VK_RISCV_TLSDESC_ADD_LO:
1577a6dacacSDimitry Andric     return "tlsdesc_add_lo";
1587a6dacacSDimitry Andric   case VK_RISCV_TLSDESC_CALL:
1597a6dacacSDimitry Andric     return "tlsdesc_call";
1600b57cec5SDimitry Andric   case VK_RISCV_TLS_GD_HI:
1610b57cec5SDimitry Andric     return "tls_gd_pcrel_hi";
162fe6060f1SDimitry Andric   case VK_RISCV_CALL:
163fe6060f1SDimitry Andric     return "call";
164fe6060f1SDimitry Andric   case VK_RISCV_CALL_PLT:
165fe6060f1SDimitry Andric     return "call_plt";
166fe6060f1SDimitry Andric   case VK_RISCV_32_PCREL:
167fe6060f1SDimitry Andric     return "32_pcrel";
1680b57cec5SDimitry Andric   }
169fe6060f1SDimitry Andric   llvm_unreachable("Invalid ELF symbol kind");
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
1730b57cec5SDimitry Andric   switch (Expr->getKind()) {
1740b57cec5SDimitry Andric   case MCExpr::Target:
1750b57cec5SDimitry Andric     llvm_unreachable("Can't handle nested target expression");
1760b57cec5SDimitry Andric     break;
1770b57cec5SDimitry Andric   case MCExpr::Constant:
1780b57cec5SDimitry Andric     break;
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   case MCExpr::Binary: {
1810b57cec5SDimitry Andric     const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
1820b57cec5SDimitry Andric     fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
1830b57cec5SDimitry Andric     fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
1840b57cec5SDimitry Andric     break;
1850b57cec5SDimitry Andric   }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   case MCExpr::SymbolRef: {
1880b57cec5SDimitry Andric     // We're known to be under a TLS fixup, so any symbol should be
1890b57cec5SDimitry Andric     // modified. There should be only one.
1900b57cec5SDimitry Andric     const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
1910b57cec5SDimitry Andric     cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
1920b57cec5SDimitry Andric     break;
1930b57cec5SDimitry Andric   }
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   case MCExpr::Unary:
1960b57cec5SDimitry Andric     fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
1970b57cec5SDimitry Andric     break;
1980b57cec5SDimitry Andric   }
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric void RISCVMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
2020b57cec5SDimitry Andric   switch (getKind()) {
2030b57cec5SDimitry Andric   default:
2040b57cec5SDimitry Andric     return;
2050b57cec5SDimitry Andric   case VK_RISCV_TPREL_HI:
2060b57cec5SDimitry Andric   case VK_RISCV_TLS_GOT_HI:
2070b57cec5SDimitry Andric   case VK_RISCV_TLS_GD_HI:
2087a6dacacSDimitry Andric   case VK_RISCV_TLSDESC_HI:
2090b57cec5SDimitry Andric     break;
2100b57cec5SDimitry Andric   }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
2160b57cec5SDimitry Andric   MCValue Value;
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
2190b57cec5SDimitry Andric       Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TPREL_HI ||
2200b57cec5SDimitry Andric       Kind == VK_RISCV_TPREL_LO || Kind == VK_RISCV_TPREL_ADD ||
2210b57cec5SDimitry Andric       Kind == VK_RISCV_TLS_GOT_HI || Kind == VK_RISCV_TLS_GD_HI ||
2227a6dacacSDimitry Andric       Kind == VK_RISCV_TLSDESC_HI || Kind == VK_RISCV_TLSDESC_LOAD_LO ||
2237a6dacacSDimitry Andric       Kind == VK_RISCV_TLSDESC_ADD_LO || Kind == VK_RISCV_TLSDESC_CALL ||
2240b57cec5SDimitry Andric       Kind == VK_RISCV_CALL || Kind == VK_RISCV_CALL_PLT)
2250b57cec5SDimitry Andric     return false;
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
2280b57cec5SDimitry Andric     return false;
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   if (!Value.isAbsolute())
2310b57cec5SDimitry Andric     return false;
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric   Res = evaluateAsInt64(Value.getConstant());
2340b57cec5SDimitry Andric   return true;
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const {
2380b57cec5SDimitry Andric   switch (Kind) {
2390b57cec5SDimitry Andric   default:
2400b57cec5SDimitry Andric     llvm_unreachable("Invalid kind");
2410b57cec5SDimitry Andric   case VK_RISCV_LO:
2420b57cec5SDimitry Andric     return SignExtend64<12>(Value);
2430b57cec5SDimitry Andric   case VK_RISCV_HI:
2440b57cec5SDimitry Andric     // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
2450b57cec5SDimitry Andric     return ((Value + 0x800) >> 12) & 0xfffff;
2460b57cec5SDimitry Andric   }
2470b57cec5SDimitry Andric }
248