Skip to content

[RISCV] RISCV vector calling convention (1/2) #77560

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 27, 2024

Conversation

4vtomat
Copy link
Member

@4vtomat 4vtomat commented Jan 10, 2024

[RISCV] RISCV vector calling convention (1/2)

This is the vector calling convention based on
https://github.com/riscv-non-isa/riscv-elf-psabi-doc,
the idea is to split between "scalar" callee-saved registers
and "vector" callee-saved registers. "scalar" ones remain the
original strategy, however, "vector" ones are handled together
with RVV objects.

The stack layout would be:

  |--------------------------| <-- FP
  | callee-allocated save    |
  | area for register varargs|
  |--------------------------|
  | callee-saved registers   | <-- scalar callee-saved
  |        (scalar)          |
  |--------------------------|
  | RVV alignment padding    |
  |--------------------------|
  | callee-saved registers   | <-- vector callee-saved
  |        (vector)          |
  |--------------------------|
  | RVV objects              |
  |--------------------------|
  | padding before RVV       |
  |--------------------------|
  | scalar local variables   |
  |--------------------------| <-- BP
  | variable size objects    |
  |--------------------------| <-- SP

Note: This patch doesn't contain "tuple" type, e.g. vint32m1x2.
      It will be handled in https://github.com/riscv-non-isa/riscv-elf-psabi-doc (2/2).

@llvmbot llvmbot added clang Clang issues not falling into any other category backend:RISC-V clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. llvm:ir labels Jan 10, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 10, 2024

@llvm/pr-subscribers-debuginfo
@llvm/pr-subscribers-llvm-binary-utilities
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-llvm-ir
@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-backend-risc-v

Author: Brandon Wu (4vtomat)

Changes
[RISCV] RISCV vector calling convention (1/2)

This is the vector calling convention based on
https://github.com/riscv-non-isa/riscv-elf-psabi-doc,
the idea is to split between "scalar" callee-saved registers
and "vector" callee-saved registers. "scalar" ones remain the
original strategy, however, "vector" ones are handled together
with RVV objects.

The stack layout would be:

  |--------------------------| &lt;-- FP
  | callee-allocated save    |
  | area for register varargs|
  |--------------------------|
  | callee-saved registers   | &lt;-- scalar callee-saved
  |        (scalar)          |
  |--------------------------|
  | RVV alignment padding    |
  |--------------------------|
  | callee-saved registers   | &lt;-- vector callee-saved
  |        (vector)          |
  |--------------------------|
  | RVV objects              |
  |--------------------------|
  | padding before RVV       |
  |--------------------------|
  | scalar local variables   |
  |--------------------------| &lt;-- BP
  | variable size objects    |
  |--------------------------| &lt;-- SP

Note: This patch doesn't contain "tuple" type, e.g. vint32m1x2.
      It will be handled in https://github.com/riscv-non-isa/riscv-elf-psabi-doc (2/2).

[RISCV] Add CFI information for vector callee-saved registers

Currently the CFI offset for RVV registers are not handled entirely,
this patch add those information for either stack unwinding or
debugger to work correctly on RVV callee-saved stack object.

Patch is 176.82 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/77560.diff

