Skip to content

Commit c804e86

Browse files
authored
[RISCV][VLS] Support RISCV VLS calling convention (#100346)
This patch adds a function attribute `riscv_vls_cc` for RISCV VLS calling convention which takes 0 or 1 argument, the argument is the `ABI_VLEN` which is the `VLEN` for passing the fixed-vector arguments, it wraps the argument as a scalable vector(VLA) using the `ABI_VLEN` and uses the corresponding mechanism to handle it. The range of `ABI_VLEN` is [32, 65536], if not specified, the default value is 128. Here is an example of VLS argument passing: Non-VLS call: ``` void original_call(__attribute__((vector_size(16))) int arg) {} => define void @original_call(i128 noundef %arg) { entry: ... ret void } ``` VLS call: ``` void __attribute__((riscv_vls_cc(256))) vls_call(__attribute__((vector_size(16))) int arg) {} => define riscv_vls_cc void @vls_call(<vscale x 1 x i32> %arg) { entry: ... ret void } } ``` The first Non-VLS call passes generic vector argument of 16 bytes by flattened integer. On the contrary, the VLS call uses `ABI_VLEN=256` which wraps the vector to <vscale x 1 x i32> where the number of scalable vector elements is calaulated by: `ORIG_ELTS * RVV_BITS_PER_BLOCK / ABI_VLEN`. Note: ORIG_ELTS = Vector Size / Type Size = 128 / 32 = 4. PsABI PR: riscv-non-isa/riscv-elf-psabi-doc#418 C-API PR: riscv-non-isa/riscv-c-api-doc#68
1 parent 98a640a commit c804e86

28 files changed

+1121
-60
lines changed

clang/include/clang-c/Index.h

+12
Original file line numberDiff line numberDiff line change
@@ -3061,6 +3061,18 @@ enum CXCallingConv {
30613061
CXCallingConv_M68kRTD = 19,
30623062
CXCallingConv_PreserveNone = 20,
30633063
CXCallingConv_RISCVVectorCall = 21,
3064+
CXCallingConv_RISCVVLSCall_32 = 22,
3065+
CXCallingConv_RISCVVLSCall_64 = 23,
3066+
CXCallingConv_RISCVVLSCall_128 = 24,
3067+
CXCallingConv_RISCVVLSCall_256 = 25,
3068+
CXCallingConv_RISCVVLSCall_512 = 26,
3069+
CXCallingConv_RISCVVLSCall_1024 = 27,
3070+
CXCallingConv_RISCVVLSCall_2048 = 28,
3071+
CXCallingConv_RISCVVLSCall_4096 = 29,
3072+
CXCallingConv_RISCVVLSCall_8192 = 30,
3073+
CXCallingConv_RISCVVLSCall_16384 = 31,
3074+
CXCallingConv_RISCVVLSCall_32768 = 32,
3075+
CXCallingConv_RISCVVLSCall_65536 = 33,
30643076

30653077
CXCallingConv_Invalid = 100,
30663078
CXCallingConv_Unexposed = 200

clang/include/clang/AST/Type.h

+9-12
Original file line numberDiff line numberDiff line change
@@ -1946,7 +1946,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
19461946
/// Extra information which affects how the function is called, like
19471947
/// regparm and the calling convention.
19481948
LLVM_PREFERRED_TYPE(CallingConv)
1949-
unsigned ExtInfo : 13;
1949+
unsigned ExtInfo : 14;
19501950

19511951
/// The ref-qualifier associated with a \c FunctionProtoType.
19521952
///
@@ -4438,19 +4438,16 @@ class FunctionType : public Type {
44384438
// Type::FunctionTypeBitfields::ExtInfo as well.
44394439

44404440
// | CC |noreturn|produces|nocallersavedregs|regparm|nocfcheck|cmsenscall|
4441-
// |0 .. 4| 5 | 6 | 7 |8 .. 10| 11 | 12 |
4441+
// |0 .. 5| 6 | 7 | 8 |9 .. 11| 12 | 13 |
44424442
//
44434443
// regparm is either 0 (no regparm attribute) or the regparm value+1.
4444-
enum { CallConvMask = 0x1F };
4445-
enum { NoReturnMask = 0x20 };
4446-
enum { ProducesResultMask = 0x40 };
4447-
enum { NoCallerSavedRegsMask = 0x80 };
4448-
enum {
4449-
RegParmMask = 0x700,
4450-
RegParmOffset = 8
4451-
};
4452-
enum { NoCfCheckMask = 0x800 };
4453-
enum { CmseNSCallMask = 0x1000 };
4444+
enum { CallConvMask = 0x3F };
4445+
enum { NoReturnMask = 0x40 };
4446+
enum { ProducesResultMask = 0x80 };
4447+
enum { NoCallerSavedRegsMask = 0x100 };
4448+
enum { RegParmMask = 0xe00, RegParmOffset = 9 };
4449+
enum { NoCfCheckMask = 0x1000 };
4450+
enum { CmseNSCallMask = 0x2000 };
44544451
uint16_t Bits = CC_C;
44554452

44564453
ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}

clang/include/clang/Basic/Attr.td

+8
Original file line numberDiff line numberDiff line change
@@ -3316,6 +3316,14 @@ def RISCVVectorCC: DeclOrTypeAttr, TargetSpecificAttr<TargetRISCV> {
33163316
let Documentation = [RISCVVectorCCDocs];
33173317
}
33183318

3319+
def RISCVVLSCC: DeclOrTypeAttr, TargetSpecificAttr<TargetRISCV> {
3320+
let Spellings = [CXX11<"riscv", "vls_cc">,
3321+
C23<"riscv", "vls_cc">,
3322+
Clang<"riscv_vls_cc">];
3323+
let Args = [UnsignedArgument<"VectorWidth", /*opt*/1>];
3324+
let Documentation = [RISCVVLSCCDocs];
3325+
}
3326+
33193327
def Target : InheritableAttr {
33203328
let Spellings = [GCC<"target">];
33213329
let Args = [StringArgument<"featuresStr">];

clang/include/clang/Basic/AttrDocs.td

+11
Original file line numberDiff line numberDiff line change
@@ -6214,6 +6214,17 @@ them if they use them.
62146214
}];
62156215
}
62166216

