diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/MC/MCAsmBackend.cpp | 10 | ||||
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 21 | ||||
-rw-r--r-- | llvm/lib/MC/MCExpr.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp | 18 |
6 files changed, 74 insertions, 5 deletions
diff --git a/llvm/lib/MC/MCAsmBackend.cpp b/llvm/lib/MC/MCAsmBackend.cpp index 3119bb997d0..92d3a8a2645 100644 --- a/llvm/lib/MC/MCAsmBackend.cpp +++ b/llvm/lib/MC/MCAsmBackend.cpp @@ -84,7 +84,15 @@ const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { {"FK_SecRel_1", 0, 8, 0}, {"FK_SecRel_2", 0, 16, 0}, {"FK_SecRel_4", 0, 32, 0}, - {"FK_SecRel_8", 0, 64, 0}}; + {"FK_SecRel_8", 0, 64, 0}, + {"FK_Data_Add_1", 0, 8, 0}, + {"FK_Data_Add_2", 0, 16, 0}, + {"FK_Data_Add_4", 0, 32, 0}, + {"FK_Data_Add_8", 0, 64, 0}, + {"FK_Data_Sub_1", 0, 8, 0}, + {"FK_Data_Sub_2", 0, 16, 0}, + {"FK_Data_Sub_4", 0, 32, 0}, + {"FK_Data_Sub_8", 0, 64, 0}}; assert((size_t)Kind <= array_lengthof(Builtins) && "Unknown fixup kind"); return Builtins[Kind]; diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index f63df8b1002..0cf17a10d08 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -720,7 +720,26 @@ MCAssembler::handleFixup(const MCAsmLayout &Layout, MCFragment &F, // The fixup was unresolved, we need a relocation. Inform the object // writer of the relocation, and give it an opportunity to adjust the // fixup value if need be. - getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, FixedValue); + if (Target.getSymA() && Target.getSymB() && + getBackend().requiresDiffExpressionRelocations()) { + // The fixup represents the difference between two symbols, which the + // backend has indicated must be resolved at link time. Split up the fixup + // into two relocations, one for the add, and one for the sub, and emit + // both of these. The constant will be associated with the add half of the + // expression. + MCFixup FixupAdd = MCFixup::createAddFor(Fixup); + MCValue TargetAdd = + MCValue::get(Target.getSymA(), nullptr, Target.getConstant()); + getWriter().recordRelocation(*this, Layout, &F, FixupAdd, TargetAdd, + FixedValue); + MCFixup FixupSub = MCFixup::createSubFor(Fixup); + MCValue TargetSub = MCValue::get(Target.getSymB()); + getWriter().recordRelocation(*this, Layout, &F, FixupSub, TargetSub, + FixedValue); + } else { + getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, + FixedValue); + } } return std::make_tuple(Target, FixedValue, IsResolved); } diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index 831c692fb2e..d38127fe135 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Config/llvm-config.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" @@ -576,8 +577,12 @@ EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout, assert((!Layout || Asm) && "Must have an assembler object if layout is given!"); - // If we have a layout, we can fold resolved differences. - if (Asm) { + // If we have a layout, we can fold resolved differences. Do not do this if + // the backend requires this to be emitted as individual relocations, unless + // the InSet flag is set to get the current difference anyway (used for + // example to calculate symbol sizes). + if (Asm && + (InSet || !Asm->getBackend().requiresDiffExpressionRelocations())) { // First, fold out any differences which are fully resolved. By // reassociating terms in // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index 91fe3f774ca..5ac3273022f 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -37,6 +37,11 @@ public: Is64Bit(Is64Bit) {} ~RISCVAsmBackend() override {} + // Generate diff expression relocations if the relax feature is enabled, + // otherwise it is safe for the assembler to calculate these internally. + bool requiresDiffExpressionRelocations() const override { + return STI.getFeatureBits()[RISCV::FeatureRelax]; + } void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef<char> Data, uint64_t Value, bool IsResolved) const override; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp index b164c78c35d..57b52aa7add 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp @@ -56,6 +56,22 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx, return ELF::R_RISCV_32; case FK_Data_8: return ELF::R_RISCV_64; + case FK_Data_Add_1: + return ELF::R_RISCV_ADD8; + case FK_Data_Add_2: + return ELF::R_RISCV_ADD16; + case FK_Data_Add_4: + return ELF::R_RISCV_ADD32; + case FK_Data_Add_8: + return ELF::R_RISCV_ADD64; + case FK_Data_Sub_1: + return ELF::R_RISCV_SUB8; + case FK_Data_Sub_2: + return ELF::R_RISCV_SUB16; + case FK_Data_Sub_4: + return ELF::R_RISCV_SUB32; + case FK_Data_Sub_8: + return ELF::R_RISCV_SUB64; case RISCV::fixup_riscv_hi20: return ELF::R_RISCV_HI20; case RISCV::fixup_riscv_lo12_i: diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp index 844039f08f9..085dcd4e5f6 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp @@ -44,7 +44,23 @@ void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const { - return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); + 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_RISCV_LO: + case VK_RISCV_HI: + case VK_RISCV_PCREL_LO: + case VK_RISCV_PCREL_HI: + return false; + } + } + + return true; } void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const { |