137 Files Affected:

  • (modified) clang/include/clang/Basic/Attr.td (+5)
  • (modified) clang/include/clang/Basic/AttrDocs.td (+10)
  • (modified) clang/include/clang/Basic/Specifiers.h (+1)
  • (modified) clang/lib/AST/ItaniumMangle.cpp (+1)
  • (modified) clang/lib/AST/Type.cpp (+2)
  • (modified) clang/lib/AST/TypePrinter.cpp (+6)
  • (modified) clang/lib/Basic/Targets/RISCV.cpp (+11)
  • (modified) clang/lib/Basic/Targets/RISCV.h (+2)
  • (modified) clang/lib/CodeGen/CGCall.cpp (+4)
  • (modified) clang/lib/Sema/SemaDeclAttr.cpp (+7)
  • (modified) clang/lib/Sema/SemaType.cpp (+4-1)
  • (added) clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c (+27)
  • (added) clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp (+19)
  • (modified) llvm/include/llvm/AsmParser/LLToken.h (+1)
  • (modified) llvm/include/llvm/IR/CallingConv.h (+3)
  • (modified) llvm/lib/AsmParser/LLLexer.cpp (+1)
  • (modified) llvm/lib/AsmParser/LLParser.cpp (+2)
  • (modified) llvm/lib/IR/AsmWriter.cpp (+1)
  • (modified) llvm/lib/Target/RISCV/RISCVCallingConv.td (+13)
  • (modified) llvm/lib/Target/RISCV/RISCVFrameLowering.cpp (+215-39)
  • (modified) llvm/lib/Target/RISCV/RISCVFrameLowering.h (+5)
  • (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+1)
  • (modified) llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp (+15)
  • (modified) llvm/test/CodeGen/RISCV/early-clobber-tied-def-subreg-liveness.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/intrinsic-cttz-elts-vscale.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/regalloc-last-chance-recoloring-failure.ll (+2)
  • (added) llvm/test/CodeGen/RISCV/rvv-cfi-info.ll (+119)
  • (modified) llvm/test/CodeGen/RISCV/rvv/abs-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/access-fixed-objects-by-rvv.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/addi-scalable-offset.mir (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-struct.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/bitreverse-sdnode.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/bitreverse-vp.ll (+7)
  • (modified) llvm/test/CodeGen/RISCV/rvv/bswap-sdnode.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/bswap-vp.ll (+7)
  • (added) llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll (+95)
  • (modified) llvm/test/CodeGen/RISCV/rvv/calling-conv-fastcc.ll (+8)
  • (modified) llvm/test/CodeGen/RISCV/rvv/calling-conv.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/ceil-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/ctlz-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/ctpop-vp.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/cttz-vp.ll (+4)
  • (modified) llvm/test/CodeGen/RISCV/rvv/emergency-slot.mir (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/extractelt-fp.ll (+4)
  • (modified) llvm/test/CodeGen/RISCV/rvv/extractelt-int-rv32.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/extractelt-int-rv64.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-bitreverse-vp.ll (+7)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-bswap-vp.ll (+7)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-ceil-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-ctlz-vp.ll (+6)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-ctpop-vp.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-cttz-vp.ll (+6)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-floor-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp-interleave.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fshr-fshl-vp.ll (+126)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-insert-subvector.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-interleave.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-interleaved-access.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-llrint.ll (+8)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-nearbyint-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-reduction-int.ll (+4)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-rint-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-round-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-roundeven-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-roundtozero-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-setcc-fp-vp.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-setcc-int-vp.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-trunc-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vcopysign-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfma-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfmax-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfmin-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfmuladd-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfwadd.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfwmul.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vfwsub.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vpmerge.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vpscatter.ll (+4)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vscale-range.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vselect-vp.ll (+4)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmul.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmulsu.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmulu.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/floor-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fmaximum-sdnode.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fminimum-sdnode.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fpclamptosat_vec.ll (+24)
  • (modified) llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll (+12)
  • (modified) llvm/test/CodeGen/RISCV/rvv/get-vlen-debugloc.mir (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/large-rvv-stack-size.mir (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/localvar.ll (+8)
  • (modified) llvm/test/CodeGen/RISCV/rvv/memory-args.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/mgather-sdnode.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/mscatter-sdnode.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/named-vector-shuffle-reverse.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/nearbyint-vp.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/no-reserved-frame.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/reg-alloc-reserve-bp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/rint-vp.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/round-vp.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/roundeven-vp.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/roundtozero-vp.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/rvv-args-by-mem.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/setcc-fp-vp.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/setcc-int-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/strided-vpstore.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vcopysign-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-load.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vector-deinterleave.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vector-interleave-store.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vector-interleave.ll (+4)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfadd-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfdiv-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfma-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfmadd-constrained-sdnode.ll (+4)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfmadd-sdnode.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfmax-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfmin-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfmsub-constrained-sdnode.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfmul-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfmuladd-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfnmadd-constrained-sdnode.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfnmsub-constrained-sdnode.ll (+4)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfptrunc-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfsub-vp.ll (+2)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfwmacc-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfwnmacc-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vfwnmsac-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vp-reverse-int.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vpmerge-sdnode.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vpscatter-sdnode.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vpstore.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vselect-fp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll (+3)
  • (modified) llvm/test/CodeGen/RISCV/rvv/vtrunc-vp.ll (+1)
  • (modified) llvm/test/CodeGen/RISCV/rvv/zvlsseg-spill.mir (+1)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index d5eabaad488965..ea9f157df98373 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2891,6 +2891,11 @@ def M68kRTD: DeclOrTypeAttr {
   let Documentation = [M68kRTDDocs];
 }
 
+def RISCVVectorCC: DeclOrTypeAttr {
+ let Spellings = [Clang<"riscv_vector_cc">];
+ let Documentation = [RISCVVectorCCDocs];
+}
+
 def Target : InheritableAttr {
   let Spellings = [GCC<"target">];
   let Args = [StringArgument<"featuresStr">];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 5416a0cbdd0757..75359c65004a97 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -5400,6 +5400,16 @@ for clang builtin functions.
   }];
 }
 
+def RISCVVectorCCDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+The ``riscv_vector_cc`` attribute can be applied to a function. It preserves 15
+registers namely, v1-v7 and v24-v31 as callee-saved. Callers thus don't need
+to save these registers before function calls, and callees only need to save
+them only if they use them.
+ }];
+}
+
 def PreferredNameDocs : Documentation {
   let Category = DocCatDecl;
   let Content = [{
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 87f29c8ae10bd9..72a10e25c923e9 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -293,6 +293,7 @@ namespace clang {
     CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs))
     CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel))
     CC_M68kRTD,       // __attribute__((m68k_rtd))