6217+
def RISCVVLSCCDocs : Documentation {
6218+
let Category = DocCatCallingConvs;
6219+
let Heading = "riscv::vls_cc, riscv_vls_cc, clang::riscv_vls_cc";
6220+
let Content = [{
6221+
The ``riscv_vls_cc`` attribute can be applied to a function. Functions
6222+
declared with this attribute will utilize the standard fixed-length vector
6223+
calling convention variant instead of the default calling convention defined by
6224+
the ABI. This variant aims to pass fixed-length vectors via vector registers,
6225+
if possible, rather than through general-purpose registers.}];
6226+
}
6227+
62176228
def PreferredNameDocs : Documentation {
62186229
let Category = DocCatDecl;
62196230
let Content = [{

clang/include/clang/Basic/Specifiers.h

+37-24
Original file line numberDiff line numberDiff line change
@@ -276,30 +276,43 @@ namespace clang {
276276

277277
/// CallingConv - Specifies the calling convention that a function uses.
278278
enum CallingConv {
279-
CC_C, // __attribute__((cdecl))
280-
CC_X86StdCall, // __attribute__((stdcall))
281-
CC_X86FastCall, // __attribute__((fastcall))
282-
CC_X86ThisCall, // __attribute__((thiscall))
283-
CC_X86VectorCall, // __attribute__((vectorcall))
284-
CC_X86Pascal, // __attribute__((pascal))
285-
CC_Win64, // __attribute__((ms_abi))
286-
CC_X86_64SysV, // __attribute__((sysv_abi))
287-
CC_X86RegCall, // __attribute__((regcall))
288-
CC_AAPCS, // __attribute__((pcs("aapcs")))
289-
CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
290-
CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
291-
CC_SpirFunction, // default for OpenCL functions on SPIR target
292-
CC_OpenCLKernel, // inferred for OpenCL kernels
293-
CC_Swift, // __attribute__((swiftcall))
294-
CC_SwiftAsync, // __attribute__((swiftasynccall))
295-
CC_PreserveMost, // __attribute__((preserve_most))
296-
CC_PreserveAll, // __attribute__((preserve_all))
297-
CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
298-
CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs))
299-
CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel))
300-
CC_M68kRTD, // __attribute__((m68k_rtd))
301-
CC_PreserveNone, // __attribute__((preserve_none))
302-
CC_RISCVVectorCall, // __attribute__((riscv_vector_cc))
279+
CC_C, // __attribute__((cdecl))
280+
CC_X86StdCall, // __attribute__((stdcall))
281+
CC_X86FastCall, // __attribute__((fastcall))
282+
CC_X86ThisCall, // __attribute__((thiscall))
283+
CC_X86VectorCall, // __attribute__((vectorcall))
284+
CC_X86Pascal, // __attribute__((pascal))
285+
CC_Win64, // __attribute__((ms_abi))
286+
CC_X86_64SysV, // __attribute__((sysv_abi))
287+
CC_X86RegCall, // __attribute__((regcall))
288+
CC_AAPCS, // __attribute__((pcs("aapcs")))
289+
CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
290+
CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
291+
CC_SpirFunction, // default for OpenCL functions on SPIR target
292+
CC_OpenCLKernel, // inferred for OpenCL kernels
293+
CC_Swift, // __attribute__((swiftcall))
294+
CC_SwiftAsync, // __attribute__((swiftasynccall))
295+
CC_PreserveMost, // __attribute__((preserve_most))
296+
CC_PreserveAll, // __attribute__((preserve_all))
297+
CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
298+
CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs))
299+
CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel))
300+
CC_M68kRTD, // __attribute__((m68k_rtd))
301+
CC_PreserveNone, // __attribute__((preserve_none))
302+
CC_RISCVVectorCall, // __attribute__((riscv_vector_cc))
303+
CC_RISCVVLSCall_32, // __attribute__((riscv_vls_cc(32)))
304+
CC_RISCVVLSCall_64, // __attribute__((riscv_vls_cc(64)))
305+
CC_RISCVVLSCall_128, // __attribute__((riscv_vls_cc)) or
306+
// __attribute__((riscv_vls_cc(128)))
307+
CC_RISCVVLSCall_256, // __attribute__((riscv_vls_cc(256)))
308+
CC_RISCVVLSCall_512, // __attribute__((riscv_vls_cc(512)))
309+
CC_RISCVVLSCall_1024, // __attribute__((riscv_vls_cc(1024)))
310+
CC_RISCVVLSCall_2048, // __attribute__((riscv_vls_cc(2048)))
311+
CC_RISCVVLSCall_4096, // __attribute__((riscv_vls_cc(4096)))
312+
CC_RISCVVLSCall_8192, // __attribute__((riscv_vls_cc(8192)))
313+
CC_RISCVVLSCall_16384, // __attribute__((riscv_vls_cc(16384)))
314+
CC_RISCVVLSCall_32768, // __attribute__((riscv_vls_cc(32768)))
315+
CC_RISCVVLSCall_65536, // __attribute__((riscv_vls_cc(65536)))
303316
};
304317

