Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
35294 views
//===-- LoongArchMCExpr.cpp - LoongArch 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 LoongArch architecture.10//11//===----------------------------------------------------------------------===//1213#include "LoongArchMCExpr.h"14#include "LoongArchAsmBackend.h"15#include "LoongArchFixupKinds.h"16#include "llvm/MC/MCContext.h"17#include "llvm/MC/MCStreamer.h"18#include "llvm/MC/MCSymbolELF.h"19#include "llvm/MC/MCValue.h"20#include "llvm/Support/Casting.h"21#include "llvm/Support/ErrorHandling.h"2223using namespace llvm;2425#define DEBUG_TYPE "loongarch-mcexpr"2627const LoongArchMCExpr *LoongArchMCExpr::create(const MCExpr *Expr,28VariantKind Kind, MCContext &Ctx,29bool Hint) {30return new (Ctx) LoongArchMCExpr(Expr, Kind, Hint);31}3233void LoongArchMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {34VariantKind Kind = getKind();35bool HasVariant =36((Kind != VK_LoongArch_None) && (Kind != VK_LoongArch_CALL));3738if (HasVariant)39OS << '%' << getVariantKindName(getKind()) << '(';40Expr->print(OS, MAI);41if (HasVariant)42OS << ')';43}4445bool LoongArchMCExpr::evaluateAsRelocatableImpl(MCValue &Res,46const MCAssembler *Asm,47const MCFixup *Fixup) const {48// Explicitly drop the layout and assembler to prevent any symbolic folding in49// the expression handling. This is required to preserve symbolic difference50// expressions to emit the paired relocations.51if (!getSubExpr()->evaluateAsRelocatable(Res, nullptr, nullptr))52return false;5354Res =55MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());56// Custom fixup types are not valid with symbol difference expressions.57return Res.getSymB() ? getKind() == VK_LoongArch_None : true;58}5960void LoongArchMCExpr::visitUsedExpr(MCStreamer &Streamer) const {61Streamer.visitUsedExpr(*getSubExpr());62}6364StringRef LoongArchMCExpr::getVariantKindName(VariantKind Kind) {65switch (Kind) {66default:67llvm_unreachable("Invalid ELF symbol kind");68case VK_LoongArch_CALL_PLT:69return "plt";70case VK_LoongArch_B16:71return "b16";72case VK_LoongArch_B21:73return "b21";74case VK_LoongArch_B26:75return "b26";76case VK_LoongArch_ABS_HI20:77return "abs_hi20";78case VK_LoongArch_ABS_LO12:79return "abs_lo12";80case VK_LoongArch_ABS64_LO20:81return "abs64_lo20";82case VK_LoongArch_ABS64_HI12:83return "abs64_hi12";84case VK_LoongArch_PCALA_HI20:85return "pc_hi20";86case VK_LoongArch_PCALA_LO12:87return "pc_lo12";88case VK_LoongArch_PCALA64_LO20:89return "pc64_lo20";90case VK_LoongArch_PCALA64_HI12:91return "pc64_hi12";92case VK_LoongArch_GOT_PC_HI20:93return "got_pc_hi20";94case VK_LoongArch_GOT_PC_LO12:95return "got_pc_lo12";96case VK_LoongArch_GOT64_PC_LO20:97return "got64_pc_lo20";98case VK_LoongArch_GOT64_PC_HI12:99return "got64_pc_hi12";100case VK_LoongArch_GOT_HI20:101return "got_hi20";102case VK_LoongArch_GOT_LO12:103return "got_lo12";104case VK_LoongArch_GOT64_LO20:105return "got64_lo20";106case VK_LoongArch_GOT64_HI12:107return "got64_hi12";108case VK_LoongArch_TLS_LE_HI20:109return "le_hi20";110case VK_LoongArch_TLS_LE_LO12:111return "le_lo12";112case VK_LoongArch_TLS_LE64_LO20:113return "le64_lo20";114case VK_LoongArch_TLS_LE64_HI12:115return "le64_hi12";116case VK_LoongArch_TLS_IE_PC_HI20:117return "ie_pc_hi20";118case VK_LoongArch_TLS_IE_PC_LO12:119return "ie_pc_lo12";120case VK_LoongArch_TLS_IE64_PC_LO20:121return "ie64_pc_lo20";122case VK_LoongArch_TLS_IE64_PC_HI12:123return "ie64_pc_hi12";124case VK_LoongArch_TLS_IE_HI20:125return "ie_hi20";126case VK_LoongArch_TLS_IE_LO12:127return "ie_lo12";128case VK_LoongArch_TLS_IE64_LO20:129return "ie64_lo20";130case VK_LoongArch_TLS_IE64_HI12:131return "ie64_hi12";132case VK_LoongArch_TLS_LD_PC_HI20:133return "ld_pc_hi20";134case VK_LoongArch_TLS_LD_HI20:135return "ld_hi20";136case VK_LoongArch_TLS_GD_PC_HI20:137return "gd_pc_hi20";138case VK_LoongArch_TLS_GD_HI20:139return "gd_hi20";140case VK_LoongArch_CALL36:141return "call36";142case VK_LoongArch_TLS_DESC_PC_HI20:143return "desc_pc_hi20";144case VK_LoongArch_TLS_DESC_PC_LO12:145return "desc_pc_lo12";146case VK_LoongArch_TLS_DESC64_PC_LO20:147return "desc64_pc_lo20";148case VK_LoongArch_TLS_DESC64_PC_HI12:149return "desc64_pc_hi12";150case VK_LoongArch_TLS_DESC_HI20:151return "desc_hi20";152case VK_LoongArch_TLS_DESC_LO12:153return "desc_lo12";154case VK_LoongArch_TLS_DESC64_LO20:155return "desc64_lo20";156case VK_LoongArch_TLS_DESC64_HI12:157return "desc64_hi12";158case VK_LoongArch_TLS_DESC_LD:159return "desc_ld";160case VK_LoongArch_TLS_DESC_CALL:161return "desc_call";162case VK_LoongArch_TLS_LE_HI20_R:163return "le_hi20_r";164case VK_LoongArch_TLS_LE_ADD_R:165return "le_add_r";166case VK_LoongArch_TLS_LE_LO12_R:167return "le_lo12_r";168case VK_LoongArch_PCREL20_S2:169return "pcrel_20";170case VK_LoongArch_TLS_LD_PCREL20_S2:171return "ld_pcrel_20";172case VK_LoongArch_TLS_GD_PCREL20_S2:173return "gd_pcrel_20";174case VK_LoongArch_TLS_DESC_PCREL20_S2:175return "desc_pcrel_20";176}177}178179LoongArchMCExpr::VariantKind180LoongArchMCExpr::getVariantKindForName(StringRef name) {181return StringSwitch<LoongArchMCExpr::VariantKind>(name)182.Case("plt", VK_LoongArch_CALL_PLT)183.Case("b16", VK_LoongArch_B16)184.Case("b21", VK_LoongArch_B21)185.Case("b26", VK_LoongArch_B26)186.Case("abs_hi20", VK_LoongArch_ABS_HI20)187.Case("abs_lo12", VK_LoongArch_ABS_LO12)188.Case("abs64_lo20", VK_LoongArch_ABS64_LO20)189.Case("abs64_hi12", VK_LoongArch_ABS64_HI12)190.Case("pc_hi20", VK_LoongArch_PCALA_HI20)191.Case("pc_lo12", VK_LoongArch_PCALA_LO12)192.Case("pc64_lo20", VK_LoongArch_PCALA64_LO20)193.Case("pc64_hi12", VK_LoongArch_PCALA64_HI12)194.Case("got_pc_hi20", VK_LoongArch_GOT_PC_HI20)195.Case("got_pc_lo12", VK_LoongArch_GOT_PC_LO12)196.Case("got64_pc_lo20", VK_LoongArch_GOT64_PC_LO20)197.Case("got64_pc_hi12", VK_LoongArch_GOT64_PC_HI12)198.Case("got_hi20", VK_LoongArch_GOT_HI20)199.Case("got_lo12", VK_LoongArch_GOT_LO12)200.Case("got64_lo20", VK_LoongArch_GOT64_LO20)201.Case("got64_hi12", VK_LoongArch_GOT64_HI12)202.Case("le_hi20", VK_LoongArch_TLS_LE_HI20)203.Case("le_lo12", VK_LoongArch_TLS_LE_LO12)204.Case("le64_lo20", VK_LoongArch_TLS_LE64_LO20)205.Case("le64_hi12", VK_LoongArch_TLS_LE64_HI12)206.Case("ie_pc_hi20", VK_LoongArch_TLS_IE_PC_HI20)207.Case("ie_pc_lo12", VK_LoongArch_TLS_IE_PC_LO12)208.Case("ie64_pc_lo20", VK_LoongArch_TLS_IE64_PC_LO20)209.Case("ie64_pc_hi12", VK_LoongArch_TLS_IE64_PC_HI12)210.Case("ie_hi20", VK_LoongArch_TLS_IE_HI20)211.Case("ie_lo12", VK_LoongArch_TLS_IE_LO12)212.Case("ie64_lo20", VK_LoongArch_TLS_IE64_LO20)213.Case("ie64_hi12", VK_LoongArch_TLS_IE64_HI12)214.Case("ld_pc_hi20", VK_LoongArch_TLS_LD_PC_HI20)215.Case("ld_hi20", VK_LoongArch_TLS_LD_HI20)216.Case("gd_pc_hi20", VK_LoongArch_TLS_GD_PC_HI20)217.Case("gd_hi20", VK_LoongArch_TLS_GD_HI20)218.Case("call36", VK_LoongArch_CALL36)219.Case("desc_pc_hi20", VK_LoongArch_TLS_DESC_PC_HI20)220.Case("desc_pc_lo12", VK_LoongArch_TLS_DESC_PC_LO12)221.Case("desc64_pc_lo20", VK_LoongArch_TLS_DESC64_PC_LO20)222.Case("desc64_pc_hi12", VK_LoongArch_TLS_DESC64_PC_HI12)223.Case("desc_hi20", VK_LoongArch_TLS_DESC_HI20)224.Case("desc_lo12", VK_LoongArch_TLS_DESC_LO12)225.Case("desc64_lo20", VK_LoongArch_TLS_DESC64_LO20)226.Case("desc64_hi12", VK_LoongArch_TLS_DESC64_HI12)227.Case("desc_ld", VK_LoongArch_TLS_DESC_LD)228.Case("desc_call", VK_LoongArch_TLS_DESC_CALL)229.Case("le_hi20_r", VK_LoongArch_TLS_LE_HI20_R)230.Case("le_add_r", VK_LoongArch_TLS_LE_ADD_R)231.Case("le_lo12_r", VK_LoongArch_TLS_LE_LO12_R)232.Case("pcrel_20", VK_LoongArch_PCREL20_S2)233.Case("ld_pcrel_20", VK_LoongArch_TLS_LD_PCREL20_S2)234.Case("gd_pcrel_20", VK_LoongArch_TLS_GD_PCREL20_S2)235.Case("desc_pcrel_20", VK_LoongArch_TLS_DESC_PCREL20_S2)236.Default(VK_LoongArch_Invalid);237}238239static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {240switch (Expr->getKind()) {241case MCExpr::Target:242llvm_unreachable("Can't handle nested target expression");243break;244case MCExpr::Constant:245break;246case MCExpr::Unary:247fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);248break;249case MCExpr::Binary: {250const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);251fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);252fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);253break;254}255case MCExpr::SymbolRef: {256// We're known to be under a TLS fixup, so any symbol should be257// modified. There should be only one.258const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);259cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);260break;261}262}263}264265void LoongArchMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {266switch (getKind()) {267default:268return;269case VK_LoongArch_TLS_LE_HI20:270case VK_LoongArch_TLS_IE_PC_HI20:271case VK_LoongArch_TLS_IE_HI20:272case VK_LoongArch_TLS_LD_PC_HI20:273case VK_LoongArch_TLS_LD_HI20:274case VK_LoongArch_TLS_GD_PC_HI20:275case VK_LoongArch_TLS_GD_HI20:276case VK_LoongArch_TLS_DESC_PC_HI20:277case VK_LoongArch_TLS_DESC_HI20:278case VK_LoongArch_TLS_LD_PCREL20_S2:279case VK_LoongArch_TLS_GD_PCREL20_S2:280case VK_LoongArch_TLS_DESC_PCREL20_S2:281break;282}283fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);284}285286287