diff options
author | Lewis Revill <lewis.revill@embecosm.com> | 2019-04-04 14:13:37 +0000 |
---|---|---|
committer | Lewis Revill <lewis.revill@embecosm.com> | 2019-04-04 14:13:37 +0000 |
commit | aa79a3fe8e09da6b6cb30a70308a804d9b232112 (patch) | |
tree | 6afa7dcd62b265871a498c8fc93a8357398371a9 /llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp | |
parent | 9f598ac7062cfb72d17d59a8f2ab322d2d31a60d (diff) | |
download | bcm5719-llvm-aa79a3fe8e09da6b6cb30a70308a804d9b232112.tar.gz bcm5719-llvm-aa79a3fe8e09da6b6cb30a70308a804d9b232112.zip |
[RISCV] Support assembling TLS add and associated modifiers
This patch adds support in the MC layer for parsing and assembling the
4-operand add instruction needed for TLS addressing. This also involves
parsing the %tprel_hi, %tprel_lo and %tprel_add operand modifiers.
Differential Revision: https://reviews.llvm.org/D55341
llvm-svn: 357698
Diffstat (limited to 'llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp')
-rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp index 692398ea955..f1248e53feb 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -56,6 +56,10 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + void expandAddTPRel(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + /// TableGen'erated function for getting the binary encoding for an /// instruction. uint64_t getBinaryCodeForInstr(const MCInst &MI, @@ -120,6 +124,44 @@ void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI, raw_ostream &OS, support::endian::write(OS, Binary, support::little); } +// Expand PseudoAddTPRel to a simple ADD with the correct relocation. +void RISCVMCCodeEmitter::expandAddTPRel(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + MCOperand DestReg = MI.getOperand(0); + MCOperand SrcReg = MI.getOperand(1); + MCOperand TPReg = MI.getOperand(2); + assert(TPReg.isReg() && TPReg.getReg() == RISCV::X4 && + "Expected thread pointer as second input to TP-relative add"); + + MCOperand SrcSymbol = MI.getOperand(3); + assert(SrcSymbol.isExpr() && + "Expected expression as third input to TP-relative add"); + + const RISCVMCExpr *Expr = dyn_cast<RISCVMCExpr>(SrcSymbol.getExpr()); + assert(Expr && Expr->getKind() == RISCVMCExpr::VK_RISCV_TPREL_ADD && + "Expected tprel_add relocation on TP-relative symbol"); + + // Emit the correct tprel_add relocation for the symbol. + Fixups.push_back(MCFixup::create( + 0, Expr, MCFixupKind(RISCV::fixup_riscv_tprel_add), MI.getLoc())); + + // Emit fixup_riscv_relax for tprel_add where the relax feature is enabled. + if (STI.getFeatureBits()[RISCV::FeatureRelax]) { + const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx); + Fixups.push_back(MCFixup::create( + 0, Dummy, MCFixupKind(RISCV::fixup_riscv_relax), MI.getLoc())); + } + + // Emit a normal ADD instruction with the given operands. + MCInst TmpInst = MCInstBuilder(RISCV::ADD) + .addOperand(DestReg) + .addOperand(SrcReg) + .addOperand(TPReg); + uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); + support::endian::write(OS, Binary, support::little); +} + void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { @@ -134,6 +176,12 @@ void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, return; } + if (MI.getOpcode() == RISCV::PseudoAddTPRel) { + expandAddTPRel(MI, OS, Fixups, STI); + MCNumEmitted += 1; + return; + } + switch (Size) { default: llvm_unreachable("Unhandled encodeInstruction length!"); @@ -208,6 +256,13 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, case RISCVMCExpr::VK_RISCV_None: case RISCVMCExpr::VK_RISCV_Invalid: llvm_unreachable("Unhandled fixup kind!"); + case RISCVMCExpr::VK_RISCV_TPREL_ADD: + // tprel_add is only used to indicate that a relocation should be emitted + // for an add instruction used in TP-relative addressing. It should not be + // expanded as if representing an actual instruction operand and so to + // encounter it here is an error. + llvm_unreachable( + "VK_RISCV_TPREL_ADD should not represent an instruction operand"); case RISCVMCExpr::VK_RISCV_LO: if (MIFrm == RISCVII::InstFormatI) FixupKind = RISCV::fixup_riscv_lo12_i; @@ -238,6 +293,20 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, case RISCVMCExpr::VK_RISCV_GOT_HI: FixupKind = RISCV::fixup_riscv_got_hi20; break; + case RISCVMCExpr::VK_RISCV_TPREL_LO: + if (MIFrm == RISCVII::InstFormatI) + FixupKind = RISCV::fixup_riscv_tprel_lo12_i; + else if (MIFrm == RISCVII::InstFormatS) + FixupKind = RISCV::fixup_riscv_tprel_lo12_s; + else + llvm_unreachable( + "VK_RISCV_TPREL_LO used with unexpected instruction format"); + RelaxCandidate = true; + break; + case RISCVMCExpr::VK_RISCV_TPREL_HI: + FixupKind = RISCV::fixup_riscv_tprel_hi20; + RelaxCandidate = true; + break; case RISCVMCExpr::VK_RISCV_CALL: FixupKind = RISCV::fixup_riscv_call; RelaxCandidate = true; |