diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index e4d5ad556d1ba3..dc1047631af76e 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -180,6 +180,7 @@ class RISCVAsmParser : public MCTargetAsmParser { bool parseDirectiveOption(); bool parseDirectiveAttribute(); bool parseDirectiveInsn(SMLoc L); + bool parseDirectiveVariantCC(); void setFeatureBits(uint64_t Feature, StringRef FeatureString) { if (!(getSTI().getFeatureBits()[Feature])) { @@ -2035,6 +2036,8 @@ bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { return parseDirectiveAttribute(); if (IDVal == ".insn") return parseDirectiveInsn(DirectiveID.getLoc()); + if (IDVal == ".variant_cc") + return parseDirectiveVariantCC(); return true; } @@ -2297,6 +2300,19 @@ bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) { /*MatchingInlineAsm=*/false); } +/// parseDirectiveVariantCC +/// ::= .variant_cc symbol +bool RISCVAsmParser::parseDirectiveVariantCC() { + StringRef Name; + if (getParser().parseIdentifier(Name)) + return TokError("expected symbol name"); + if (parseEOL()) + return false; + getTargetStreamer().emitDirectiveVariantCC( + *getContext().getOrCreateSymbol(Name)); + return false; +} + void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) { MCInst CInst; bool Res = compressInst(CInst, Inst, getSTI(), S.getContext()); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp index c63488bb4d3476..f0b246b9fb0923 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -187,6 +187,11 @@ void RISCVTargetELFStreamer::reset() { Contents.clear(); } +void RISCVTargetELFStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) { + getStreamer().getAssembler().registerSymbol(Symbol); + cast(Symbol).setOther(ELF::STO_RISCV_VARIANT_CC); +} + namespace { class RISCVELFStreamer : public MCELFStreamer { static std::pair getRelocPairForSize(unsigned Size) { diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h index 7ca2f5ab562349..ccb20af0caa5be 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h @@ -106,6 +106,7 @@ class RISCVTargetELFStreamer : public RISCVTargetStreamer { void emitDirectiveOptionNoRVC() override; void emitDirectiveOptionRelax() override; void emitDirectiveOptionNoRelax() override; + void emitDirectiveVariantCC(MCSymbol &Symbol) override; void finish() override; }; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp index 5f9ed77d07cf58..e03869f3834b37 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp @@ -32,6 +32,7 @@ void RISCVTargetStreamer::emitDirectiveOptionRVC() {} void RISCVTargetStreamer::emitDirectiveOptionNoRVC() {} void RISCVTargetStreamer::emitDirectiveOptionRelax() {} void RISCVTargetStreamer::emitDirectiveOptionNoRelax() {} +void RISCVTargetStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) {} void RISCVTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {} void RISCVTargetStreamer::finishAttributeSection() {} void RISCVTargetStreamer::emitTextAttribute(unsigned Attribute, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h index 0d35d0b698a9f5..3455859949beef 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h @@ -33,6 +33,7 @@ class RISCVTargetStreamer : public MCTargetStreamer { virtual void emitDirectiveOptionNoRVC(); virtual void emitDirectiveOptionRelax(); virtual void emitDirectiveOptionNoRelax(); + virtual void emitDirectiveVariantCC(MCSymbol &Symbol); virtual void emitAttribute(unsigned Attribute, unsigned Value); virtual void finishAttributeSection(); virtual void emitTextAttribute(unsigned Attribute, StringRef String); diff --git a/llvm/test/MC/RISCV/directive-variant_cc.s b/llvm/test/MC/RISCV/directive-variant_cc.s new file mode 100644 index 00000000000000..c40de9f3618e09 --- /dev/null +++ b/llvm/test/MC/RISCV/directive-variant_cc.s @@ -0,0 +1,42 @@ +// RUN: llvm-mc -triple riscv64 -filetype obj -o - %s | llvm-readobj --symbols - | FileCheck %s +// RUN: llvm-mc -triple riscv64 -filetype obj -defsym=OBJ=1 -o - %s | llvm-readelf -s - | FileCheck %s --check-prefix=OBJ +// RUN: not llvm-mc -triple riscv64 -filetype asm -defsym=ERR=1 -o - %s 2>&1 | FileCheck %s --check-prefix=ERR + +.text +.variant_cc local +local: + +// CHECK: Name: local +// CHECK: Other [ (0x80) + +.ifdef OBJ +/// Binding directive before .variant_cc. +.global def1 +.variant_cc def1 +def1: + +/// Binding directive after .variant_cc. +.variant_cc def2 +.weak def2 +def2: + +.globl alias_def1 +.set alias_def1, def1 + +.variant_cc undef + +// OBJ: NOTYPE LOCAL DEFAULT [VARIANT_CC] [[#]] local +// OBJ-NEXT: NOTYPE GLOBAL DEFAULT [VARIANT_CC] [[#]] def1 +// OBJ-NEXT: NOTYPE WEAK DEFAULT [VARIANT_CC] [[#]] def2 +// OBJ-NEXT: NOTYPE GLOBAL DEFAULT [[#]] alias_def1 +// OBJ-NEXT: NOTYPE GLOBAL DEFAULT [VARIANT_CC] UND undef +.endif + +.ifdef ERR +.variant_cc +// ERR: [[#@LINE-1]]:12: error: expected symbol name + +.global fox +.variant_cc fox bar +// ERR: [[#@LINE-1]]:17: error: expected newline +.endif