aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp139
1 files changed, 139 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp b/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp
new file mode 100644
index 000000000000..b9989822dc36
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp
@@ -0,0 +1,139 @@
+//===-- CSKYMCExpr.cpp - CSKY specific MC expression classes -*- C++ -*----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CSKYMCExpr.h"
+#include "CSKYFixupKinds.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/Support/Casting.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "csky-mc-expr"
+
+const CSKYMCExpr *CSKYMCExpr::create(const MCExpr *Expr, VariantKind Kind,
+ MCContext &Ctx) {
+ return new (Ctx) CSKYMCExpr(Kind, Expr);
+}
+
+StringRef CSKYMCExpr::getVariantKindName(VariantKind Kind) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("Invalid ELF symbol kind");
+ case VK_CSKY_None:
+ case VK_CSKY_ADDR:
+ return "";
+ case VK_CSKY_ADDR_HI16:
+ return "@HI16";
+ case VK_CSKY_ADDR_LO16:
+ return "@LO16";
+ case VK_CSKY_GOT_IMM18_BY4:
+ case VK_CSKY_GOT:
+ return "@GOT";
+ case VK_CSKY_GOTPC:
+ return "@GOTPC";
+ case VK_CSKY_GOTOFF:
+ return "@GOTOFF";
+ case VK_CSKY_PLT_IMM18_BY4:
+ case VK_CSKY_PLT:
+ return "@PLT";
+ case VK_CSKY_TLSLE:
+ return "@TPOFF";
+ case VK_CSKY_TLSIE:
+ return "@GOTTPOFF";
+ case VK_CSKY_TLSGD:
+ return "@TLSGD32";
+ case VK_CSKY_TLSLDO:
+ return "@TLSLDO32";
+ case VK_CSKY_TLSLDM:
+ return "@TLSLDM32";
+ }
+}
+
+void CSKYMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
+ Streamer.visitUsedExpr(*getSubExpr());
+}
+
+void CSKYMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
+ Expr->print(OS, MAI);
+ OS << getVariantKindName(getKind());
+}
+
+static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
+ switch (Expr->getKind()) {
+ case MCExpr::Target:
+ llvm_unreachable("Can't handle nested target expression");
+ break;
+ case MCExpr::Constant:
+ break;
+
+ case MCExpr::Binary: {
+ const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
+ fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
+ fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
+ break;
+ }
+
+ case MCExpr::SymbolRef: {
+ // We're known to be under a TLS fixup, so any symbol should be
+ // modified. There should be only one.
+ const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
+ cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
+ break;
+ }
+
+ case MCExpr::Unary:
+ fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
+ break;
+ }
+}
+
+void CSKYMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
+ switch (getKind()) {
+ default:
+ return;
+ case VK_CSKY_TLSLE:
+ case VK_CSKY_TLSIE:
+ case VK_CSKY_TLSGD:
+ break;
+ }
+
+ fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
+}
+
+bool CSKYMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
+ const MCAsmLayout *Layout,
+ const MCFixup *Fixup) const {
+ if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
+ return false;
+
+ // Some custom fixup types are not valid with symbol difference expressions
+ if (Res.getSymA() && Res.getSymB()) {
+ switch (getKind()) {
+ default:
+ return true;
+ case VK_CSKY_GOT:
+ case VK_CSKY_GOT_IMM18_BY4:
+ case VK_CSKY_GOTPC:
+ case VK_CSKY_GOTOFF:
+ case VK_CSKY_PLT:
+ case VK_CSKY_PLT_IMM18_BY4:
+ case VK_CSKY_TLSIE:
+ case VK_CSKY_TLSLE:
+ case VK_CSKY_TLSGD:
+ case VK_CSKY_TLSLDO:
+ case VK_CSKY_TLSLDM:
+ return false;
+ }
+ }
+
+ return true;
+}