Skip to content

[RISCV][VLS] Support RISCV VLS calling convention #100346

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 12 commits into from
Mar 3, 2025
Merged
12 changes: 12 additions & 0 deletions clang/include/clang-c/Index.h
Original file line number Diff line number Diff line change
Expand Up @@ -3053,6 +3053,18 @@ enum CXCallingConv {
CXCallingConv_M68kRTD = 19,
CXCallingConv_PreserveNone = 20,
CXCallingConv_RISCVVectorCall = 21,
CXCallingConv_RISCVVLSCall_32 = 22,
CXCallingConv_RISCVVLSCall_64 = 23,
CXCallingConv_RISCVVLSCall_128 = 24,
CXCallingConv_RISCVVLSCall_256 = 25,
CXCallingConv_RISCVVLSCall_512 = 26,
CXCallingConv_RISCVVLSCall_1024 = 27,
CXCallingConv_RISCVVLSCall_2048 = 28,
CXCallingConv_RISCVVLSCall_4096 = 29,
CXCallingConv_RISCVVLSCall_8192 = 30,
CXCallingConv_RISCVVLSCall_16384 = 31,
CXCallingConv_RISCVVLSCall_32768 = 32,
CXCallingConv_RISCVVLSCall_65536 = 33,

CXCallingConv_Invalid = 100,
CXCallingConv_Unexposed = 200
Expand Down
21 changes: 9 additions & 12 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -1946,7 +1946,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
/// Extra information which affects how the function is called, like
/// regparm and the calling convention.
LLVM_PREFERRED_TYPE(CallingConv)
unsigned ExtInfo : 13;
unsigned ExtInfo : 14;

/// The ref-qualifier associated with a \c FunctionProtoType.
///
Expand Down Expand Up @@ -4437,19 +4437,16 @@ class FunctionType : public Type {
// Type::FunctionTypeBitfields::ExtInfo as well.

// | CC |noreturn|produces|nocallersavedregs|regparm|nocfcheck|cmsenscall|
// |0 .. 4| 5 | 6 | 7 |8 .. 10| 11 | 12 |
// |0 .. 5| 6 | 7 | 8 |9 .. 11| 12 | 13 |
//
// regparm is either 0 (no regparm attribute) or the regparm value+1.
enum { CallConvMask = 0x1F };
enum { NoReturnMask = 0x20 };
enum { ProducesResultMask = 0x40 };
enum { NoCallerSavedRegsMask = 0x80 };
enum {
RegParmMask = 0x700,
RegParmOffset = 8
};
enum { NoCfCheckMask = 0x800 };
enum { CmseNSCallMask = 0x1000 };
enum { CallConvMask = 0x3F };
enum { NoReturnMask = 0x40 };
enum { ProducesResultMask = 0x80 };
enum { NoCallerSavedRegsMask = 0x100 };
enum { RegParmMask = 0xe00, RegParmOffset = 9 };
enum { NoCfCheckMask = 0x1000 };
enum { CmseNSCallMask = 0x2000 };
uint16_t Bits = CC_C;

ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -3285,6 +3285,14 @@ def RISCVVectorCC: DeclOrTypeAttr, TargetSpecificAttr<TargetRISCV> {
let Documentation = [RISCVVectorCCDocs];
}

def RISCVVLSCC: DeclOrTypeAttr, TargetSpecificAttr<TargetRISCV> {
let Spellings = [CXX11<"riscv", "vls_cc">,
C23<"riscv", "vls_cc">,
Clang<"riscv_vls_cc">];
let Args = [UnsignedArgument<"VectorWidth", /*opt*/1>];
let Documentation = [RISCVVLSCCDocs];
}

def Target : InheritableAttr {
let Spellings = [GCC<"target">];
let Args = [StringArgument<"featuresStr">];
Expand Down
11 changes: 11 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -6061,6 +6061,17 @@ them if they use them.
}];
}