+    CC_RISCVVectorCall, // __attribute__((riscv_vector_cc))
   };
 
   /// Checks whether the given calling convention supports variadic
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index b1678479888eb7..6af83a83c22fc7 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3442,6 +3442,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
   case CC_PreserveMost:
   case CC_PreserveAll:
   case CC_M68kRTD:
+  case CC_RISCVVectorCall:
     // FIXME: we should be mangling all of the above.
     return "";
 
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index a894d3289eb185..8895a1065d949b 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -3409,6 +3409,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
   case CC_PreserveMost: return "preserve_most";
   case CC_PreserveAll: return "preserve_all";
   case CC_M68kRTD: return "m68k_rtd";
+  case CC_RISCVVectorCall: return "riscv_vector_cc";
   }
 
   llvm_unreachable("Invalid calling convention.");
@@ -3896,6 +3897,7 @@ bool AttributedType::isCallingConv() const {
   case attr::PreserveMost:
   case attr::PreserveAll:
   case attr::M68kRTD:
+  case attr::RISCVVectorCC:
     return true;
   }
   llvm_unreachable("invalid attr kind");
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index f6941242927367..6138ea47941c7e 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1047,6 +1047,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
     case CC_M68kRTD:
       OS << " __attribute__((m68k_rtd))";
       break;
+    case CC_RISCVVectorCall:
+      OS << "__attribute__((riscv_vector_cc))";
+      break;
     }
   }
 
@@ -1885,6 +1888,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
   case attr::M68kRTD:
     OS << "m68k_rtd";
     break;
+  case attr::RISCVVectorCC:
+    OS << "riscv_vector_cc";
+    break;
   case attr::NoDeref:
     OS << "noderef";
     break;
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index daaa8639ae8358..0a5cf09040eedf 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -480,3 +480,14 @@ ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
   }
   return Ret;
 }