305318
/// Checks whether the given calling convention supports variadic

clang/lib/AST/ItaniumMangle.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -3489,6 +3489,20 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
34893489
case CC_M68kRTD:
34903490
case CC_PreserveNone:
34913491
case CC_RISCVVectorCall:
3492+
#define CC_VLS_CASE(ABI_VLEN) case CC_RISCVVLSCall_##ABI_VLEN:
3493+
CC_VLS_CASE(32)
3494+
CC_VLS_CASE(64)
3495+
CC_VLS_CASE(128)
3496+
CC_VLS_CASE(256)
3497+
CC_VLS_CASE(512)
3498+
CC_VLS_CASE(1024)
3499+
CC_VLS_CASE(2048)
3500+
CC_VLS_CASE(4096)
3501+
CC_VLS_CASE(8192)
3502+
CC_VLS_CASE(16384)
3503+
CC_VLS_CASE(32768)
3504+
CC_VLS_CASE(65536)
3505+
#undef CC_VLS_CASE
34923506
// FIXME: we should be mangling all of the above.
34933507
return "";
34943508

clang/lib/AST/Type.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -3559,6 +3559,21 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
35593559
case CC_PreserveNone: return "preserve_none";
35603560
// clang-format off
35613561
case CC_RISCVVectorCall: return "riscv_vector_cc";
3562+
#define CC_VLS_CASE(ABI_VLEN) \
3563+
case CC_RISCVVLSCall_##ABI_VLEN: return "riscv_vls_cc(" #ABI_VLEN ")";
3564+
CC_VLS_CASE(32)
3565+
CC_VLS_CASE(64)
3566+
CC_VLS_CASE(128)
3567+
CC_VLS_CASE(256)
3568+
CC_VLS_CASE(512)
3569+
CC_VLS_CASE(1024)
3570+
CC_VLS_CASE(2048)
3571+
CC_VLS_CASE(4096)
3572+
CC_VLS_CASE(8192)
3573+
CC_VLS_CASE(16384)
3574+
CC_VLS_CASE(32768)
3575+
CC_VLS_CASE(65536)
3576+
#undef CC_VLS_CASE
35623577
// clang-format on
35633578
}
35643579