def RISCVVLSCCDocs : Documentation {
let Category = DocCatCallingConvs;
let Heading = "riscv::vls_cc, riscv_vls_cc, clang::riscv_vls_cc";
let Content = [{
The ``riscv_vls_cc`` attribute can be applied to a function. Functions
declared with this attribute will utilize the standard fixed-length vector
calling convention variant instead of the default calling convention defined by
the ABI. This variant aims to pass fixed-length vectors via vector registers,
if possible, rather than through general-purpose registers.}];
}

def PreferredNameDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
Expand Down
61 changes: 37 additions & 24 deletions clang/include/clang/Basic/Specifiers.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,30 +276,43 @@ namespace clang {

/// CallingConv - Specifies the calling convention that a function uses.
enum CallingConv {
CC_C, // __attribute__((cdecl))
CC_X86StdCall, // __attribute__((stdcall))
CC_X86FastCall, // __attribute__((fastcall))
CC_X86ThisCall, // __attribute__((thiscall))
CC_X86VectorCall, // __attribute__((vectorcall))
CC_X86Pascal, // __attribute__((pascal))
CC_Win64, // __attribute__((ms_abi))
CC_X86_64SysV, // __attribute__((sysv_abi))
CC_X86RegCall, // __attribute__((regcall))
CC_AAPCS, // __attribute__((pcs("aapcs")))
CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
CC_SpirFunction, // default for OpenCL functions on SPIR target
CC_OpenCLKernel, // inferred for OpenCL kernels
CC_Swift, // __attribute__((swiftcall))
CC_SwiftAsync, // __attribute__((swiftasynccall))
CC_PreserveMost, // __attribute__((preserve_most))
CC_PreserveAll, // __attribute__((preserve_all))
CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs))
CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel))
CC_M68kRTD, // __attribute__((m68k_rtd))
CC_PreserveNone, // __attribute__((preserve_none))
CC_RISCVVectorCall, // __attribute__((riscv_vector_cc))
CC_C, // __attribute__((cdecl))
CC_X86StdCall, // __attribute__((stdcall))
CC_X86FastCall, // __attribute__((fastcall))
CC_X86ThisCall, // __attribute__((thiscall))
CC_X86VectorCall, // __attribute__((vectorcall))
CC_X86Pascal, // __attribute__((pascal))
CC_Win64, // __attribute__((ms_abi))
CC_X86_64SysV, // __attribute__((sysv_abi))
CC_X86RegCall, // __attribute__((regcall))
CC_AAPCS, // __attribute__((pcs("aapcs")))
CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
CC_SpirFunction, // default for OpenCL functions on SPIR target
CC_OpenCLKernel, // inferred for OpenCL kernels
CC_Swift, // __attribute__((swiftcall))
CC_SwiftAsync, // __attribute__((swiftasynccall))
CC_PreserveMost, // __attribute__((preserve_most))
CC_PreserveAll, // __attribute__((preserve_all))
CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs))
CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel))
CC_M68kRTD, // __attribute__((m68k_rtd))
CC_PreserveNone, // __attribute__((preserve_none))
CC_RISCVVectorCall, // __attribute__((riscv_vector_cc))
CC_RISCVVLSCall_32, // __attribute__((riscv_vls_cc(32)))
CC_RISCVVLSCall_64, // __attribute__((riscv_vls_cc(64)))
CC_RISCVVLSCall_128, // __attribute__((riscv_vls_cc)) or
// __attribute__((riscv_vls_cc(128)))
CC_RISCVVLSCall_256, // __attribute__((riscv_vls_cc(256)))
CC_RISCVVLSCall_512, // __attribute__((riscv_vls_cc(512)))
CC_RISCVVLSCall_1024, // __attribute__((riscv_vls_cc(1024)))
CC_RISCVVLSCall_2048, // __attribute__((riscv_vls_cc(2048)))
CC_RISCVVLSCall_4096, // __attribute__((riscv_vls_cc(4096)))
CC_RISCVVLSCall_8192, // __attribute__((riscv_vls_cc(8192)))
CC_RISCVVLSCall_16384, // __attribute__((riscv_vls_cc(16384)))
CC_RISCVVLSCall_32768, // __attribute__((riscv_vls_cc(32768)))
CC_RISCVVLSCall_65536, // __attribute__((riscv_vls_cc(65536)))
};

