Index: llvm/include/llvm/MC/MCELFStreamer.h =================================================================== --- llvm/include/llvm/MC/MCELFStreamer.h +++ llvm/include/llvm/MC/MCELFStreamer.h @@ -92,17 +92,17 @@ NumericAndTextAttributes } Type; unsigned Tag; - unsigned IntValue; + uint64_t IntValue; std::string StringValue; }; // Attributes that are added and managed entirely by target. SmallVector Contents; - void setAttributeItem(unsigned Attribute, unsigned Value, + void setAttributeItem(unsigned Attribute, uint64_t Value, bool OverwriteExisting); void setAttributeItem(unsigned Attribute, StringRef Value, bool OverwriteExisting); - void setAttributeItems(unsigned Attribute, unsigned IntValue, + void setAttributeItems(unsigned Attribute, uint64_t IntValue, StringRef StringValue, bool OverwriteExisting); void emitAttributesSection(StringRef Vendor, const Twine &Section, unsigned Type, MCSection *&AttributeSection) { Index: llvm/include/llvm/Support/ELFAttributeParser.h =================================================================== --- llvm/include/llvm/Support/ELFAttributeParser.h +++ llvm/include/llvm/Support/ELFAttributeParser.h @@ -43,7 +43,9 @@ public: virtual ~ELFAttributeParser() { static_cast(!cursor.takeError()); } + Error integerAttribute(unsigned tag, bool printAsHex); Error integerAttribute(unsigned tag); + Error maskAttribute(unsigned tag); Error stringAttribute(unsigned tag); ELFAttributeParser(ScopedPrinter *sw, TagNameMap tagNameMap, StringRef vendor) Index: llvm/include/llvm/Support/RISCVAttributes.h =================================================================== --- llvm/include/llvm/Support/RISCVAttributes.h +++ llvm/include/llvm/Support/RISCVAttributes.h @@ -32,6 +32,7 @@ PRIV_SPEC = 8, PRIV_SPEC_MINOR = 10, PRIV_SPEC_REVISION = 12, + RESERVED_REGS = 14, }; enum StackAlign { ALIGN_4 = 4, ALIGN_16 = 16 }; Index: llvm/lib/MC/MCELFStreamer.cpp =================================================================== --- llvm/lib/MC/MCELFStreamer.cpp +++ llvm/lib/MC/MCELFStreamer.cpp @@ -735,7 +735,7 @@ llvm_unreachable("ELF doesn't support this directive"); } -void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value, +void MCELFStreamer::setAttributeItem(unsigned Attribute, uint64_t Value, bool OverwriteExisting) { // Look for existing attribute item if (AttributeItem *Item = getAttributeItem(Attribute)) { @@ -769,7 +769,7 @@ Contents.push_back(Item); } -void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue, +void MCELFStreamer::setAttributeItems(unsigned Attribute, uint64_t IntValue, StringRef StringValue, bool OverwriteExisting) { // Look for existing attribute item Index: llvm/lib/Support/ELFAttributeParser.cpp =================================================================== --- llvm/lib/Support/ELFAttributeParser.cpp +++ llvm/lib/Support/ELFAttributeParser.cpp @@ -35,7 +35,7 @@ return Error::success(); } -Error ELFAttributeParser::integerAttribute(unsigned tag) { +Error ELFAttributeParser::integerAttribute(unsigned tag, bool printAsHex) { StringRef tagName = ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false); uint64_t value = de.getULEB128(cursor); @@ -46,11 +46,22 @@ sw->printNumber("Tag", tag); if (!tagName.empty()) sw->printString("TagName", tagName); - sw->printNumber("Value", value); + if (printAsHex) + sw->printHex("Value", value); + else + sw->printNumber("Value", value); } return Error::success(); } +Error ELFAttributeParser::integerAttribute(unsigned tag) { + return integerAttribute(tag, /*printAsHex=*/false); +} + +Error ELFAttributeParser::maskAttribute(unsigned tag) { + return integerAttribute(tag, /*printAsHex=*/true); +} + Error ELFAttributeParser::stringAttribute(unsigned tag) { StringRef tagName = ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false); Index: llvm/lib/Support/RISCVAttributeParser.cpp =================================================================== --- llvm/lib/Support/RISCVAttributeParser.cpp +++ llvm/lib/Support/RISCVAttributeParser.cpp @@ -36,6 +36,10 @@ { RISCVAttrs::UNALIGNED_ACCESS, &RISCVAttributeParser::unalignedAccess, + }, + { + RISCVAttrs::RESERVED_REGS, + &ELFAttributeParser::maskAttribute, }}; Error RISCVAttributeParser::unalignedAccess(unsigned tag) { Index: llvm/lib/Support/RISCVAttributes.cpp =================================================================== --- llvm/lib/Support/RISCVAttributes.cpp +++ llvm/lib/Support/RISCVAttributes.cpp @@ -18,6 +18,7 @@ {PRIV_SPEC, "Tag_priv_spec"}, {PRIV_SPEC_MINOR, "Tag_priv_spec_minor"}, {PRIV_SPEC_REVISION, "Tag_priv_spec_revision"}, + {RESERVED_REGS, "Tag_reserved_registers"}, }; constexpr TagNameMap RISCVAttributeTags{tagData}; Index: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -169,6 +169,7 @@ bool parseOperand(OperandVector &Operands, StringRef Mnemonic); bool parseDirectiveOption(); + bool parseReservedRegsAttribute(int64_t &IntegerValue); bool parseDirectiveAttribute(); void setFeatureBits(uint64_t Feature, StringRef FeatureString) { @@ -1990,6 +1991,81 @@ return false; } +/// parseReservedRegsAttribute +/// ::= '{' reg_list '}' +/// ::= '{' '}' +bool RISCVAsmParser::parseReservedRegsAttribute(int64_t &IntegerValue) { + MCAsmParser &Parser = getParser(); + + IntegerValue = 0; + if (Parser.parseToken(AsmToken::LCurly, "opening curly brace expected")) + return true; + + // Handle an empty register list + if (Parser.getTok().is(AsmToken::RCurly)) { + Parser.Lex(); + return false; + } + + // reg_list + // ::= reg_range ',' reg_list + // ::= reg_range + while (1) { + // reg_range + // ::= reg '-' reg + // ::= reg + SmallVector RegList; + + unsigned StartRegNo; + SMLoc StartLoc, EndLoc; + if (ParseRegister(StartRegNo, StartLoc, EndLoc)) + return Error(Parser.getTok().getLoc(), "expected register"); + + bool StartRegIsGPR = StartRegNo >= RISCV::X0 && StartRegNo <= RISCV::X31; + if (!StartRegIsGPR) + return Error(Parser.getTok().getLoc(), "invalid register"); + + // reg_range ::= reg '-' reg + if (Parser.getTok().is(AsmToken::Minus)) { + Parser.Lex(); + + unsigned EndRegNo; + if (ParseRegister(EndRegNo, StartLoc, EndLoc)) + return Error(Parser.getTok().getLoc(), + "expected register for end of range"); + + bool EndRegIsGPR = EndRegNo >= RISCV::X0 && EndRegNo <= RISCV::X31; + if (!EndRegIsGPR) + return Error(Parser.getTok().getLoc(), "invalid register"); + + if (StartRegIsGPR && !EndRegIsGPR) + return Error(Parser.getTok().getLoc(), "invalid register range"); + + unsigned LoRegNo = std::min(StartRegNo, EndRegNo); + unsigned HiRegNo = std::max(StartRegNo, EndRegNo); + for (unsigned RegNo = LoRegNo; RegNo <= HiRegNo; RegNo++) + RegList.push_back(RegNo); + } + // reg_range ::= reg + else + RegList.push_back(StartRegNo); + + for (unsigned RegNo : RegList) { + RegNo = RegNo - RISCV::X0; + IntegerValue |= 1ULL << RegNo; + } + + if (Parser.getTok().is(AsmToken::Comma)) + Parser.Lex(); + else + break; + } + if (Parser.parseToken(AsmToken::RCurly, "closing curly brace expected")) + return true; + + return false; +} + /// parseDirectiveAttribute /// ::= .attribute expression ',' ( expression | "string" ) /// ::= .attribute identifier ',' ( expression | "string" ) @@ -2035,7 +2111,13 @@ IsIntegerValue = false; SMLoc ValueExprLoc = Parser.getTok().getLoc(); - if (IsIntegerValue) { + + // The 'reserved register' attribute has a special syntax even though + // it is encoded as a simple integer mask. + if (Tag == RISCVAttrs::RESERVED_REGS) { + if (parseReservedRegsAttribute(IntegerValue)) + return true; + } else if (IsIntegerValue) { const MCExpr *ValueExpr; if (Parser.parseExpression(ValueExpr)) return true; @@ -2231,51 +2313,13 @@ return false; } -// Since only a RISCVGenSubtargetInfo is available here, extract register -// reservation directly from the STI bitfields. -static bool isRegisterReserved(MCRegister Reg, const MCSubtargetInfo &STI) { - switch (Reg) { - default: return false; - case RISCV::X1: return STI.getFeatureBits()[RISCV::FeatureReserveX1]; - case RISCV::X2: return STI.getFeatureBits()[RISCV::FeatureReserveX2]; - case RISCV::X3: return STI.getFeatureBits()[RISCV::FeatureReserveX3]; - case RISCV::X4: return STI.getFeatureBits()[RISCV::FeatureReserveX4]; - case RISCV::X5: return STI.getFeatureBits()[RISCV::FeatureReserveX5]; - case RISCV::X6: return STI.getFeatureBits()[RISCV::FeatureReserveX6]; - case RISCV::X7: return STI.getFeatureBits()[RISCV::FeatureReserveX7]; - case RISCV::X8: return STI.getFeatureBits()[RISCV::FeatureReserveX8]; - case RISCV::X9: return STI.getFeatureBits()[RISCV::FeatureReserveX9]; - case RISCV::X10: return STI.getFeatureBits()[RISCV::FeatureReserveX10]; - case RISCV::X11: return STI.getFeatureBits()[RISCV::FeatureReserveX11]; - case RISCV::X12: return STI.getFeatureBits()[RISCV::FeatureReserveX12]; - case RISCV::X13: return STI.getFeatureBits()[RISCV::FeatureReserveX13]; - case RISCV::X14: return STI.getFeatureBits()[RISCV::FeatureReserveX14]; - case RISCV::X15: return STI.getFeatureBits()[RISCV::FeatureReserveX15]; - case RISCV::X16: return STI.getFeatureBits()[RISCV::FeatureReserveX16]; - case RISCV::X17: return STI.getFeatureBits()[RISCV::FeatureReserveX17]; - case RISCV::X18: return STI.getFeatureBits()[RISCV::FeatureReserveX18]; - case RISCV::X19: return STI.getFeatureBits()[RISCV::FeatureReserveX19]; - case RISCV::X20: return STI.getFeatureBits()[RISCV::FeatureReserveX20]; - case RISCV::X21: return STI.getFeatureBits()[RISCV::FeatureReserveX21]; - case RISCV::X22: return STI.getFeatureBits()[RISCV::FeatureReserveX22]; - case RISCV::X23: return STI.getFeatureBits()[RISCV::FeatureReserveX23]; - case RISCV::X24: return STI.getFeatureBits()[RISCV::FeatureReserveX24]; - case RISCV::X25: return STI.getFeatureBits()[RISCV::FeatureReserveX25]; - case RISCV::X26: return STI.getFeatureBits()[RISCV::FeatureReserveX26]; - case RISCV::X27: return STI.getFeatureBits()[RISCV::FeatureReserveX27]; - case RISCV::X28: return STI.getFeatureBits()[RISCV::FeatureReserveX28]; - case RISCV::X29: return STI.getFeatureBits()[RISCV::FeatureReserveX29]; - case RISCV::X30: return STI.getFeatureBits()[RISCV::FeatureReserveX30]; - case RISCV::X31: return STI.getFeatureBits()[RISCV::FeatureReserveX31]; - } -} - void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) { // Provide a warning about defs of reserved registers. auto &Desc = MII.get(Inst.getOpcode()); for (unsigned i = 0; i < Desc.getNumDefs(); i++) { if (Inst.getOperand(i).isReg() && - isRegisterReserved(Inst.getOperand(i).getReg(), getSTI()) && + RISCVFeatures::isRegisterReserved(Inst.getOperand(i).getReg(), + getSTI()) && WarnOnReservedReg) Warning(Inst.getLoc(), "Instruction modifies reserved register"); } @@ -2567,8 +2611,7 @@ } const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); - RISCVII::VConstraintType Constraints = - RISCVII::getConstraint(MCID.TSFlags); + RISCVII::VConstraintType Constraints = RISCVII::getConstraint(MCID.TSFlags); if (Constraints == RISCVII::NoConstraint) return false; Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h @@ -316,6 +316,10 @@ namespace RISCVFeatures { +// Tests whether a given register is reserved in the feature bits of the +// subtarget. +bool isRegisterReserved(MCRegister Reg, const MCSubtargetInfo &STI); + // Validates if the given combination of features are valid for the target // triple. Exits with report_fatal_error if not. void validate(const Triple &TT, const FeatureBitset &FeatureBits); Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp @@ -14,6 +14,7 @@ #include "RISCVBaseInfo.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Triple.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/raw_ostream.h" namespace llvm { @@ -87,6 +88,43 @@ namespace RISCVFeatures { +bool isRegisterReserved(MCRegister Reg, const MCSubtargetInfo &STI) { + switch (Reg) { + default: return false; + case RISCV::X1: return STI.getFeatureBits()[RISCV::FeatureReserveX1]; + case RISCV::X2: return STI.getFeatureBits()[RISCV::FeatureReserveX2]; + case RISCV::X3: return STI.getFeatureBits()[RISCV::FeatureReserveX3]; + case RISCV::X4: return STI.getFeatureBits()[RISCV::FeatureReserveX4]; + case RISCV::X5: return STI.getFeatureBits()[RISCV::FeatureReserveX5]; + case RISCV::X6: return STI.getFeatureBits()[RISCV::FeatureReserveX6]; + case RISCV::X7: return STI.getFeatureBits()[RISCV::FeatureReserveX7]; + case RISCV::X8: return STI.getFeatureBits()[RISCV::FeatureReserveX8]; + case RISCV::X9: return STI.getFeatureBits()[RISCV::FeatureReserveX9]; + case RISCV::X10: return STI.getFeatureBits()[RISCV::FeatureReserveX10]; + case RISCV::X11: return STI.getFeatureBits()[RISCV::FeatureReserveX11]; + case RISCV::X12: return STI.getFeatureBits()[RISCV::FeatureReserveX12]; + case RISCV::X13: return STI.getFeatureBits()[RISCV::FeatureReserveX13]; + case RISCV::X14: return STI.getFeatureBits()[RISCV::FeatureReserveX14]; + case RISCV::X15: return STI.getFeatureBits()[RISCV::FeatureReserveX15]; + case RISCV::X16: return STI.getFeatureBits()[RISCV::FeatureReserveX16]; + case RISCV::X17: return STI.getFeatureBits()[RISCV::FeatureReserveX17]; + case RISCV::X18: return STI.getFeatureBits()[RISCV::FeatureReserveX18]; + case RISCV::X19: return STI.getFeatureBits()[RISCV::FeatureReserveX19]; + case RISCV::X20: return STI.getFeatureBits()[RISCV::FeatureReserveX20]; + case RISCV::X21: return STI.getFeatureBits()[RISCV::FeatureReserveX21]; + case RISCV::X22: return STI.getFeatureBits()[RISCV::FeatureReserveX22]; + case RISCV::X23: return STI.getFeatureBits()[RISCV::FeatureReserveX23]; + case RISCV::X24: return STI.getFeatureBits()[RISCV::FeatureReserveX24]; + case RISCV::X25: return STI.getFeatureBits()[RISCV::FeatureReserveX25]; + case RISCV::X26: return STI.getFeatureBits()[RISCV::FeatureReserveX26]; + case RISCV::X27: return STI.getFeatureBits()[RISCV::FeatureReserveX27]; + case RISCV::X28: return STI.getFeatureBits()[RISCV::FeatureReserveX28]; + case RISCV::X29: return STI.getFeatureBits()[RISCV::FeatureReserveX29]; + case RISCV::X30: return STI.getFeatureBits()[RISCV::FeatureReserveX30]; + case RISCV::X31: return STI.getFeatureBits()[RISCV::FeatureReserveX31]; + } +} + void validate(const Triple &TT, const FeatureBitset &FeatureBits) { if (TT.isArch64Bit() && !FeatureBits[RISCV::Feature64Bit]) report_fatal_error("RV64 target requires an RV64 CPU"); Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h @@ -84,10 +84,11 @@ std::string(StringValue)}); } - void emitAttribute(unsigned Attribute, unsigned Value) override; + void emitAttribute(unsigned Attribute, uint64_t Value) override; void emitTextAttribute(unsigned Attribute, StringRef String) override; - void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, + void emitIntTextAttribute(unsigned Attribute, uint64_t IntValue, StringRef StringValue) override; + void emitRegListAttribute(unsigned Attribute, uint64_t IntValue) override; void finishAttributeSection() override; size_t calculateContentSize() const; Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -79,7 +79,7 @@ void RISCVTargetELFStreamer::emitDirectiveOptionWarnReservedReg() {} void RISCVTargetELFStreamer::emitDirectiveOptionNoWarnReservedReg() {} -void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) { +void RISCVTargetELFStreamer::emitAttribute(unsigned Attribute, uint64_t Value) { setAttributeItem(Attribute, Value, /*OverwriteExisting=*/true); } @@ -89,12 +89,17 @@ } void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute, - unsigned IntValue, + uint64_t IntValue, StringRef StringValue) { setAttributeItems(Attribute, IntValue, StringValue, /*OverwriteExisting=*/true); } +void RISCVTargetELFStreamer::emitRegListAttribute(unsigned Attribute, + uint64_t IntValue) { + setAttributeItem(Attribute, IntValue, /*OverwriteExisting=*/true); +} + void RISCVTargetELFStreamer::finishAttributeSection() { if (Contents.empty()) return; Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h @@ -31,11 +31,12 @@ virtual void emitDirectiveOptionNoRelax(); virtual void emitDirectiveOptionWarnReservedReg(); virtual void emitDirectiveOptionNoWarnReservedReg(); - virtual void emitAttribute(unsigned Attribute, unsigned Value); + virtual void emitAttribute(unsigned Attribute, uint64_t Value); virtual void finishAttributeSection(); virtual void emitTextAttribute(unsigned Attribute, StringRef String); - virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, + virtual void emitIntTextAttribute(unsigned Attribute, uint64_t IntValue, StringRef StringValue); + virtual void emitRegListAttribute(unsigned Attribute, uint64_t IntValue); void emitTargetAttributes(const MCSubtargetInfo &STI); }; @@ -45,10 +46,11 @@ formatted_raw_ostream &OS; void finishAttributeSection() override; - void emitAttribute(unsigned Attribute, unsigned Value) override; + void emitAttribute(unsigned Attribute, uint64_t Value) override; void emitTextAttribute(unsigned Attribute, StringRef String) override; - void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, + void emitIntTextAttribute(unsigned Attribute, uint64_t IntValue, StringRef StringValue) override; + void emitRegListAttribute(unsigned Attribute, uint64_t IntValue) override; public: RISCVTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp @@ -11,6 +11,8 @@ //===----------------------------------------------------------------------===// #include "RISCVTargetStreamer.h" +#include "RISCVBaseInfo.h" +#include "RISCVInstPrinter.h" #include "RISCVMCTargetDesc.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/RISCVAttributes.h" @@ -29,13 +31,15 @@ void RISCVTargetStreamer::emitDirectiveOptionNoRVC() {} void RISCVTargetStreamer::emitDirectiveOptionRelax() {} void RISCVTargetStreamer::emitDirectiveOptionNoRelax() {} -void RISCVTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {} +void RISCVTargetStreamer::emitAttribute(unsigned Attribute, uint64_t Value) {} void RISCVTargetStreamer::finishAttributeSection() {} void RISCVTargetStreamer::emitTextAttribute(unsigned Attribute, StringRef String) {} void RISCVTargetStreamer::emitIntTextAttribute(unsigned Attribute, - unsigned IntValue, + uint64_t IntValue, StringRef StringValue) {} +void RISCVTargetStreamer::emitRegListAttribute(unsigned Attribute, + uint64_t IntValue) {} void RISCVTargetStreamer::emitDirectiveOptionWarnReservedReg() {} void RISCVTargetStreamer::emitDirectiveOptionNoWarnReservedReg() {} @@ -96,6 +100,16 @@ Arch += "_zvlsseg0p10"; emitTextAttribute(RISCVAttrs::ARCH, Arch); + + // Calculcate the mask of gpr registers which are reserved and emit the + // attribute if it's non-empty. + uint64_t ReservedMask = 0; + for (unsigned Reg = 0; Reg < 32; Reg++) { + if (RISCVFeatures::isRegisterReserved(RISCV::X0 + Reg, STI)) + ReservedMask |= 1ULL << Reg; + } + if (ReservedMask) + emitRegListAttribute(RISCVAttrs::RESERVED_REGS, ReservedMask); } // This part is for ascii assembly output @@ -135,7 +149,7 @@ OS << "\t.option\tnorelax\n"; } -void RISCVTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) { +void RISCVTargetAsmStreamer::emitAttribute(unsigned Attribute, uint64_t Value) { OS << "\t.attribute\t" << Attribute << ", " << Twine(Value) << "\n"; } @@ -145,9 +159,33 @@ } void RISCVTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute, - unsigned IntValue, + uint64_t IntValue, StringRef StringValue) {} +void RISCVTargetAsmStreamer::emitRegListAttribute(unsigned Attribute, + uint64_t IntValue) { + dbgs() << IntValue << "\n"; + OS << "\t.attribute\t" << Attribute << ", {"; + bool PrintComma = false; + for (unsigned Reg = 0; Reg < 32; Reg++) { + if (IntValue & (1ULL << Reg)) { + unsigned RangeStart = Reg; + unsigned RangeEnd = Reg; + while ((IntValue & (1ULL << Reg)) && Reg < 32) + RangeEnd = Reg++; + + if (PrintComma) + OS << ", "; + + OS << RISCVInstPrinter::getRegisterName(RISCV::X0 + RangeStart); + if (RangeStart != RangeEnd) + OS << "-" << RISCVInstPrinter::getRegisterName(RISCV::X0 + RangeEnd); + PrintComma = true; + } + } + OS << "}\n"; +} + void RISCVTargetAsmStreamer::finishAttributeSection() {} void RISCVTargetAsmStreamer::emitDirectiveOptionWarnReservedReg() { Index: llvm/test/CodeGen/RISCV/attributes.ll =================================================================== --- llvm/test/CodeGen/RISCV/attributes.ll +++ llvm/test/CodeGen/RISCV/attributes.ll @@ -20,6 +20,7 @@ ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbs %s -o - | FileCheck --check-prefix=RV32ZBS %s ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbt %s -o - | FileCheck --check-prefix=RV32ZBT %s ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbb,+experimental-zfh,+experimental-zvamo,+experimental-v,+f,+experimental-zvlsseg %s -o - | FileCheck --check-prefix=RV32COMBINED %s +; RUN: llc -mtriple=riscv32 -mattr=+reserve-x2,+reserve-x14,+reserve-x29,+reserve-x30,+reserve-x31 %s -o - | FileCheck --check-prefix=RV32RESERVED %s ; RUN: llc -mtriple=riscv64 -mattr=+m %s -o - | FileCheck --check-prefix=RV64M %s ; RUN: llc -mtriple=riscv64 -mattr=+a %s -o - | FileCheck --check-prefix=RV64A %s ; RUN: llc -mtriple=riscv64 -mattr=+f %s -o - | FileCheck --check-prefix=RV64F %s @@ -40,6 +41,7 @@ ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbs %s -o - | FileCheck --check-prefix=RV64ZBS %s ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbt %s -o - | FileCheck --check-prefix=RV64ZBT %s ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbb,+experimental-zfh,+experimental-zvamo,+experimental-v,+f,+experimental-zvlsseg %s -o - | FileCheck --check-prefix=RV64COMBINED %s +; RUN: llc -mtriple=riscv64 -mattr=+reserve-x2,+reserve-x14,+reserve-x29,+reserve-x30,+reserve-x31 %s -o - | FileCheck --check-prefix=RV64RESERVED %s ; RV32M: .attribute 5, "rv32i2p0_m2p0" ; RV32A: .attribute 5, "rv32i2p0_a2p0" @@ -61,6 +63,7 @@ ; RV32ZBS: .attribute 5, "rv32i2p0_zbs0p93" ; RV32ZBT: .attribute 5, "rv32i2p0_zbt0p93" ; RV32COMBINED: .attribute 5, "rv32i2p0_f2p0_v0p10_zfh0p1_zbb0p93_zvamo0p10_zvlsseg0p10" +; RV32RESERVED: .attribute 14, {sp, a4, t4-t6} ; RV64M: .attribute 5, "rv64i2p0_m2p0" ; RV64A: .attribute 5, "rv64i2p0_a2p0" @@ -82,6 +85,7 @@ ; RV64ZBT: .attribute 5, "rv64i2p0_zbt0p93" ; RV64V: .attribute 5, "rv64i2p0_v0p10_zvamo0p10_zvlsseg0p10" ; RV64COMBINED: .attribute 5, "rv64i2p0_f2p0_v0p10_zfh0p1_zbb0p93_zvamo0p10_zvlsseg0p10" +; RV64RESERVED: .attribute 14, {sp, a4, t4-t6} define i32 @addi(i32 %a) { Index: llvm/test/MC/RISCV/attribute-reserved-regs.s =================================================================== --- /dev/null +++ llvm/test/MC/RISCV/attribute-reserved-regs.s @@ -0,0 +1,22 @@ +## Test llvm-mc can handle the reserved_regs attribute correctly. + +# RUN: llvm-mc %s -triple=riscv32 -filetype=asm | FileCheck %s +# RUN: llvm-mc %s -triple=riscv64 -filetype=asm | FileCheck %s + +.attribute reserved_registers, { } +# CHECK: attribute 14, 0 + +.attribute reserved_registers, { x1 } +# CHECK: attribute 14, 2 + +.attribute reserved_registers, { x0-x5 } +# CHECK: attribute 14, 63 + +.attribute reserved_registers, { x22-x21 } +# CHECK: attribute 14, 6291456 + +.attribute reserved_registers, { t3, t5-t6 } +# CHECK: attribute 14, 3489660928 + +.attribute reserved_registers, { x0, x1, x2, x3, x29-x30, x31 } +# CHECK: attribute 14, 3758096399 Index: llvm/test/MC/RISCV/attribute.s =================================================================== --- llvm/test/MC/RISCV/attribute.s +++ llvm/test/MC/RISCV/attribute.s @@ -20,3 +20,6 @@ .attribute priv_spec_revision, 0 # CHECK: attribute 12, 0 + +.attribute reserved_registers, { } +# CHECK: attribute 14, 0