+
+TargetInfo::CallingConvCheckResult
+RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
+  switch (CC) {
+    default:
+      return CCCR_Warning;
+    case CC_C:
+    case CC_RISCVVectorCall:
+      return CCCR_OK;
+  }
+}
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index f98c88cd45f831..e65a6a1f127e8d 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -110,6 +110,8 @@ class RISCVTargetInfo : public TargetInfo {
 
   bool hasBFloat16Type() const override { return true; }
 
+  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
+
   bool useFP16ConversionIntrinsics() const override {
     return false;
   }
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 51a43b5f85b3cc..a099bb0efd73f6 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -73,6 +73,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
   case CC_Swift: return llvm::CallingConv::Swift;
   case CC_SwiftAsync: return llvm::CallingConv::SwiftTail;
   case CC_M68kRTD: return llvm::CallingConv::M68k_RTD;
+  case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall;
   }
 }
 
@@ -256,6 +257,9 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
   if (D->hasAttr<M68kRTDAttr>())
     return CC_M68kRTD;
 
+  if (D->hasAttr<RISCVVectorCCAttr>())
+    return CC_RISCVVectorCall;
+
   return CC_C;
 }
 
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index d059b406ef86e0..4322d2106737e8 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5235,6 +5235,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   case ParsedAttr::AT_M68kRTD:
     D->addAttr(::new (S.Context) M68kRTDAttr(S.Context, AL));
     return;
+  case ParsedAttr::AT_RISCVVectorCC:
+    D->addAttr(::new (S.Context) RISCVVectorCCAttr(S.Context, AL));
+    return;
   default:
     llvm_unreachable("unexpected attribute kind");
   }
@@ -5441,6 +5444,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
   case ParsedAttr::AT_M68kRTD:
     CC = CC_M68kRTD;
     break;
+  case ParsedAttr::AT_RISCVVectorCC:
+    CC = CC_RISCVVectorCall;
+    break;
   default: llvm_unreachable("unexpected attribute kind");
   }
 
@@ -9373,6 +9379,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
   case ParsedAttr::AT_AArch64SVEPcs:
   case ParsedAttr::AT_AMDGPUKernelCall:
   case ParsedAttr::AT_M68kRTD:
+  case ParsedAttr::AT_RISCVVectorCC:
     handleCallConvAttr(S, D, AL);
     break;
   case ParsedAttr::AT_Suppress:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index a376f20fa4f4e0..03695c907bdcd5 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -137,7 +137,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
   case ParsedAttr::AT_IntelOclBicc:                                            \
   case ParsedAttr::AT_PreserveMost:                                            \
   case ParsedAttr::AT_PreserveAll:                                             \
-  case ParsedAttr::AT_M68kRTD
+  case ParsedAttr::AT_M68kRTD:                                                 \
+  case ParsedAttr::AT_RISCVVectorCC
 
 // Function type attributes.
 #define FUNCTION_TYPE_ATTRS_CASELIST                                           \
@@ -7852,6 +7853,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
     return createSimpleAttr<PreserveAllAttr>(Ctx, Attr);
   case ParsedAttr::AT_M68kRTD:
     return createSimpleAttr<M68kRTDAttr>(Ctx, Attr);