/// Checks whether the given calling convention supports variadic
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3489,6 +3489,20 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
case CC_M68kRTD:
case CC_PreserveNone:
case CC_RISCVVectorCall:
#define CC_VLS_CASE(ABI_VLEN) case CC_RISCVVLSCall_##ABI_VLEN:
CC_VLS_CASE(32)
CC_VLS_CASE(64)
CC_VLS_CASE(128)
CC_VLS_CASE(256)
CC_VLS_CASE(512)
CC_VLS_CASE(1024)
CC_VLS_CASE(2048)
CC_VLS_CASE(4096)
CC_VLS_CASE(8192)
CC_VLS_CASE(16384)
CC_VLS_CASE(32768)
CC_VLS_CASE(65536)
#undef CC_VLS_CASE
// FIXME: we should be mangling all of the above.
return "";

Expand Down
16 changes: 16 additions & 0 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3561,6 +3561,21 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_PreserveNone: return "preserve_none";
// clang-format off
case CC_RISCVVectorCall: return "riscv_vector_cc";
#define CC_VLS_CASE(ABI_VLEN) \
case CC_RISCVVLSCall_##ABI_VLEN: return "riscv_vls_cc(" #ABI_VLEN ")";
CC_VLS_CASE(32)
CC_VLS_CASE(64)
CC_VLS_CASE(128)
CC_VLS_CASE(256)
CC_VLS_CASE(512)
CC_VLS_CASE(1024)
CC_VLS_CASE(2048)
CC_VLS_CASE(4096)
CC_VLS_CASE(8192)
CC_VLS_CASE(16384)
CC_VLS_CASE(32768)
CC_VLS_CASE(65536)
#undef CC_VLS_CASE
// clang-format on
}

Expand Down Expand Up @@ -4228,6 +4243,7 @@ bool AttributedType::isCallingConv() const {
case attr::M68kRTD:
case attr::PreserveNone:
case attr::RISCVVectorCC:
case attr::RISCVVLSCC:
return true;
}
llvm_unreachable("invalid attr kind");
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,23 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
case CC_RISCVVectorCall:
OS << "__attribute__((riscv_vector_cc))";
break;
#define CC_VLS_CASE(ABI_VLEN) \
case CC_RISCVVLSCall_##ABI_VLEN: \
OS << "__attribute__((riscv_vls_cc" #ABI_VLEN "))"; \
break;
CC_VLS_CASE(32)
CC_VLS_CASE(64)
CC_VLS_CASE(128)
CC_VLS_CASE(256)
CC_VLS_CASE(512)
CC_VLS_CASE(1024)
CC_VLS_CASE(2048)
CC_VLS_CASE(4096)
CC_VLS_CASE(8192)
CC_VLS_CASE(16384)
CC_VLS_CASE(32768)
CC_VLS_CASE(65536)
#undef CC_VLS_CASE
}
}