@@ -4226,6 +4241,7 @@ bool AttributedType::isCallingConv() const {
42264241
case attr::M68kRTD:
42274242
case attr::PreserveNone:
42284243
case attr::RISCVVectorCC:
4244+
case attr::RISCVVLSCC:
42294245
return true;
42304246
}
42314247
llvm_unreachable("invalid attr kind");

clang/lib/AST/TypePrinter.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,23 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
11361136
case CC_RISCVVectorCall:
11371137
OS << "__attribute__((riscv_vector_cc))";
11381138
break;
1139+
#define CC_VLS_CASE(ABI_VLEN) \
1140+
case CC_RISCVVLSCall_##ABI_VLEN: \
1141+
OS << "__attribute__((riscv_vls_cc" #ABI_VLEN "))"; \
1142+
break;
1143+
CC_VLS_CASE(32)
1144+
CC_VLS_CASE(64)
1145+
CC_VLS_CASE(128)
1146+
CC_VLS_CASE(256)
1147+
CC_VLS_CASE(512)
1148+
CC_VLS_CASE(1024)
1149+
CC_VLS_CASE(2048)
1150+
CC_VLS_CASE(4096)
1151+
CC_VLS_CASE(8192)
1152+
CC_VLS_CASE(16384)
1153+
CC_VLS_CASE(32768)
1154+
CC_VLS_CASE(65536)
1155+
#undef CC_VLS_CASE
11391156
}
11401157
}
11411158

@@ -2064,6 +2081,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
20642081
case attr::RISCVVectorCC:
20652082
OS << "riscv_vector_cc";
20662083
break;
2084+
case attr::RISCVVLSCC:
2085+
OS << "riscv_vls_cc";
2086+
break;
20672087
case attr::NoDeref:
20682088
OS << "noderef";
20692089
break;

clang/lib/Basic/Targets/RISCV.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,18 @@ RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
559559
return CCCR_Warning;
560560
case CC_C:
561561
case CC_RISCVVectorCall:
562+
case CC_RISCVVLSCall_32:
563+
case CC_RISCVVLSCall_64:
564+
case CC_RISCVVLSCall_128:
565+
case CC_RISCVVLSCall_256:
566+
case CC_RISCVVLSCall_512:
567+
case CC_RISCVVLSCall_1024:
568+
case CC_RISCVVLSCall_2048:
569+
case CC_RISCVVLSCall_4096:
570+
case CC_RISCVVLSCall_8192:
571+
case CC_RISCVVLSCall_16384:
572+
case CC_RISCVVLSCall_32768:
573+
case CC_RISCVVLSCall_65536:
562574
return CCCR_OK;
563575
}
564576
}

clang/lib/CodeGen/CGCall.cpp