+  case ParsedAttr::AT_RISCVVectorCC:
+    return createSimpleAttr<RISCVVectorCCAttr>(Ctx, Attr);
   }
   llvm_unreachable("unexpected attribute kind!");
 }
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
new file mode 100644
index 00000000000000..a5b59306223dfb
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c
@@ -0,0 +1,27 @@
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
+// RUN:   -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s
+
+#include <riscv_vector.h>
+
+// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @bar
+vint32m1_t __attribute__((riscv_vector_cc)) bar(vint32m1_t input);
+vint32m1_t test_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
+  vint32m1_t ret;
+  vint32m1_t val;
+  val = __riscv_vle32_v_i32m1(base, vl);
+  ret = bar(input);
+  __riscv_vse32_v_i32m1(base, val, vl);
+  return ret;
+}
+
+// CHECK-LLVM: call <vscale x 2 x i32> @baz
+vint32m1_t baz(vint32m1_t input);
+vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {
+  vint32m1_t ret;
+  vint32m1_t val;
+  val = __riscv_vle32_v_i32m1(base, vl);
+  ret = baz(input);
+  __riscv_vse32_v_i32m1(base, val, vl);
+  return ret;
+}
diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp
new file mode 100644
index 00000000000000..22761146093fde
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp
@@ -0,0 +1,19 @@
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 %s -triple riscv64 -target-feature +v -verify
+
+__attribute__((riscv_vector_cc)) int var; // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'int'}}
+
+__attribute__((riscv_vector_cc)) void func();
+__attribute__((riscv_vector_cc(1))) void func_invalid(); // expected-error {{'riscv_vector_cc' attribute takes no arguments}}
+
+void test_no_attribute(int); // expected-note {{previous declaration is here}}
+void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}}
+
+class test_cc {
+  __attribute__((riscv_vector_cc)) void member_func();
+};
+
+void test_lambda() {
+  __attribute__((riscv_vector_cc)) auto lambda = []() { // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'auto'}}
+  };
+}
diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h
index 147cf56c821aa1..f6c2e7339fb1b2 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -179,6 +179,7 @@ enum Kind {
   kw_tailcc,
   kw_m68k_rtdcc,
   kw_graalcc,
+  kw_riscv_vector_cc,
 
   // Attributes:
   kw_attributes,
diff --git a/llvm/include/llvm/IR/CallingConv.h b/llvm/include/llvm/IR/CallingConv.h
index 3a522c239ad59e..f20f2c4ccb781b 100644
--- a/llvm/include/llvm/IR/CallingConv.h
+++ b/llvm/include/llvm/IR/CallingConv.h
@@ -251,6 +251,9 @@ namespace CallingConv {
     /// Used by GraalVM. Two additional registers are reserved.
     GRAAL = 107,
 
+    /// Calling convention used for RISC-V V-extension.
+    RISCV_VectorCall = 108,
+
     /// The highest possible ID. Must be some 2^k - 1.
     MaxID = 1023
   };
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index c8da3efbb68aff..b4ddecf02d265b 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -636,6 +636,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(tailcc);
   KEYWORD(m68k_rtdcc);
   KEYWORD(graalcc);
+  KEYWORD(riscv_vector_cc);
 
   KEYWORD(cc);
   KEYWORD(c);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index fb9e1ba875e1fa..bcdbb75abdd7c0 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -2005,6 +2005,7 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) {
 ///   ::= 'tailcc'
 ///   ::= 'm68k_rtdcc'
 ///   ::= 'graalcc'
+///   ::= 'riscv_vector_cc'
 ///   ::= 'cc' UINT
 ///
 bool LLParser::parseOptionalCallingConv(unsigned &CC) {
@@ -2074,6 +2075,7 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) {
   case lltok::kw_tailcc:         CC = CallingConv::Tail; break;
   case lltok::kw_m68k_rtdcc:     CC = CallingConv::M68k_RTD; break;
   case lltok::kw_graalcc:        CC = CallingConv::GRAAL; break;
+  case lltok::kw_riscv_vector_cc:CC = CallingConv::RISCV_VectorCall; break;
   case lltok::kw_cc: {
       Lex.Lex();
       return parseUInt32(CC);
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 278cdfce411050..119092e5c61081 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -362,6 +362,7 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
   case CallingConv::AMDGPU_KERNEL: Out << "amdgpu_kernel"; break;
   case CallingConv::AMDGPU_Gfx:    Out << "amdgpu_gfx"; break;
   case CallingConv::M68k_RTD:      Out << "m68k_rtdcc"; break;
+  case CallingConv::RISCV_VectorCall: Out << "riscv_vector_cc"; break;
   }
 }
 
diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.td b/llvm/lib/Target/RISCV/RISCVCallingConv.td
index 3dd0b372382865..25e54044aa6d61 100644
--- a/llvm/lib/Target/RISCV/RISCVCallingConv.td
+++ b/llvm/lib/Target/RISCV/RISCVCallingConv.td
@@ -24,6 +24,19 @@ def CSR_ILP32D_LP64D
     : CalleeSavedRegs<(add CSR_ILP32_LP64,
                        F8_D, F9_D, (sequence "F%u_D", 18, 27))>;
 
+defvar CSR_V = (add (sequence "V%u", 1, 7), (sequence "V%u", 24, 31),
+                     V2M2, V4M2, V6M2, V24M2, V26M2, V28M2, V30M2,
+                     V4M4, V24M4, V28M4, V24M8);
+
+def CSR_ILP32_LP64_V
+    : CalleeSavedRegs<(add CSR_ILP32_LP64, CSR_V)>;
+
+def CSR_ILP32F_LP64F_V
+    : CalleeSavedRegs<(add CSR_ILP32F_LP64F, CSR_V)>;
+
+def CSR_ILP32D_LP64D_V
+    : CalleeSavedRegs<(add CSR_ILP32D_LP64D, CSR_V)>;
+
 // Needed for implementation of RISCVRegisterInfo::getNoPreservedMask()
 def CSR_NoRegs : CalleeSavedRegs<(add)>;
 
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 8dfea6d3862057..ae51dbdb92ad3e 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -365,6 +365,21 @@ getUnmanagedCSI(const MachineFunction &MF,
   return NonLibcallCSI;
 }
 
+static SmallVector<CalleeSavedInfo, 8>
+getRVVCalleeSavedInfo(const MachineFunction &MF,
+                      const std::vector<CalleeSavedInfo> &CSI) {
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  SmallVector<CalleeSavedInfo, 8> RVVCSI;
+
+  for (auto &CS : CSI) {
+    int FI = CS.getFrameIdx();
+    if (FI >= 0 && MFI.getStackID(FI) == TargetStackID::ScalableVector)
+      RVVCSI.push_back(CS);
+  }
+
+  return RVVCSI;
+}
+
 void RISCVFrameLowering::adjustStackForRVV(MachineFunction &MF,
                                            MachineBasicBlock &MBB,
                                            MachineBasicBlock::iterator MBBI,
@@ -397,6 +412,32 @@ void RISCVFrameLowering::adjustStackForRVV(MachineFunction &MF,
                Flag, getStackAlign());
 }
 
+static void appendScalableVectorExpression(SmallVectorImpl<char> &Expr,
+                                           int FixedOffset, int ScalableOffset,
+                                           unsigned DwarfVlenb,
+                                           llvm::raw_string_ostream &Comment) {
+  uint8_t buffer[16];
+  if (FixedOffset) {
+    Expr.push_back(dwarf::DW_OP_consts);
+    Expr.append(buffer, buffer + encodeSLEB128(FixedOffset, buffer));
+    Expr.push_back((uint8_t)dwarf::DW_OP_plus);
+    Comment << (FixedOffset < 0 ? " - " : " + ") << std::abs(FixedOffset);
+  }
+
+  Expr.push_back((uint8_t)dwarf::DW_OP_consts);
+  Expr.append(buffer, buffer + encodeSLEB128(ScalableOffset, buffer));
+
+  Expr.push_back((uint8_t)dwarf::DW_OP_bregx);
+  Expr.append(buffer, buffer + encodeULEB128(DwarfVlenb, buffer));
+  Expr.push_back(0);
+
+  Expr.push_back((uint8_t)dwarf::DW_OP_mul);
+  Expr.push_back((uint8_t)dwarf::DW_OP_plus);
+
+  Comment << (ScalableOffset < 0 ? " - " : " + ") << std::abs(ScalableOffset)
+          << " * vlenb";
+}
+
 static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI,
                                                Register Reg,
                                                uint64_t FixedOffset,
@@ -414,29 +455,40 @@ static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI,
   else
     Comment << printReg(Reg, &TRI);
 
-  uint8_t buffer[16];
-  if (FixedOffset) {
-    Expr.push_back(dwarf::DW_OP_consts);
-    Expr.append(buffer, buffer + encodeSLEB128(FixedOffset, buffer));
-    Expr.push_back((uint8_t)dwarf::DW_OP_plus);
-    Comment << " + " << FixedOffset;
-  }
+  appendScalableVectorExpression(
+      Expr, FixedOffset, ScalableOffset,
+      TRI.getDwarfRegNum(RISCV::VLENB, true), Comment);
 
-  Expr.push_back((uint8_t)dwarf::DW_OP_consts);
-  Expr.append(buffer, buffer + encodeSLEB128(ScalableOffset, buffer));
+  SmallString<64> DefCfaExpr;
+  uint8_t buffer[16];
+  DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
+  DefCfaExpr.append(buffer, buffer + encodeULEB128(Expr.size(), buffer));
+  DefCfaExpr.append(Expr.str());
 
-  unsigned DwarfVlenb = TRI.getDwarfRegNum(RISCV::VLENB, true);
-  Expr.push_back((uint8_t)dwarf::DW_OP_bregx);
-  Expr.append(buffer, buffer + encodeULEB128(DwarfVlenb, buffer));
-  Expr.push_back(0);
+  return MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str(), SMLoc(),
+                                        Comment.str());
+}
 