Expand Down Expand Up @@ -2064,6 +2081,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::RISCVVectorCC:
OS << "riscv_vector_cc";
break;
case attr::RISCVVLSCC:
OS << "riscv_vls_cc";
break;
case attr::NoDeref:
OS << "noderef";
break;
Expand Down
12 changes: 12 additions & 0 deletions clang/lib/Basic/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,18 @@ RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
return CCCR_Warning;
case CC_C:
case CC_RISCVVectorCall:
case CC_RISCVVLSCall_32:
case CC_RISCVVLSCall_64:
case CC_RISCVVLSCall_128:
case CC_RISCVVLSCall_256:
case CC_RISCVVLSCall_512:
case CC_RISCVVLSCall_1024:
case CC_RISCVVLSCall_2048:
case CC_RISCVVLSCall_4096:
case CC_RISCVVLSCall_8192:
case CC_RISCVVLSCall_16384:
case CC_RISCVVLSCall_32768:
case CC_RISCVVLSCall_65536:
return CCCR_OK;
}
}
Expand Down
50 changes: 50 additions & 0 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,22 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
// clang-format off
case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall;
// clang-format on
#define CC_VLS_CASE(ABI_VLEN) \
case CC_RISCVVLSCall_##ABI_VLEN: \
return llvm::CallingConv::RISCV_VLSCall_##ABI_VLEN;
CC_VLS_CASE(32)
CC_VLS_CASE(64)
CC_VLS_CASE(128)
CC_VLS_CASE(256)
CC_VLS_CASE(512)
CC_VLS_CASE(1024)
CC_VLS_CASE(2048)
CC_VLS_CASE(4096)
CC_VLS_CASE(8192)
CC_VLS_CASE(16384)
CC_VLS_CASE(32768)
CC_VLS_CASE(65536)
#undef CC_VLS_CASE
}
}

Expand Down Expand Up @@ -266,6 +282,29 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
if (D->hasAttr<RISCVVectorCCAttr>())
return CC_RISCVVectorCall;

if (RISCVVLSCCAttr *PCS = D->getAttr<RISCVVLSCCAttr>()) {
switch (PCS->getVectorWidth()) {
default:
llvm_unreachable("Invalid RISC-V VLS ABI VLEN");
#define CC_VLS_CASE(ABI_VLEN) \
case ABI_VLEN: \
return CC_RISCVVLSCall_##ABI_VLEN;
CC_VLS_CASE(32)
CC_VLS_CASE(64)
CC_VLS_CASE(128)
CC_VLS_CASE(256)
CC_VLS_CASE(512)
CC_VLS_CASE(1024)
CC_VLS_CASE(2048)
CC_VLS_CASE(4096)
CC_VLS_CASE(8192)
CC_VLS_CASE(16384)
CC_VLS_CASE(32768)
CC_VLS_CASE(65536)
#undef CC_VLS_CASE
}
}

return CC_C;
}

Expand Down Expand Up @@ -3235,6 +3274,17 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
}
}

// Struct of fixed-length vectors and struct of array of fixed-length
// vector in VLS calling convention are coerced to vector tuple
// type(represented as TargetExtType) and scalable vector type
// respectively, they're no longer handled as struct.
if (ArgI.isDirect() && isa<llvm::StructType>(ConvertType(Ty)) &&
(isa<llvm::TargetExtType>(ArgI.getCoerceToType()) ||
isa<llvm::ScalableVectorType>(ArgI.getCoerceToType()))) {
ArgVals.push_back(ParamValue::forDirect(AI));
break;
}

llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg),
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,21 @@ static unsigned getDwarfCC(CallingConv CC) {
return llvm::dwarf::DW_CC_LLVM_PreserveNone;
case CC_RISCVVectorCall:
return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall;
#define CC_VLS_CASE(ABI_VLEN) case CC_RISCVVLSCall_##ABI_VLEN:
CC_VLS_CASE(32)
CC_VLS_CASE(64)
CC_VLS_CASE(128)
CC_VLS_CASE(256)
CC_VLS_CASE(512)
CC_VLS_CASE(1024)
CC_VLS_CASE(2048)
CC_VLS_CASE(4096)
CC_VLS_CASE(8192)
CC_VLS_CASE(16384)
CC_VLS_CASE(32768)
CC_VLS_CASE(65536)
#undef CC_VLS_CASE
return llvm::dwarf::DW_CC_LLVM_RISCVVLSCall;
}
return 0;
}
Expand Down
Loading