+50
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,22 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
7777
// clang-format off
7878
case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall;
7979
// clang-format on
80+
#define CC_VLS_CASE(ABI_VLEN) \
81+
case CC_RISCVVLSCall_##ABI_VLEN: \
82+
return llvm::CallingConv::RISCV_VLSCall_##ABI_VLEN;
83+
CC_VLS_CASE(32)
84+
CC_VLS_CASE(64)
85+
CC_VLS_CASE(128)
86+
CC_VLS_CASE(256)
87+
CC_VLS_CASE(512)
88+
CC_VLS_CASE(1024)
89+
CC_VLS_CASE(2048)
90+
CC_VLS_CASE(4096)
91+
CC_VLS_CASE(8192)
92+
CC_VLS_CASE(16384)
93+
CC_VLS_CASE(32768)
94+
CC_VLS_CASE(65536)
95+
#undef CC_VLS_CASE
8096
}
8197
}
8298

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

285+
if (RISCVVLSCCAttr *PCS = D->getAttr<RISCVVLSCCAttr>()) {
286+
switch (PCS->getVectorWidth()) {
287+
default:
288+
llvm_unreachable("Invalid RISC-V VLS ABI VLEN");
289+
#define CC_VLS_CASE(ABI_VLEN) \
290+
case ABI_VLEN: \
291+
return CC_RISCVVLSCall_##ABI_VLEN;
292+
CC_VLS_CASE(32)
293+
CC_VLS_CASE(64)
294+
CC_VLS_CASE(128)
295+
CC_VLS_CASE(256)
296+
CC_VLS_CASE(512)
297+
CC_VLS_CASE(1024)
298+
CC_VLS_CASE(2048)
299+
CC_VLS_CASE(4096)
300+
CC_VLS_CASE(8192)
301+
CC_VLS_CASE(16384)
302+
CC_VLS_CASE(32768)
303+
CC_VLS_CASE(65536)
304+
#undef CC_VLS_CASE
305+
}
306+
}
307+
269308
return CC_C;
270309
}
271310

@@ -3234,6 +3273,17 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
32343273
}
32353274
}
32363275

3276+
// Struct of fixed-length vectors and struct of array of fixed-length
3277+
// vector in VLS calling convention are coerced to vector tuple
3278+
// type(represented as TargetExtType) and scalable vector type
3279+
// respectively, they're no longer handled as struct.
3280+
if (ArgI.isDirect() && isa<llvm::StructType>(ConvertType(Ty)) &&
3281+
(isa<llvm::TargetExtType>(ArgI.getCoerceToType()) ||
3282+
isa<llvm::ScalableVectorType>(ArgI.getCoerceToType()))) {
3283+
ArgVals.push_back(ParamValue::forDirect(AI));
3284+
break;
3285+
}
3286+
32373287
llvm::StructType *STy =
32383288
dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
32393289
Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg),

clang/lib/CodeGen/CGDebugInfo.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -1593,6 +1593,21 @@ static unsigned getDwarfCC(CallingConv CC) {
15931593
return llvm::dwarf::DW_CC_LLVM_PreserveNone;
15941594
case CC_RISCVVectorCall:
15951595
return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall;
1596+
#define CC_VLS_CASE(ABI_VLEN) case CC_RISCVVLSCall_##ABI_VLEN:
1597+
CC_VLS_CASE(32)
1598+
CC_VLS_CASE(64)
1599+
CC_VLS_CASE(128)
1600+
CC_VLS_CASE(256)
1601+
CC_VLS_CASE(512)
1602+
CC_VLS_CASE(1024)
1603+
CC_VLS_CASE(2048)
1604+
CC_VLS_CASE(4096)
1605+
CC_VLS_CASE(8192)
1606+
CC_VLS_CASE(16384)
1607+
CC_VLS_CASE(32768)
1608+
CC_VLS_CASE(65536)
1609+
#undef CC_VLS_CASE
1610+
return llvm::dwarf::DW_CC_LLVM_RISCVVLSCall;
15961611
}
15971612
return 0;
15981613
}

0 commit comments

Comments
 (0)