
Summary: Previously, we would erroneously turn %pcrel_lo(label), where label has a %pcrel_hi against a weak symbol, into %pcrel_lo(label + offset), as evaluatePCRelLo would believe the target independent logic was going to fold it. Moreover, even if that were fixed, shouldForceRelocation lacks an MCAsmLayout and thus cannot evaluate the %pcrel_hi fixup to a value and check the symbol, so we would then erroneously constant-fold the %pcrel_lo whilst leaving the %pcrel_hi intact. After D72197, this same sequence also occurs for symbols with global binding, which is triggered in real-world code. Instead, as discussed in D71978, we introduce a new FKF_IsTarget flag to avoid these kinds of issues. All the resolution logic happens in one place, with no coordination required between RISCAsmBackend and RISCVMCExpr to ensure they implement the same logic twice. Although the implementation of %pcrel_hi can be left as target independent, we make it target dependent to ensure that they are handled identically to %pcrel_lo, otherwise we risk one of them being constant folded but the other being preserved. This also allows us to properly support fixup pairs where the instructions are in different fragments. Reviewers: asb, lenary, efriedma Reviewed By: efriedma Subscribers: arichardson, hiraditya, rbar, johnrusso, simoncook, sabuasal, niosHD, kito-cheng, shiva0217, MaskRay, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, Jim, s.egerton, pzheng, sameer.abuasal, apazos, luismarques, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D73211
92 lines
2.6 KiB
C++
92 lines
2.6 KiB
C++
//===-- RISCVMCExpr.h - RISCV 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file describes RISCV-specific MCExprs, used for modifiers like
|
|
// "%hi" or "%lo" etc.,
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVMCEXPR_H
|
|
#define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVMCEXPR_H
|
|
|
|
#include "llvm/MC/MCExpr.h"
|
|
|
|
namespace llvm {
|
|
|
|
class StringRef;
|
|
class MCOperand;
|
|
class RISCVMCExpr : public MCTargetExpr {
|
|
public:
|
|
enum VariantKind {
|
|
VK_RISCV_None,
|
|
VK_RISCV_LO,
|
|
VK_RISCV_HI,
|
|
VK_RISCV_PCREL_LO,
|
|
VK_RISCV_PCREL_HI,
|
|
VK_RISCV_GOT_HI,
|
|
VK_RISCV_TPREL_LO,
|
|
VK_RISCV_TPREL_HI,
|
|
VK_RISCV_TPREL_ADD,
|
|
VK_RISCV_TLS_GOT_HI,
|
|
VK_RISCV_TLS_GD_HI,
|
|
VK_RISCV_CALL,
|
|
VK_RISCV_CALL_PLT,
|
|
VK_RISCV_32_PCREL,
|
|
VK_RISCV_Invalid
|
|
};
|
|
|
|
private:
|
|
const MCExpr *Expr;
|
|
const VariantKind Kind;
|
|
|
|
int64_t evaluateAsInt64(int64_t Value) const;
|
|
|
|
explicit RISCVMCExpr(const MCExpr *Expr, VariantKind Kind)
|
|
: Expr(Expr), Kind(Kind) {}
|
|
|
|
public:
|
|
static const RISCVMCExpr *create(const MCExpr *Expr, VariantKind Kind,
|
|
MCContext &Ctx);
|
|
|
|
VariantKind getKind() const { return Kind; }
|
|
|
|
const MCExpr *getSubExpr() const { return Expr; }
|
|
|
|
/// Get the corresponding PC-relative HI fixup that a VK_RISCV_PCREL_LO
|
|
/// points to, and optionally the fragment containing it.
|
|
///
|
|
/// \returns nullptr if this isn't a VK_RISCV_PCREL_LO pointing to a
|
|
/// known PC-relative HI fixup.
|
|
const MCFixup *getPCRelHiFixup(const MCFragment **DFOut) const;
|
|
|
|
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
|
|
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
|
|
const MCFixup *Fixup) const override;
|
|
void visitUsedExpr(MCStreamer &Streamer) const override;
|
|
MCFragment *findAssociatedFragment() const override {
|
|
return getSubExpr()->findAssociatedFragment();
|
|
}
|
|
|
|
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override;
|
|
|
|
bool evaluateAsConstant(int64_t &Res) const;
|
|
|
|
static bool classof(const MCExpr *E) {
|
|
return E->getKind() == MCExpr::Target;
|
|
}
|
|
|
|
static bool classof(const RISCVMCExpr *) { return true; }
|
|
|
|
static VariantKind getVariantKindForName(StringRef name);
|
|
static StringRef getVariantKindName(VariantKind Kind);
|
|
};
|
|
|
|
} // end namespace llvm.
|
|
|
|
#endif
|