-  Expr.push_back((uint8_t)dwarf::DW_OP_mul);
-  Expr.push_back((uint8_t)dwarf::DW_OP_plus);
+static MCCFIInstruction createDefCFAOffset(const TargetRegisterInfo &TRI,
+                                           Register Reg,
+                                           uint64_t FixedOffset,
+                                           uint64_t ScalableOffset) {
+  assert(ScalableOffset != 0 && "Did not need to adjust CFA for RVV");
+  SmallString<64> Expr;
+  std::string CommentBuffer;
+  llvm::raw_string_ostream Comment(CommentBuffer);
+  Comment << printReg(Reg, &TRI) << "  @ cfa";
 
-  Comment << " + " << ScalableOffset << " * vlenb";
+  // Build up the expression (FixedOffset + ScalableOffset * VLENB).
+  appendScalableVectorExpression(
+      Expr, FixedOffset, ScalableOffset,
+      TRI.getDwarfRegNum(RISCV::VLENB, true), Comment);
 
   SmallString<64> DefCfaExpr;
-  DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
+  uint8_t buffer[16];
+  unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
+  DefCfaExpr.push_back(dwarf::DW_CFA_expression);
+  DefCfaExpr.append(buffer, buffer + encodeULEB128(DwarfReg, buffer));
   DefCfaExpr.append(buffer, buffer + encodeULEB128(Expr.size(), buffer));
   DefCfaExpr.append(Expr.str());
 
@@ -563,6 +615,10 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
   // directives.
   for (const auto &Entry : CSI) {
     int FrameIdx = Entry.getFrameIdx();
+    if (FrameIdx >=0 &&
+        MFI.getStackID(FrameIdx) == TargetStackID::ScalableVector)
+      continue;
+
     int64_t Offset;
     // Offsets for objects with fixed locations (IE: those saved by libcall) are
     // simply calculated from the frame index.
@@ -638,6 +694,9 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
           .addCFIIndex(CFIIndex)
           .setMIFlag(MachineInstr::FrameSetup);
     }
+
+    std::advance(MBBI, getRVVCalleeSavedInfo(MF, CSI).size());
+    emitCalleeSavedRVVPrologCFI(MBB, MBBI, hasFP(MF));
   }
 
   if (hasFP(MF)) {
@@ -712,7 +771,7 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
 
   const auto &CSI = getUnmanagedCSI(MF, MFI.getCalleeSavedInfo());
 
-  // Skip to before the restores of callee-saved registers
+  // Skip to before the restores of scalar callee-saved registers
   // FIXME: assumes exactly one instruction is used to restore each
   // callee-saved register.
   auto LastFrameDestroy = MBBI;
@@ -724,6 +783,9 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
   uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize();
   uint64_t RVVStackSize = RVFI->getRVVStackSize();
 
+  if (RVVStackSize)
+    emitCalleeSavedRVVEpilogCFI(MBB, LastFrameDestroy);
+
   // Restore the stack pointer using the value of the frame pointer. Only
   // necessary if the stack pointer was modified, me...
[truncated]

Copy link

github-actions bot commented Jan 10, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@kito-cheng kito-cheng requested review from asb and preames January 19, 2024 07:06
@kito-cheng kito-cheng changed the title riscv vector cc [RISCV] RISCV vector calling convention (1/2) Jan 19, 2024
@4vtomat
Copy link
Member Author

4vtomat commented Feb 7, 2024

The latest fixup commit add [[riscv::riscv_vector]] supports for C23 and C++11.

@4vtomat
Copy link
Member Author

4vtomat commented Feb 21, 2024

Rebase

@4vtomat
Copy link
Member Author

4vtomat commented Mar 1, 2024

ping

@sunshaoce
Copy link
Contributor

I tried compiling it and then got two warnings.

llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp:1408:11: warning: enumeration value 'CC_RISCVVectorCall' not handled in switch [-Wswitch]
 1408 |   switch (CC) {
      |           ^~
1 warning generated.
[3629/3776] Building CXX object tools/clang/tools/libclang/CMakeFiles/libclang.dir/CXType.cpp.o
llvm-project/clang/tools/libclang/CXType.cpp:662:13: warning: enumeration value 'CC_RISCVVectorCall' not handled in switch [-Wswitch]
  662 |     switch (FD->getCallConv()) {
      |             ^~~~~~~~~~~~~~~~~
1 warning generated.

@4vtomat
Copy link
Member Author

4vtomat commented Mar 2, 2024

I tried compiling it and then got two warnings.

llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp:1408:11: warning: enumeration value 'CC_RISCVVectorCall' not handled in switch [-Wswitch]
 1408 |   switch (CC) {
      |           ^~
1 warning generated.
[3629/3776] Building CXX object tools/clang/tools/libclang/CMakeFiles/libclang.dir/CXType.cpp.o
llvm-project/clang/tools/libclang/CXType.cpp:662:13: warning: enumeration value 'CC_RISCVVectorCall' not handled in switch [-Wswitch]
  662 |     switch (FD->getCallConv()) {
      |             ^~~~~~~~~~~~~~~~~
1 warning generated.

I forgot to add these cases for CC_RISCVVectorCall lol, thanks~

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

This is the vector calling convention based on
https://github.com/riscv-non-isa/riscv-elf-psabi-doc,
the idea is to split between "scalar" callee-saved registers
and "vector" callee-saved registers. "scalar" ones remain the
original strategy, however, "vector" ones are handled together
with RVV objects.

The stack layout would be:

  |--------------------------| <-- FP
  | callee-allocated save    |
  | area for register varargs|
  |--------------------------|
  | callee-saved registers   | <-- scalar callee-saved
  |        (scalar)          |
  |--------------------------|
  | RVV alignment padding    |
  |--------------------------|
  | callee-saved registers   | <-- vector callee-saved
  |        (vector)          |
  |--------------------------|
  | RVV objects              |
  |--------------------------|
  | padding before RVV       |
  |--------------------------|
  | scalar local variables   |
  |--------------------------| <-- BP
  | variable size objects    |
  |--------------------------| <-- SP

Note: This patch doesn't contain "tuple" type, e.g. vint32m1x2.
      It will be handled in https://github.com/riscv-non-isa/riscv-elf-psabi-doc (2/2).

Differential Revision: https://reviews.llvm.org/D154576
@4vtomat
Copy link
Member Author

4vtomat commented Mar 27, 2024

Rebase and squash, I think it should be separated into 2 commits, I'll create another commit for CFI one.

@4vtomat 4vtomat merged commit 9189660 into llvm:main Mar 27, 2024
@4vtomat 4vtomat deleted the riscv_vector_cc branch March 27, 2024 15:03
delcypher pushed a commit to swiftlang/llvm-project that referenced this pull request Mar 27, 2024
…] RISCV vector calling convention (1/2) (llvm#77560)))

Merge commit '91896607ffb8' from llvm.org/main into next

Conflicts:
	llvm/include/llvm/BinaryFormat/Dwarf.def

rdar://125488167
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category debuginfo llvm:binary-utilities llvm:ir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants