Skip to content

Commit 15161b0

Browse files
committed
[RISCV][VLS] Support RISCV VLS calling convention
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. An option `-mriscv-abi-vlen=N` is also added to specify the `ABI_VLEN` globally, it's used for every functions are being compiled, however if both function attribute and option are specified, the function attribute has higher priority than the option which means the function attribute overwrites the `ABI_VLEN` specified by the option. 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.
1 parent dc1c00f commit 15161b0

33 files changed

+265
-39
lines changed

clang/include/clang-c/Index.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3005,6 +3005,7 @@ enum CXCallingConv {
30053005
CXCallingConv_M68kRTD = 19,
30063006
CXCallingConv_PreserveNone = 20,
30073007
CXCallingConv_RISCVVectorCall = 21,
3008+
CXCallingConv_RISCVVLSCall = 22,
30083009

30093010
CXCallingConv_Invalid = 100,
30103011
CXCallingConv_Unexposed = 200

clang/include/clang/AST/Type.h

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,7 +1942,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
19421942
/// Extra information which affects how the function is called, like
19431943
/// regparm and the calling convention.
19441944
LLVM_PREFERRED_TYPE(CallingConv)
1945-
unsigned ExtInfo : 13;
1945+
unsigned ExtInfo : 17;
19461946

19471947
/// The ref-qualifier associated with a \c FunctionProtoType.
19481948
///
@@ -4395,6 +4395,8 @@ class FunctionType : public Type {
43954395

43964396
// | CC |noreturn|produces|nocallersavedregs|regparm|nocfcheck|cmsenscall|
43974397
// |0 .. 4| 5 | 6 | 7 |8 .. 10| 11 | 12 |
4398+
// |RISCV-ABI-VLEN|
4399+
// |13 .. 17|
43984400
//
43994401
// regparm is either 0 (no regparm attribute) or the regparm value+1.
44004402
enum { CallConvMask = 0x1F };
@@ -4407,23 +4409,25 @@ class FunctionType : public Type {
44074409
};
44084410
enum { NoCfCheckMask = 0x800 };
44094411
enum { CmseNSCallMask = 0x1000 };
4410-
uint16_t Bits = CC_C;
4412+
enum { Log2RISCVABIVLenMask = 0x1E000, Log2RISCVABIVLenOffset = 13 };
4413+
uint32_t Bits = CC_C;
44114414

4412-
ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
4415+
ExtInfo(unsigned Bits) : Bits(static_cast<uint32_t>(Bits)) {}
44134416

44144417
public:
44154418
// Constructor with no defaults. Use this when you know that you
44164419
// have all the elements (when reading an AST file for example).
44174420
ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc,
44184421
bool producesResult, bool noCallerSavedRegs, bool NoCfCheck,
4419-
bool cmseNSCall) {
4422+
bool cmseNSCall, unsigned Log2RISCVABIVLen) {
44204423
assert((!hasRegParm || regParm < 7) && "Invalid regparm value");
44214424
Bits = ((unsigned)cc) | (noReturn ? NoReturnMask : 0) |
44224425
(producesResult ? ProducesResultMask : 0) |
44234426
(noCallerSavedRegs ? NoCallerSavedRegsMask : 0) |
44244427
(hasRegParm ? ((regParm + 1) << RegParmOffset) : 0) |
44254428
(NoCfCheck ? NoCfCheckMask : 0) |
4426-
(cmseNSCall ? CmseNSCallMask : 0);
4429+
(cmseNSCall ? CmseNSCallMask : 0) |
4430+
(Log2RISCVABIVLen << Log2RISCVABIVLenOffset);
44274431
}
44284432

44294433
// Constructor with all defaults. Use when for example creating a
@@ -4450,6 +4454,10 @@ class FunctionType : public Type {
44504454

44514455
CallingConv getCC() const { return CallingConv(Bits & CallConvMask); }
44524456

4457+
unsigned getLog2RISCVABIVLen() const {
4458+
return (Bits & Log2RISCVABIVLenMask) >> Log2RISCVABIVLenOffset;
4459+
}
4460+
44534461
bool operator==(ExtInfo Other) const {
44544462
return Bits == Other.Bits;
44554463
}
@@ -4505,6 +4513,11 @@ class FunctionType : public Type {
45054513
return ExtInfo((Bits & ~CallConvMask) | (unsigned) cc);
45064514
}
45074515

4516+
ExtInfo withLog2RISCVABIVLen(unsigned Log2RISCVABIVLen) const {
4517+
return ExtInfo((Bits & ~Log2RISCVABIVLenMask) |
4518+
(Log2RISCVABIVLen << Log2RISCVABIVLenOffset));
4519+
}
4520+
45084521
void Profile(llvm::FoldingSetNodeID &ID) const {
45094522
ID.AddInteger(Bits);
45104523
}
@@ -4609,6 +4622,9 @@ class FunctionType : public Type {
46094622

46104623
bool getCmseNSCallAttr() const { return getExtInfo().getCmseNSCall(); }
46114624
CallingConv getCallConv() const { return getExtInfo().getCC(); }
4625+
unsigned getLog2RISCVABIVLen() const {
4626+
return getExtInfo().getLog2RISCVABIVLen();
4627+
}
46124628
ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
46134629

46144630
static_assert((~Qualifiers::FastMask & Qualifiers::CVRMask) == 0,

clang/include/clang/AST/TypeProperties.td

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,14 +313,17 @@ let Class = FunctionType in {
313313
def : Property<"cmseNSCall", Bool> {
314314
let Read = [{ node->getExtInfo().getCmseNSCall() }];
315315
}
316+
def : Property<"Log2RISCVABIVLen", UInt32> {
317+
let Read = [{ node->getExtInfo().getLog2RISCVABIVLen() }];
318+
}
316319
}
317320

318321
let Class = FunctionNoProtoType in {
319322
def : Creator<[{
320323
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
321324
callingConvention, producesResult,
322325
noCallerSavedRegs, noCfCheck,
323-
cmseNSCall);
326+
cmseNSCall, Log2RISCVABIVLen);
324327
return ctx.getFunctionNoProtoType(returnType, extInfo);
325328
}]>;
326329
}
@@ -363,7 +366,7 @@ let Class = FunctionProtoType in {
363366
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
364367
callingConvention, producesResult,
365368
noCallerSavedRegs, noCfCheck,
366-
cmseNSCall);
369+
cmseNSCall, Log2RISCVABIVLen);
367370
FunctionProtoType::ExtProtoInfo epi;
368371
epi.ExtInfo = extInfo;
369372
epi.Variadic = variadic;

clang/include/clang/Basic/Attr.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3139,6 +3139,14 @@ def RISCVVectorCC: DeclOrTypeAttr, TargetSpecificAttr<TargetRISCV> {
31393139
let Documentation = [RISCVVectorCCDocs];
31403140
}
31413141

3142+
def RISCVVLSCC: DeclOrTypeAttr, TargetSpecificAttr<TargetRISCV> {
3143+
let Spellings = [CXX11<"riscv", "vls_cc">,
3144+
C23<"riscv", "vls_cc">,
3145+
Clang<"riscv_vls_cc">];
3146+
let Args = [UnsignedArgument<"VectorWidth", /*opt*/1>];
3147+
let Documentation = [RISCVVLSCCDocs];
3148+
}
3149+
31423150
def Target : InheritableAttr {
31433151
let Spellings = [GCC<"target">];
31443152
let Args = [StringArgument<"featuresStr">];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5554,6 +5554,17 @@ them if they use them.
55545554
}];
55555555
}
55565556

