Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
35294 views
//===-- RISCVMCExpr.cpp - RISC-V specific MC expression classes -----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains the implementation of the assembly expression modifiers9// accepted by the RISC-V architecture (e.g. ":lo12:", ":gottprel_g1:", ...).10//11//===----------------------------------------------------------------------===//1213#include "RISCVMCExpr.h"14#include "MCTargetDesc/RISCVAsmBackend.h"15#include "RISCVFixupKinds.h"16#include "llvm/BinaryFormat/ELF.h"17#include "llvm/MC/MCAssembler.h"18#include "llvm/MC/MCContext.h"19#include "llvm/MC/MCStreamer.h"20#include "llvm/MC/MCSymbolELF.h"21#include "llvm/MC/MCValue.h"22#include "llvm/Support/Casting.h"23#include "llvm/Support/ErrorHandling.h"2425using namespace llvm;2627#define DEBUG_TYPE "riscvmcexpr"2829const RISCVMCExpr *RISCVMCExpr::create(const MCExpr *Expr, VariantKind Kind,30MCContext &Ctx) {31return new (Ctx) RISCVMCExpr(Expr, Kind);32}3334void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {35VariantKind Kind = getKind();36bool HasVariant = ((Kind != VK_RISCV_None) && (Kind != VK_RISCV_CALL) &&37(Kind != VK_RISCV_CALL_PLT));3839if (HasVariant)40OS << '%' << getVariantKindName(getKind()) << '(';41Expr->print(OS, MAI);42if (HasVariant)43OS << ')';44}4546const MCFixup *RISCVMCExpr::getPCRelHiFixup(const MCFragment **DFOut) const {47MCValue AUIPCLoc;48if (!getSubExpr()->evaluateAsRelocatable(AUIPCLoc, nullptr, nullptr))49return nullptr;5051const MCSymbolRefExpr *AUIPCSRE = AUIPCLoc.getSymA();52if (!AUIPCSRE)53return nullptr;5455const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol();56const auto *DF = dyn_cast_or_null<MCDataFragment>(AUIPCSymbol->getFragment());5758if (!DF)59return nullptr;6061uint64_t Offset = AUIPCSymbol->getOffset();62if (DF->getContents().size() == Offset) {63DF = dyn_cast_or_null<MCDataFragment>(DF->getNext());64if (!DF)65return nullptr;66Offset = 0;67}6869for (const MCFixup &F : DF->getFixups()) {70if (F.getOffset() != Offset)71continue;7273switch ((unsigned)F.getKind()) {74default:75continue;76case RISCV::fixup_riscv_got_hi20:77case RISCV::fixup_riscv_tls_got_hi20:78case RISCV::fixup_riscv_tls_gd_hi20:79case RISCV::fixup_riscv_pcrel_hi20:80case RISCV::fixup_riscv_tlsdesc_hi20:81if (DFOut)82*DFOut = DF;83return &F;84}85}8687return nullptr;88}8990bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res,91const MCAssembler *Asm,92const MCFixup *Fixup) const {93// Explicitly drop the layout and assembler to prevent any symbolic folding in94// the expression handling. This is required to preserve symbolic difference95// expressions to emit the paired relocations.96if (!getSubExpr()->evaluateAsRelocatable(Res, nullptr, nullptr))97return false;9899Res =100MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());101// Custom fixup types are not valid with symbol difference expressions.102return Res.getSymB() ? getKind() == VK_RISCV_None : true;103}104105void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const {106Streamer.visitUsedExpr(*getSubExpr());107}108109RISCVMCExpr::VariantKind RISCVMCExpr::getVariantKindForName(StringRef name) {110return StringSwitch<RISCVMCExpr::VariantKind>(name)111.Case("lo", VK_RISCV_LO)112.Case("hi", VK_RISCV_HI)113.Case("pcrel_lo", VK_RISCV_PCREL_LO)114.Case("pcrel_hi", VK_RISCV_PCREL_HI)115.Case("got_pcrel_hi", VK_RISCV_GOT_HI)116.Case("tprel_lo", VK_RISCV_TPREL_LO)117.Case("tprel_hi", VK_RISCV_TPREL_HI)118.Case("tprel_add", VK_RISCV_TPREL_ADD)119.Case("tls_ie_pcrel_hi", VK_RISCV_TLS_GOT_HI)120.Case("tls_gd_pcrel_hi", VK_RISCV_TLS_GD_HI)121.Case("tlsdesc_hi", VK_RISCV_TLSDESC_HI)122.Case("tlsdesc_load_lo", VK_RISCV_TLSDESC_LOAD_LO)123.Case("tlsdesc_add_lo", VK_RISCV_TLSDESC_ADD_LO)124.Case("tlsdesc_call", VK_RISCV_TLSDESC_CALL)125.Default(VK_RISCV_Invalid);126}127128StringRef RISCVMCExpr::getVariantKindName(VariantKind Kind) {129switch (Kind) {130case VK_RISCV_Invalid:131case VK_RISCV_None:132llvm_unreachable("Invalid ELF symbol kind");133case VK_RISCV_LO:134return "lo";135case VK_RISCV_HI:136return "hi";137case VK_RISCV_PCREL_LO:138return "pcrel_lo";139case VK_RISCV_PCREL_HI:140return "pcrel_hi";141case VK_RISCV_GOT_HI:142return "got_pcrel_hi";143case VK_RISCV_TPREL_LO:144return "tprel_lo";145case VK_RISCV_TPREL_HI:146return "tprel_hi";147case VK_RISCV_TPREL_ADD:148return "tprel_add";149case VK_RISCV_TLS_GOT_HI:150return "tls_ie_pcrel_hi";151case VK_RISCV_TLSDESC_HI:152return "tlsdesc_hi";153case VK_RISCV_TLSDESC_LOAD_LO:154return "tlsdesc_load_lo";155case VK_RISCV_TLSDESC_ADD_LO:156return "tlsdesc_add_lo";157case VK_RISCV_TLSDESC_CALL:158return "tlsdesc_call";159case VK_RISCV_TLS_GD_HI:160return "tls_gd_pcrel_hi";161case VK_RISCV_CALL:162return "call";163case VK_RISCV_CALL_PLT:164return "call_plt";165case VK_RISCV_32_PCREL:166return "32_pcrel";167}168llvm_unreachable("Invalid ELF symbol kind");169}170171static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {172switch (Expr->getKind()) {173case MCExpr::Target:174llvm_unreachable("Can't handle nested target expression");175break;176case MCExpr::Constant:177break;178179case MCExpr::Binary: {180const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);181fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);182fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);183break;184}185186case MCExpr::SymbolRef: {187// We're known to be under a TLS fixup, so any symbol should be188// modified. There should be only one.189const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);190cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);191break;192}193194case MCExpr::Unary:195fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);196break;197}198}199200void RISCVMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {201switch (getKind()) {202default:203return;204case VK_RISCV_TPREL_HI:205case VK_RISCV_TLS_GOT_HI:206case VK_RISCV_TLS_GD_HI:207case VK_RISCV_TLSDESC_HI:208break;209}210211fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);212}213214bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {215MCValue Value;216217if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||218Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TPREL_HI ||219Kind == VK_RISCV_TPREL_LO || Kind == VK_RISCV_TPREL_ADD ||220Kind == VK_RISCV_TLS_GOT_HI || Kind == VK_RISCV_TLS_GD_HI ||221Kind == VK_RISCV_TLSDESC_HI || Kind == VK_RISCV_TLSDESC_LOAD_LO ||222Kind == VK_RISCV_TLSDESC_ADD_LO || Kind == VK_RISCV_TLSDESC_CALL ||223Kind == VK_RISCV_CALL || Kind == VK_RISCV_CALL_PLT)224return false;225226if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))227return false;228229if (!Value.isAbsolute())230return false;231232Res = evaluateAsInt64(Value.getConstant());233return true;234}235236int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const {237switch (Kind) {238default:239llvm_unreachable("Invalid kind");240case VK_RISCV_LO:241return SignExtend64<12>(Value);242case VK_RISCV_HI:243// Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.244return ((Value + 0x800) >> 12) & 0xfffff;245}246}247248249