diff options
Diffstat (limited to 'llvm/lib/Target/RISCV/MCTargetDesc')
14 files changed, 568 insertions, 188 deletions
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index 5881a0a86ef7..bb1f1cc7f49a 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -9,6 +9,7 @@ #include "RISCVAsmBackend.h" #include "RISCVMCExpr.h" #include "llvm/ADT/APInt.h" +#include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDirectives.h" @@ -22,14 +23,75 @@ using namespace llvm; +Optional<MCFixupKind> RISCVAsmBackend::getFixupKind(StringRef Name) const { + if (STI.getTargetTriple().isOSBinFormatELF()) { + unsigned Type; + Type = llvm::StringSwitch<unsigned>(Name) +#define ELF_RELOC(X, Y) .Case(#X, Y) +#include "llvm/BinaryFormat/ELFRelocs/RISCV.def" +#undef ELF_RELOC + .Default(-1u); + if (Type != -1u) + return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type); + } + return None; +} + +const MCFixupKindInfo & +RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { + const static MCFixupKindInfo Infos[] = { + // This table *must* be in the order that the fixup_* kinds are defined in + // RISCVFixupKinds.h. + // + // name offset bits flags + {"fixup_riscv_hi20", 12, 20, 0}, + {"fixup_riscv_lo12_i", 20, 12, 0}, + {"fixup_riscv_lo12_s", 0, 32, 0}, + {"fixup_riscv_pcrel_hi20", 12, 20, + MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget}, + {"fixup_riscv_pcrel_lo12_i", 20, 12, + MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget}, + {"fixup_riscv_pcrel_lo12_s", 0, 32, + MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget}, + {"fixup_riscv_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_tprel_hi20", 12, 20, 0}, + {"fixup_riscv_tprel_lo12_i", 20, 12, 0}, + {"fixup_riscv_tprel_lo12_s", 0, 32, 0}, + {"fixup_riscv_tprel_add", 0, 0, 0}, + {"fixup_riscv_tls_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_tls_gd_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_rvc_branch", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_call", 0, 64, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_call_plt", 0, 64, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_relax", 0, 0, 0}, + {"fixup_riscv_align", 0, 0, 0}}; + static_assert((array_lengthof(Infos)) == RISCV::NumTargetFixupKinds, + "Not all fixup kinds added to Infos array"); + + // Fixup kinds from .reloc directive are like R_RISCV_NONE. They + // do not require any extra processing. + if (Kind >= FirstLiteralRelocationKind) + return MCAsmBackend::getFixupKindInfo(FK_NONE); + + if (Kind < FirstTargetFixupKind) + return MCAsmBackend::getFixupKindInfo(Kind); + + assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && + "Invalid kind!"); + return Infos[Kind - FirstTargetFixupKind]; +} + // If linker relaxation is enabled, or the relax option had previously been // enabled, always emit relocations even if the fixup can be resolved. This is // necessary for correctness as offsets may change during relaxation. bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target) { - bool ShouldForce = false; - + if (Fixup.getKind() >= FirstLiteralRelocationKind) + return true; switch (Fixup.getTargetKind()) { default: break; @@ -44,40 +106,9 @@ bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm, case RISCV::fixup_riscv_tls_got_hi20: case RISCV::fixup_riscv_tls_gd_hi20: return true; - case RISCV::fixup_riscv_pcrel_lo12_i: - case RISCV::fixup_riscv_pcrel_lo12_s: - // For pcrel_lo12, force a relocation if the target of the corresponding - // pcrel_hi20 is not in the same fragment. - const MCFixup *T = cast<RISCVMCExpr>(Fixup.getValue())->getPCRelHiFixup(); - if (!T) { - Asm.getContext().reportError(Fixup.getLoc(), - "could not find corresponding %pcrel_hi"); - return false; - } - - switch (T->getTargetKind()) { - default: - llvm_unreachable("Unexpected fixup kind for pcrel_lo12"); - break; - case RISCV::fixup_riscv_got_hi20: - case RISCV::fixup_riscv_tls_got_hi20: - case RISCV::fixup_riscv_tls_gd_hi20: - ShouldForce = true; - break; - case RISCV::fixup_riscv_pcrel_hi20: { - MCFragment *TFragment = T->getValue()->findAssociatedFragment(); - MCFragment *FixupFragment = Fixup.getValue()->findAssociatedFragment(); - assert(FixupFragment && "We should have a fragment for this fixup"); - ShouldForce = - !TFragment || TFragment->getParent() != FixupFragment->getParent(); - break; - } - } - break; } - return ShouldForce || STI.getFeatureBits()[RISCV::FeatureRelax] || - ForceRelocs; + return STI.getFeatureBits()[RISCV::FeatureRelax] || ForceRelocs; } bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, @@ -108,10 +139,10 @@ bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, } } -void RISCVAsmBackend::relaxInstruction(const MCInst &Inst, - const MCSubtargetInfo &STI, - MCInst &Res) const { +void RISCVAsmBackend::relaxInstruction(MCInst &Inst, + const MCSubtargetInfo &STI) const { // TODO: replace this with call to auto generated uncompressinstr() function. + MCInst Res; switch (Inst.getOpcode()) { default: llvm_unreachable("Opcode not expected!"); @@ -142,6 +173,7 @@ void RISCVAsmBackend::relaxInstruction(const MCInst &Inst, Res.addOperand(Inst.getOperand(0)); break; } + Inst = std::move(Res); } // Given a compressed control flow instruction this function returns @@ -284,13 +316,77 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, } } +bool RISCVAsmBackend::evaluateTargetFixup( + const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup, + const MCFragment *DF, const MCValue &Target, uint64_t &Value, + bool &WasForced) { + const MCFixup *AUIPCFixup; + const MCFragment *AUIPCDF; + MCValue AUIPCTarget; + switch (Fixup.getTargetKind()) { + default: + llvm_unreachable("Unexpected fixup kind!"); + case RISCV::fixup_riscv_pcrel_hi20: + AUIPCFixup = &Fixup; + AUIPCDF = DF; + AUIPCTarget = Target; + break; + case RISCV::fixup_riscv_pcrel_lo12_i: + case RISCV::fixup_riscv_pcrel_lo12_s: { + AUIPCFixup = cast<RISCVMCExpr>(Fixup.getValue())->getPCRelHiFixup(&AUIPCDF); + if (!AUIPCFixup) { + Asm.getContext().reportError(Fixup.getLoc(), + "could not find corresponding %pcrel_hi"); + return true; + } + + // MCAssembler::evaluateFixup will emit an error for this case when it sees + // the %pcrel_hi, so don't duplicate it when also seeing the %pcrel_lo. + const MCExpr *AUIPCExpr = AUIPCFixup->getValue(); + if (!AUIPCExpr->evaluateAsRelocatable(AUIPCTarget, &Layout, AUIPCFixup)) + return true; + break; + } + } + + if (!AUIPCTarget.getSymA() || AUIPCTarget.getSymB()) + return false; + + const MCSymbolRefExpr *A = AUIPCTarget.getSymA(); + const MCSymbol &SA = A->getSymbol(); + if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined()) + return false; + + auto *Writer = Asm.getWriterPtr(); + if (!Writer) + return false; + + bool IsResolved = Writer->isSymbolRefDifferenceFullyResolvedImpl( + Asm, SA, *AUIPCDF, false, true); + if (!IsResolved) + return false; + + Value = Layout.getSymbolOffset(SA) + AUIPCTarget.getConstant(); + Value -= Layout.getFragmentOffset(AUIPCDF) + AUIPCFixup->getOffset(); + + if (shouldForceRelocation(Asm, *AUIPCFixup, AUIPCTarget)) { + WasForced = true; + return false; + } + + return true; +} + void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef<char> Data, uint64_t Value, bool IsResolved, const MCSubtargetInfo *STI) const { + MCFixupKind Kind = Fixup.getKind(); + if (Kind >= FirstLiteralRelocationKind) + return; MCContext &Ctx = Asm.getContext(); - MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); + MCFixupKindInfo Info = getFixupKindInfo(Kind); if (!Value) return; // Doesn't change encoding. // Apply any target-specific value adjustments. diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h index 254249c87dc8..090132af3585 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -65,6 +65,11 @@ public: const MCAsmLayout &Layout, MCAlignFragment &AF) override; + bool evaluateTargetFixup(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFixup &Fixup, const MCFragment *DF, + const MCValue &Target, uint64_t &Value, + bool &WasForced) override; + void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef<char> Data, uint64_t Value, bool IsResolved, @@ -92,52 +97,16 @@ public: return RISCV::NumTargetFixupKinds; } - const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { - const static MCFixupKindInfo Infos[] = { - // This table *must* be in the order that the fixup_* kinds are defined in - // RISCVFixupKinds.h. - // - // name offset bits flags - { "fixup_riscv_hi20", 12, 20, 0 }, - { "fixup_riscv_lo12_i", 20, 12, 0 }, - { "fixup_riscv_lo12_s", 0, 32, 0 }, - { "fixup_riscv_pcrel_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_pcrel_lo12_i", 20, 12, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_pcrel_lo12_s", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_tprel_hi20", 12, 20, 0 }, - { "fixup_riscv_tprel_lo12_i", 20, 12, 0 }, - { "fixup_riscv_tprel_lo12_s", 0, 32, 0 }, - { "fixup_riscv_tprel_add", 0, 0, 0 }, - { "fixup_riscv_tls_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_tls_gd_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_rvc_branch", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_call", 0, 64, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_call_plt", 0, 64, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_relax", 0, 0, 0 }, - { "fixup_riscv_align", 0, 0, 0 } - }; - static_assert((array_lengthof(Infos)) == RISCV::NumTargetFixupKinds, - "Not all fixup kinds added to Infos array"); - - if (Kind < FirstTargetFixupKind) - return MCAsmBackend::getFixupKindInfo(Kind); - - assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && - "Invalid kind!"); - return Infos[Kind - FirstTargetFixupKind]; - } + Optional<MCFixupKind> getFixupKind(StringRef Name) const override; + + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; bool mayNeedRelaxation(const MCInst &Inst, const MCSubtargetInfo &STI) const override; unsigned getRelaxedOpcode(unsigned Op) const; - void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, - MCInst &Res) const override; - + void relaxInstruction(MCInst &Inst, + const MCSubtargetInfo &STI) const override; bool writeNopData(raw_ostream &OS, uint64_t Count) const override; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp index 08b75795ed4b..b38ba2bff582 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp @@ -52,6 +52,8 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx, const MCExpr *Expr = Fixup.getValue(); // Determine the type of the relocation unsigned Kind = Fixup.getTargetKind(); + if (Kind >= FirstLiteralRelocationKind) + return Kind - FirstLiteralRelocationKind; if (IsPCRel) { switch (Kind) { default: diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp index 40fa195f3790..079dc919928a 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -15,14 +15,18 @@ #include "RISCVMCTargetDesc.h" #include "Utils/RISCVBaseInfo.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/RISCVAttributes.h" using namespace llvm; // This part is for ELF object output. RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI) - : RISCVTargetStreamer(S) { + : RISCVTargetStreamer(S), CurrentVendor("riscv") { MCAssembler &MCA = getStreamer().getAssembler(); const FeatureBitset &Features = STI.getFeatureBits(); auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend()); @@ -62,7 +66,104 @@ MCELFStreamer &RISCVTargetELFStreamer::getStreamer() { void RISCVTargetELFStreamer::emitDirectiveOptionPush() {} void RISCVTargetELFStreamer::emitDirectiveOptionPop() {} +void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {} +void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {} void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {} void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {} void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {} void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {} + +void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) { + setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true); +} + +void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute, + StringRef String) { + setAttributeItem(Attribute, String, /*OverwriteExisting=*/true); +} + +void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute, + unsigned IntValue, + StringRef StringValue) { + setAttributeItems(Attribute, IntValue, StringValue, + /*OverwriteExisting=*/true); +} + +void RISCVTargetELFStreamer::finishAttributeSection() { + if (Contents.empty()) + return; + + if (AttributeSection) { + Streamer.SwitchSection(AttributeSection); + } else { + MCAssembler &MCA = getStreamer().getAssembler(); + AttributeSection = MCA.getContext().getELFSection( + ".riscv.attributes", ELF::SHT_RISCV_ATTRIBUTES, 0); + Streamer.SwitchSection(AttributeSection); + + Streamer.emitInt8(ELFAttrs::Format_Version); + } + + // Vendor size + Vendor name + '\0' + const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1; + + // Tag + Tag Size + const size_t TagHeaderSize = 1 + 4; + + const size_t ContentsSize = calculateContentSize(); + + Streamer.emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize); + Streamer.emitBytes(CurrentVendor); + Streamer.emitInt8(0); // '\0' + + Streamer.emitInt8(ELFAttrs::File); + Streamer.emitInt32(TagHeaderSize + ContentsSize); + + // Size should have been accounted for already, now + // emit each field as its type (ULEB or String). + for (AttributeItem item : Contents) { + Streamer.emitULEB128IntValue(item.Tag); + switch (item.Type) { + default: + llvm_unreachable("Invalid attribute type"); + case AttributeType::Numeric: + Streamer.emitULEB128IntValue(item.IntValue); + break; + case AttributeType::Text: + Streamer.emitBytes(item.StringValue); + Streamer.emitInt8(0); // '\0' + break; + case AttributeType::NumericAndText: + Streamer.emitULEB128IntValue(item.IntValue); + Streamer.emitBytes(item.StringValue); + Streamer.emitInt8(0); // '\0' + break; + } + } + + Contents.clear(); +} + +size_t RISCVTargetELFStreamer::calculateContentSize() const { + size_t Result = 0; + for (AttributeItem item : Contents) { + switch (item.Type) { + case AttributeType::Hidden: + break; + case AttributeType::Numeric: + Result += getULEB128Size(item.Tag); + Result += getULEB128Size(item.IntValue); + break; + case AttributeType::Text: + Result += getULEB128Size(item.Tag); + Result += item.StringValue.size() + 1; // string + '\0' + break; + case AttributeType::NumericAndText: + Result += getULEB128Size(item.Tag); + Result += getULEB128Size(item.IntValue); + Result += item.StringValue.size() + 1; // string + '\0'; + break; + } + } + return Result; +} diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h index 138df786eaf3..392c87054d43 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h @@ -15,16 +15,94 @@ namespace llvm { class RISCVTargetELFStreamer : public RISCVTargetStreamer { +private: + enum class AttributeType { Hidden, Numeric, Text, NumericAndText }; + + struct AttributeItem { + AttributeType Type; + unsigned Tag; + unsigned IntValue; + std::string StringValue; + }; + + StringRef CurrentVendor; + SmallVector<AttributeItem, 64> Contents; + + MCSection *AttributeSection = nullptr; + + AttributeItem *getAttributeItem(unsigned Attribute) { + for (size_t i = 0; i < Contents.size(); ++i) + if (Contents[i].Tag == Attribute) + return &Contents[i]; + return nullptr; + } + + void setAttributeItem(unsigned Attribute, unsigned Value, + bool OverwriteExisting) { + // Look for existing attribute item. + if (AttributeItem *Item = getAttributeItem(Attribute)) { + if (!OverwriteExisting) + return; + Item->Type = AttributeType::Numeric; + Item->IntValue = Value; + return; + } + + // Create new attribute item. + Contents.push_back({AttributeType::Numeric, Attribute, Value, ""}); + } + + void setAttributeItem(unsigned Attribute, StringRef Value, + bool OverwriteExisting) { + // Look for existing attribute item. + if (AttributeItem *Item = getAttributeItem(Attribute)) { + if (!OverwriteExisting) + return; + Item->Type = AttributeType::Text; + Item->StringValue = std::string(Value); + return; + } + + // Create new attribute item. + Contents.push_back({AttributeType::Text, Attribute, 0, std::string(Value)}); + } + + void setAttributeItems(unsigned Attribute, unsigned IntValue, + StringRef StringValue, bool OverwriteExisting) { + // Look for existing attribute item. + if (AttributeItem *Item = getAttributeItem(Attribute)) { + if (!OverwriteExisting) + return; + Item->Type = AttributeType::NumericAndText; + Item->IntValue = IntValue; + Item->StringValue = std::string(StringValue); + return; + } + + // Create new attribute item. + Contents.push_back({AttributeType::NumericAndText, Attribute, IntValue, + std::string(StringValue)}); + } + + void emitAttribute(unsigned Attribute, unsigned Value) override; + void emitTextAttribute(unsigned Attribute, StringRef String) override; + void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, + StringRef StringValue) override; + void finishAttributeSection() override; + size_t calculateContentSize() const; + public: MCELFStreamer &getStreamer(); RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); - virtual void emitDirectiveOptionPush(); - virtual void emitDirectiveOptionPop(); - virtual void emitDirectiveOptionRVC(); - virtual void emitDirectiveOptionNoRVC(); - virtual void emitDirectiveOptionRelax(); - virtual void emitDirectiveOptionNoRelax(); + void emitDirectiveOptionPush() override; + void emitDirectiveOptionPop() override; + void emitDirectiveOptionPIC() override; + void emitDirectiveOptionNoPIC() override; + void emitDirectiveOptionRVC() override; + void emitDirectiveOptionNoRVC() override; + void emitDirectiveOptionRelax() override; + void emitDirectiveOptionNoRelax() override; }; } #endif diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp index 22bb80ae34e2..eae3e13dbe40 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp @@ -73,7 +73,7 @@ void RISCVInstPrinter::printInst(const MCInst *MI, uint64_t Address, Res = uncompressInst(UncompressedMI, *MI, MRI, STI); if (Res) NewMI = const_cast<MCInst *>(&UncompressedMI); - if (NoAliases || !printAliasInstr(NewMI, STI, O)) + if (NoAliases || !printAliasInstr(NewMI, Address, STI, O)) printInstruction(NewMI, Address, STI, O); printAnnotation(O, Annot); } @@ -150,6 +150,39 @@ void RISCVInstPrinter::printAtomicMemOp(const MCInst *MI, unsigned OpNo, return; } +void RISCVInstPrinter::printVTypeI(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O) { + unsigned Imm = MI->getOperand(OpNo).getImm(); + unsigned Sew = (Imm >> 2) & 0x7; + unsigned Lmul = Imm & 0x3; + + Lmul = 0x1 << Lmul; + Sew = 0x1 << (Sew + 3); + O << "e" << Sew << ",m" << Lmul; +} + +void RISCVInstPrinter::printVMaskReg(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, + raw_ostream &O) { + const MCOperand &MO = MI->getOperand(OpNo); + + assert(MO.isReg() && "printVMaskReg can only print register operands"); + if (MO.getReg() == RISCV::NoRegister) + return; + O << ", "; + printRegName(O, MO.getReg()); + O << ".t"; +} + +void RISCVInstPrinter::printSImm5Plus1(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, + raw_ostream &O) { + const MCOperand &MO = MI->getOperand(OpNo); + + assert(MO.isImm() && "printSImm5Plus1 can only print constant operands"); + O << MO.getImm() + 1; +} + const char *RISCVInstPrinter::getRegisterName(unsigned RegNo) { return getRegisterName(RegNo, ArchRegNames ? RISCV::NoRegAltName : RISCV::ABIRegAltName); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h index aeb2ea636060..fdaa00c5f8eb 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h @@ -17,7 +17,6 @@ #include "llvm/MC/MCInstPrinter.h" namespace llvm { -class MCOperand; class RISCVInstPrinter : public MCInstPrinter { public: @@ -41,14 +40,20 @@ public: raw_ostream &O); void printAtomicMemOp(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O); + void printVTypeI(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, + raw_ostream &O); + void printVMaskReg(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O); + void printSImm5Plus1(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O); // Autogenerated by tblgen. void printInstruction(const MCInst *MI, uint64_t Address, const MCSubtargetInfo &STI, raw_ostream &O); - bool printAliasInstr(const MCInst *MI, const MCSubtargetInfo &STI, - raw_ostream &O); - void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx, - unsigned PrintMethodIdx, + bool printAliasInstr(const MCInst *MI, uint64_t Address, + const MCSubtargetInfo &STI, raw_ostream &O); + void printCustomAliasOperand(const MCInst *MI, uint64_t Address, + unsigned OpIdx, unsigned PrintMethodIdx, const MCSubtargetInfo &STI, raw_ostream &O); static const char *getRegisterName(unsigned RegNo); static const char *getRegisterName(unsigned RegNo, unsigned AltIdx); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp index de99960848a5..816206c477df 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -80,6 +80,10 @@ public: unsigned getImmOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + + unsigned getVMaskReg(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; }; } // end anonymous namespace @@ -89,13 +93,14 @@ MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII, return new RISCVMCCodeEmitter(Ctx, MCII); } -// Expand PseudoCALL(Reg) and PseudoTAIL to AUIPC and JALR with relocation -// types. We expand PseudoCALL(Reg) and PseudoTAIL while encoding, meaning AUIPC -// and JALR won't go through RISCV MC to MC compressed instruction -// transformation. This is acceptable because AUIPC has no 16-bit form and -// C_JALR have no immediate operand field. We let linker relaxation deal with -// it. When linker relaxation enabled, AUIPC and JALR have chance relax to JAL. -// If C extension is enabled, JAL has chance relax to C_JAL. +// Expand PseudoCALL(Reg), PseudoTAIL and PseudoJump to AUIPC and JALR with +// relocation types. We expand those pseudo-instructions while encoding them, +// meaning AUIPC and JALR won't go through RISCV MC to MC compressed +// instruction transformation. This is acceptable because AUIPC has no 16-bit +// form and C_JALR has no immediate operand field. We let linker relaxation +// deal with it. When linker relaxation is enabled, AUIPC and JALR have a +// chance to relax to JAL. +// If the C extension is enabled, JAL has a chance relax to C_JAL. void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { @@ -108,9 +113,12 @@ void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI, raw_ostream &OS, } else if (MI.getOpcode() == RISCV::PseudoCALLReg) { Func = MI.getOperand(1); Ra = MI.getOperand(0).getReg(); - } else { + } else if (MI.getOpcode() == RISCV::PseudoCALL) { Func = MI.getOperand(0); Ra = RISCV::X1; + } else if (MI.getOpcode() == RISCV::PseudoJump) { + Func = MI.getOperand(1); + Ra = MI.getOperand(0).getReg(); } uint32_t Binary; @@ -125,8 +133,9 @@ void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI, raw_ostream &OS, Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); support::endian::write(OS, Binary, support::little); - if (MI.getOpcode() == RISCV::PseudoTAIL) - // Emit JALR X0, X6, 0 + if (MI.getOpcode() == RISCV::PseudoTAIL || + MI.getOpcode() == RISCV::PseudoJump) + // Emit JALR X0, Ra, 0 TmpInst = MCInstBuilder(RISCV::JALR).addReg(RISCV::X0).addReg(Ra).addImm(0); else // Emit JALR Ra, Ra, 0 @@ -180,9 +189,13 @@ void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, // Get byte count of instruction. unsigned Size = Desc.getSize(); + // RISCVInstrInfo::getInstSizeInBytes hard-codes the number of expanded + // instructions for each pseudo, and must be updated when adding new pseudos + // or changing existing ones. if (MI.getOpcode() == RISCV::PseudoCALLReg || MI.getOpcode() == RISCV::PseudoCALL || - MI.getOpcode() == RISCV::PseudoTAIL) { + MI.getOpcode() == RISCV::PseudoTAIL || + MI.getOpcode() == RISCV::PseudoJump) { expandFunctionCall(MI, OS, Fixups, STI); MCNumEmitted += 2; return; @@ -368,4 +381,20 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, return 0; } +unsigned RISCVMCCodeEmitter::getVMaskReg(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + MCOperand MO = MI.getOperand(OpNo); + assert(MO.isReg() && "Expected a register."); + + switch (MO.getReg()) { + default: + llvm_unreachable("Invalid mask register."); + case RISCV::V0: + return 0; + case RISCV::NoRegister: + return 1; + } +} + #include "RISCVGenMCCodeEmitter.inc" diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp index 7aa9b5e7d683..2a6f372e50be 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp @@ -47,7 +47,7 @@ void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { OS << ')'; } -const MCFixup *RISCVMCExpr::getPCRelHiFixup() const { +const MCFixup *RISCVMCExpr::getPCRelHiFixup(const MCFragment **DFOut) const { MCValue AUIPCLoc; if (!getSubExpr()->evaluateAsRelocatable(AUIPCLoc, nullptr, nullptr)) return nullptr; @@ -81,6 +81,8 @@ const MCFixup *RISCVMCExpr::getPCRelHiFixup() const { case RISCV::fixup_riscv_tls_got_hi20: case RISCV::fixup_riscv_tls_gd_hi20: case RISCV::fixup_riscv_pcrel_hi20: + if (DFOut) + *DFOut = DF; return &F; } } @@ -88,74 +90,9 @@ const MCFixup *RISCVMCExpr::getPCRelHiFixup() const { return nullptr; } -bool RISCVMCExpr::evaluatePCRelLo(MCValue &Res, const MCAsmLayout *Layout, - const MCFixup *Fixup) const { - // VK_RISCV_PCREL_LO has to be handled specially. The MCExpr inside is - // actually the location of a auipc instruction with a VK_RISCV_PCREL_HI fixup - // pointing to the real target. We need to generate an MCValue in the form of - // (<real target> + <offset from this fixup to the auipc fixup>). The Fixup - // is pcrel relative to the VK_RISCV_PCREL_LO fixup, so we need to add the - // offset to the VK_RISCV_PCREL_HI Fixup from VK_RISCV_PCREL_LO to correct. - - // Don't try to evaluate if the fixup will be forced as a relocation (e.g. - // as linker relaxation is enabled). If we evaluated pcrel_lo in this case, - // the modified fixup will be converted into a relocation that no longer - // points to the pcrel_hi as the linker requires. - auto &RAB = - static_cast<RISCVAsmBackend &>(Layout->getAssembler().getBackend()); - if (RAB.willForceRelocations()) - return false; - - MCValue AUIPCLoc; - if (!getSubExpr()->evaluateAsValue(AUIPCLoc, *Layout)) - return false; - - const MCSymbolRefExpr *AUIPCSRE = AUIPCLoc.getSymA(); - // Don't try to evaluate %pcrel_hi/%pcrel_lo pairs that cross fragment - // boundries. - if (!AUIPCSRE || - findAssociatedFragment() != AUIPCSRE->findAssociatedFragment()) - return false; - - const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol(); - if (!AUIPCSymbol) - return false; - - const MCFixup *TargetFixup = getPCRelHiFixup(); - if (!TargetFixup) - return false; - - if ((unsigned)TargetFixup->getKind() != RISCV::fixup_riscv_pcrel_hi20) - return false; - - MCValue Target; - if (!TargetFixup->getValue()->evaluateAsValue(Target, *Layout)) - return false; - - if (!Target.getSymA() || !Target.getSymA()->getSymbol().isInSection()) - return false; - - if (&Target.getSymA()->getSymbol().getSection() != - findAssociatedFragment()->getParent()) - return false; - - // We must use TargetFixup rather than AUIPCSymbol here. They will almost - // always have the same offset, except for the case when AUIPCSymbol is at - // the end of a fragment and the fixup comes from offset 0 in the next - // fragment. - uint64_t AUIPCOffset = TargetFixup->getOffset(); - - Res = MCValue::get(Target.getSymA(), nullptr, - Target.getConstant() + (Fixup->getOffset() - AUIPCOffset)); - return true; -} - bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const { - if (Kind == VK_RISCV_PCREL_LO && evaluatePCRelLo(Res, Layout, Fixup)) - return true; - if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup)) return false; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h index 921df376f3df..77038cee4e9d 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h @@ -19,7 +19,7 @@ namespace llvm { class StringRef; -class MCOperand; + class RISCVMCExpr : public MCTargetExpr { public: enum VariantKind { @@ -46,9 +46,6 @@ private: int64_t evaluateAsInt64(int64_t Value) const; - bool evaluatePCRelLo(MCValue &Res, const MCAsmLayout *Layout, - const MCFixup *Fixup) const; - explicit RISCVMCExpr(const MCExpr *Expr, VariantKind Kind) : Expr(Expr), Kind(Kind) {} @@ -61,11 +58,11 @@ public: const MCExpr *getSubExpr() const { return Expr; } /// Get the corresponding PC-relative HI fixup that a VK_RISCV_PCREL_LO - /// points to. + /// 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; + const MCFixup *getPCRelHiFixup(const MCFragment **DFOut) const; void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp index c37482be3c2c..a474224e1a4e 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/Register.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" @@ -56,7 +57,7 @@ static MCAsmInfo *createRISCVMCAsmInfo(const MCRegisterInfo &MRI, MCAsmInfo *MAI = new RISCVMCAsmInfo(TT); Register SP = MRI.getDwarfRegNum(RISCV::X2, true); - MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, SP, 0); + MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(nullptr, SP, 0); MAI->addInitialFrameState(Inst); return MAI; @@ -64,7 +65,7 @@ static MCAsmInfo *createRISCVMCAsmInfo(const MCRegisterInfo &MRI, static MCSubtargetInfo *createRISCVMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { - std::string CPUName = CPU; + std::string CPUName = std::string(CPU); if (CPUName.empty()) CPUName = TT.isArch64Bit() ? "generic-rv64" : "generic-rv32"; return createRISCVMCSubtargetInfoImpl(TT, CPUName, FS); @@ -93,6 +94,49 @@ static MCTargetStreamer *createRISCVAsmTargetStreamer(MCStreamer &S, return new RISCVTargetAsmStreamer(S, OS); } +static MCTargetStreamer *createRISCVNullTargetStreamer(MCStreamer &S) { + return new RISCVTargetStreamer(S); +} + +namespace { + +class RISCVMCInstrAnalysis : public MCInstrAnalysis { +public: + explicit RISCVMCInstrAnalysis(const MCInstrInfo *Info) + : MCInstrAnalysis(Info) {} + + bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + uint64_t &Target) const override { + if (isConditionalBranch(Inst)) { + int64_t Imm; + if (Size == 2) + Imm = Inst.getOperand(1).getImm(); + else + Imm = Inst.getOperand(2).getImm(); + Target = Addr + Imm; + return true; + } + + if (Inst.getOpcode() == RISCV::C_JAL || Inst.getOpcode() == RISCV::C_J) { + Target = Addr + Inst.getOperand(0).getImm(); + return true; + } + + if (Inst.getOpcode() == RISCV::JAL) { + Target = Addr + Inst.getOperand(1).getImm(); + return true; + } + + return false; + } +}; + +} // end anonymous namespace + +static MCInstrAnalysis *createRISCVInstrAnalysis(const MCInstrInfo *Info) { + return new RISCVMCInstrAnalysis(Info); +} + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMC() { for (Target *T : {&getTheRISCV32Target(), &getTheRISCV64Target()}) { TargetRegistry::RegisterMCAsmInfo(*T, createRISCVMCAsmInfo); @@ -104,8 +148,12 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMC() { TargetRegistry::RegisterMCSubtargetInfo(*T, createRISCVMCSubtargetInfo); TargetRegistry::RegisterObjectTargetStreamer( *T, createRISCVObjectTargetStreamer); + TargetRegistry::RegisterMCInstrAnalysis(*T, createRISCVInstrAnalysis); // Register the asm target streamer. TargetRegistry::RegisterAsmTargetStreamer(*T, createRISCVAsmTargetStreamer); + // Register the null target streamer. + TargetRegistry::RegisterNullTargetStreamer(*T, + createRISCVNullTargetStreamer); } } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h index b30997533ddf..5216a689715a 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h @@ -26,11 +26,7 @@ class MCInstrInfo; class MCObjectTargetWriter; class MCRegisterInfo; class MCSubtargetInfo; -class StringRef; class Target; -class Triple; -class raw_ostream; -class raw_pwrite_stream; MCCodeEmitter *createRISCVMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp index 913e1f744192..54a2fb288579 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp @@ -11,12 +11,59 @@ //===----------------------------------------------------------------------===// #include "RISCVTargetStreamer.h" +#include "RISCVSubtarget.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/RISCVAttributes.h" using namespace llvm; RISCVTargetStreamer::RISCVTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} +void RISCVTargetStreamer::finish() { finishAttributeSection(); } + +void RISCVTargetStreamer::emitDirectiveOptionPush() {} +void RISCVTargetStreamer::emitDirectiveOptionPop() {} +void RISCVTargetStreamer::emitDirectiveOptionPIC() {} +void RISCVTargetStreamer::emitDirectiveOptionNoPIC() {} +void RISCVTargetStreamer::emitDirectiveOptionRVC() {} +void RISCVTargetStreamer::emitDirectiveOptionNoRVC() {} +void RISCVTargetStreamer::emitDirectiveOptionRelax() {} +void RISCVTargetStreamer::emitDirectiveOptionNoRelax() {} +void RISCVTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {} +void RISCVTargetStreamer::finishAttributeSection() {} +void RISCVTargetStreamer::emitTextAttribute(unsigned Attribute, + StringRef String) {} +void RISCVTargetStreamer::emitIntTextAttribute(unsigned Attribute, + unsigned IntValue, + StringRef StringValue) {} + +void RISCVTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) { + if (STI.hasFeature(RISCV::FeatureRV32E)) + emitAttribute(RISCVAttrs::STACK_ALIGN, RISCVAttrs::ALIGN_4); + else + emitAttribute(RISCVAttrs::STACK_ALIGN, RISCVAttrs::ALIGN_16); + + std::string Arch = "rv32"; + if (STI.hasFeature(RISCV::Feature64Bit)) + Arch = "rv64"; + if (STI.hasFeature(RISCV::FeatureRV32E)) + Arch += "e1p9"; + else + Arch += "i2p0"; + if (STI.hasFeature(RISCV::FeatureStdExtM)) + Arch += "_m2p0"; + if (STI.hasFeature(RISCV::FeatureStdExtA)) + Arch += "_a2p0"; + if (STI.hasFeature(RISCV::FeatureStdExtF)) + Arch += "_f2p0"; + if (STI.hasFeature(RISCV::FeatureStdExtD)) + Arch += "_d2p0"; + if (STI.hasFeature(RISCV::FeatureStdExtC)) + Arch += "_c2p0"; + + emitTextAttribute(RISCVAttrs::ARCH, Arch); +} + // This part is for ascii assembly output RISCVTargetAsmStreamer::RISCVTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS) @@ -30,6 +77,14 @@ void RISCVTargetAsmStreamer::emitDirectiveOptionPop() { OS << "\t.option\tpop\n"; } +void RISCVTargetAsmStreamer::emitDirectiveOptionPIC() { + OS << "\t.option\tpic\n"; +} + +void RISCVTargetAsmStreamer::emitDirectiveOptionNoPIC() { + OS << "\t.option\tnopic\n"; +} + void RISCVTargetAsmStreamer::emitDirectiveOptionRVC() { OS << "\t.option\trvc\n"; } @@ -45,3 +100,18 @@ void RISCVTargetAsmStreamer::emitDirectiveOptionRelax() { void RISCVTargetAsmStreamer::emitDirectiveOptionNoRelax() { OS << "\t.option\tnorelax\n"; } + +void RISCVTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) { + OS << "\t.attribute\t" << Attribute << ", " << Twine(Value) << "\n"; +} + +void RISCVTargetAsmStreamer::emitTextAttribute(unsigned Attribute, + StringRef String) { + OS << "\t.attribute\t" << Attribute << ", \"" << String << "\"\n"; +} + +void RISCVTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute, + unsigned IntValue, + StringRef StringValue) {} + +void RISCVTargetAsmStreamer::finishAttributeSection() {} diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h index 1becc134b2a2..32fa20f25d82 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h @@ -10,30 +10,49 @@ #define LLVM_LIB_TARGET_RISCV_RISCVTARGETSTREAMER_H #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" namespace llvm { class RISCVTargetStreamer : public MCTargetStreamer { public: RISCVTargetStreamer(MCStreamer &S); - - virtual void emitDirectiveOptionPush() = 0; - virtual void emitDirectiveOptionPop() = 0; - virtual void emitDirectiveOptionRVC() = 0; - virtual void emitDirectiveOptionNoRVC() = 0; - virtual void emitDirectiveOptionRelax() = 0; - virtual void emitDirectiveOptionNoRelax() = 0; + void finish() override; + + virtual void emitDirectiveOptionPush(); + virtual void emitDirectiveOptionPop(); + virtual void emitDirectiveOptionPIC(); + virtual void emitDirectiveOptionNoPIC(); + virtual void emitDirectiveOptionRVC(); + virtual void emitDirectiveOptionNoRVC(); + virtual void emitDirectiveOptionRelax(); + virtual void emitDirectiveOptionNoRelax(); + virtual void emitAttribute(unsigned Attribute, unsigned Value); + virtual void finishAttributeSection(); + virtual void emitTextAttribute(unsigned Attribute, StringRef String); + virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, + StringRef StringValue); + + void emitTargetAttributes(const MCSubtargetInfo &STI); }; // This part is for ascii assembly output class RISCVTargetAsmStreamer : public RISCVTargetStreamer { formatted_raw_ostream &OS; + void finishAttributeSection() override; + void emitAttribute(unsigned Attribute, unsigned Value) override; + void emitTextAttribute(unsigned Attribute, StringRef String) override; + void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, + StringRef StringValue) override; + public: RISCVTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); void emitDirectiveOptionPush() override; void emitDirectiveOptionPop() override; + void emitDirectiveOptionPIC() override; + void emitDirectiveOptionNoPIC() override; void emitDirectiveOptionRVC() override; void emitDirectiveOptionNoRVC() override; void emitDirectiveOptionRelax() override; |