5557+
def RISCVVLSCCDocs : Documentation {
5558+
let Category = DocCatCallingConvs;
5559+
let Heading = "riscv::vls_cc, riscv_vls_cc, clang::riscv_vls_cc";
5560+
let Content = [{
5561+
The ``riscv_vls_cc`` attribute can be applied to a function. Functions
5562+
declared with this attribute will utilize the standard fixed-length vector
5563+
calling convention variant instead of the default calling convention defined by
5564+
the ABI. This variant aims to pass fixed-length vectors via vector registers,
5565+
if possible, rather than through general-purpose registers.}];
5566+
}
5567+
55575568
def PreferredNameDocs : Documentation {
55585569
let Category = DocCatDecl;
55595570
let Content = [{

clang/include/clang/Basic/Specifiers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ namespace clang {
297297
CC_M68kRTD, // __attribute__((m68k_rtd))
298298
CC_PreserveNone, // __attribute__((preserve_none))
299299
CC_RISCVVectorCall, // __attribute__((riscv_vector_cc))
300+
CC_RISCVVLSCall, // __attribute__((riscv_vls_cc))
300301
};
301302

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

clang/include/clang/CodeGen/CGFunctionInfo.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,9 @@ class CGFunctionInfo final
608608
/// Log 2 of the maximum vector width.
609609
unsigned MaxVectorWidth : 4;
610610

611+
/// Log2 of ABI_VLEN used in RISCV VLS calling convention.
612+
unsigned Log2RISCVABIVLen : 4;
613+
611614
RequiredArgs Required;
612615

613616
/// The struct representing all arguments passed in memory. Only used when
@@ -718,11 +721,13 @@ class CGFunctionInfo final
718721
bool getHasRegParm() const { return HasRegParm; }
719722
unsigned getRegParm() const { return RegParm; }
720723

724+
unsigned getLog2RISCVABIVLen() const { return Log2RISCVABIVLen; }
725+
721726
FunctionType::ExtInfo getExtInfo() const {
722727
return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(),
723728
getASTCallingConvention(), isReturnsRetained(),
724729
isNoCallerSavedRegs(), isNoCfCheck(),
725-
isCmseNSCall());
730+
isCmseNSCall(), getLog2RISCVABIVLen());
726731
}
727732

728733
CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
@@ -776,6 +781,7 @@ class CGFunctionInfo final
776781
ID.AddInteger(RegParm);
777782
ID.AddBoolean(NoCfCheck);
778783
ID.AddBoolean(CmseNSCall);
784+
ID.AddInteger(Log2RISCVABIVLen);
779785
ID.AddInteger(Required.getOpaqueData());
780786
ID.AddBoolean(HasExtParameterInfos);
781787
if (HasExtParameterInfos) {
@@ -803,6 +809,7 @@ class CGFunctionInfo final
803809
ID.AddInteger(info.getRegParm());
804810
ID.AddBoolean(info.getNoCfCheck());
805811
ID.AddBoolean(info.getCmseNSCall());
812+
ID.AddInteger(info.getLog2RISCVABIVLen());
806813
ID.AddInteger(required.getOpaqueData());
807814
ID.AddBoolean(!paramInfos.empty());
808815
if (!paramInfos.empty()) {

clang/include/clang/Driver/Options.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4865,6 +4865,8 @@ def mrvv_vector_bits_EQ : Joined<["-"], "mrvv-vector-bits=">, Group<m_Group>,
48654865
!eq(GlobalDocumentation.Program, "Flang") : "",
48664866
true: " The value will be reflected in __riscv_v_fixed_vlen preprocessor define"),
48674867
" (RISC-V only)")>;
4868+
def mriscv_abi_vlen_EQ : Joined<["-"], "mriscv-abi-vlen=">, Group<m_Group>,
4869+
HelpText<"Specify the VLEN for VLS calling convention.">;
48684870

48694871
def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_Group>,
48704872
HelpText<"Allow memory accesses to be unaligned (AArch32/MIPSr6 only)">;

clang/lib/AST/ASTContext.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10826,6 +10826,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
1082610826
return {};
1082710827
if (lbaseInfo.getNoCfCheck() != rbaseInfo.getNoCfCheck())
1082810828
return {};
10829+
if (lbaseInfo.getLog2RISCVABIVLen() != rbaseInfo.getLog2RISCVABIVLen())
10830+
return {};
1082910831

1083010832
// When merging declarations, it's common for supplemental information like
1083110833
// attributes to only be present in one of the declarations, and we generally

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3452,6 +3452,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
34523452
case CC_M68kRTD:
34533453
case CC_PreserveNone:
34543454
case CC_RISCVVectorCall:
3455+
case CC_RISCVVLSCall:
34553456
// FIXME: we should be mangling all of the above.
34563457
return "";
34573458

0 commit comments

Comments
 (0)