@@ -10286,6 +10286,11 @@ class CommonSPIRABIInfo : public DefaultABIInfo {
10286
10286
10287
10287
ABIArgInfo classifyKernelArgumentType (QualType Ty) const ;
10288
10288
10289
+ // Add new functions rather than overload existing so that these public APIs
10290
+ // can't be blindly misused with wrong calling convention.
10291
+ ABIArgInfo classifyRegcallReturnType (QualType RetTy) const ;
10292
+ ABIArgInfo classifyRegcallArgumentType (QualType RetTy) const ;
10293
+
10289
10294
void computeInfo (CGFunctionInfo &FI) const override ;
10290
10295
10291
10296
private:
@@ -10305,17 +10310,114 @@ ABIArgInfo CommonSPIRABIInfo::classifyKernelArgumentType(QualType Ty) const {
10305
10310
10306
10311
void CommonSPIRABIInfo::computeInfo (CGFunctionInfo &FI) const {
10307
10312
llvm::CallingConv::ID CC = FI.getCallingConvention ();
10313
+ bool IsRegCall = CC == llvm::CallingConv::X86_RegCall;
10308
10314
10309
- if (!getCXXABI ().classifyReturnType (FI))
10310
- FI.getReturnInfo () = classifyReturnType (FI.getReturnType ());
10315
+ if (!getCXXABI ().classifyReturnType (FI)) {
10316
+ CanQualType RetT = FI.getReturnType ();
10317
+ FI.getReturnInfo () =
10318
+ IsRegCall ? classifyRegcallReturnType (RetT) : classifyReturnType (RetT);
10319
+ }
10311
10320
10312
10321
for (auto &Arg : FI.arguments ()) {
10313
10322
if (CC == llvm::CallingConv::SPIR_KERNEL) {
10314
10323
Arg.info = classifyKernelArgumentType (Arg.type );
10315
10324
} else {
10316
- Arg.info = classifyArgumentType (Arg.type );
10325
+ Arg.info = IsRegCall ? classifyRegcallArgumentType (Arg.type )
10326
+ : classifyArgumentType (Arg.type );
10327
+ }
10328
+ }
10329
+ }
10330
+
10331
+ // The two functions below are based on AMDGPUABIInfo, but without any
10332
+ // restriction on the maximum number of arguments passed via registers.
10333
+ // SPIRV BEs are expected to further adjust the calling convention as
10334
+ // needed (use stack or byval-like passing) for some of the arguments.
10335
+
10336
+ ABIArgInfo CommonSPIRABIInfo::classifyRegcallReturnType (QualType RetTy) const {
10337
+ if (isAggregateTypeForABI (RetTy)) {
10338
+ // Records with non-trivial destructors/copy-constructors should not be
10339
+ // returned by value.
10340
+ if (!getRecordArgABI (RetTy, getCXXABI ())) {
10341
+ // Ignore empty structs/unions.
10342
+ if (isEmptyRecord (getContext (), RetTy, true ))
10343
+ return ABIArgInfo::getIgnore ();
10344
+
10345
+ // Lower single-element structs to just return a regular value.
10346
+ if (const Type *SeltTy = isSingleElementStruct (RetTy, getContext ()))
10347
+ return ABIArgInfo::getDirect (CGT.ConvertType (QualType (SeltTy, 0 )));
10348
+
10349
+ if (const RecordType *RT = RetTy->getAs <RecordType>()) {
10350
+ const RecordDecl *RD = RT->getDecl ();
10351
+ if (RD->hasFlexibleArrayMember ())
10352
+ return classifyReturnType (RetTy);
10353
+ }
10354
+
10355
+ // Pack aggregates <= 8 bytes into a single vector register or pair.
10356
+ // TODO make this parameterizeable/adjustable depending on spir target
10357
+ // triple abi component.
10358
+ uint64_t Size = getContext ().getTypeSize (RetTy);
10359
+ if (Size <= 16 )
10360
+ return ABIArgInfo::getDirect (llvm::Type::getInt16Ty (getVMContext ()));
10361
+
10362
+ if (Size <= 32 )
10363
+ return ABIArgInfo::getDirect (llvm::Type::getInt32Ty (getVMContext ()));
10364
+
10365
+ if (Size <= 64 ) {
10366
+ llvm::Type *I32Ty = llvm::Type::getInt32Ty (getVMContext ());
10367
+ return ABIArgInfo::getDirect (llvm::ArrayType::get (I32Ty, 2 ));
10368
+ }
10369
+ return ABIArgInfo::getDirect ();
10317
10370
}
10318
10371
}
10372
+ // Otherwise just do the default thing.
10373
+ return classifyReturnType (RetTy);
10374
+ }
10375
+
10376
+ ABIArgInfo CommonSPIRABIInfo::classifyRegcallArgumentType (QualType Ty) const {
10377
+ Ty = useFirstFieldIfTransparentUnion (Ty);
10378
+
10379
+ if (isAggregateTypeForABI (Ty)) {
10380
+ // Records with non-trivial destructors/copy-constructors should not be
10381
+ // passed by value.
10382
+ if (auto RAA = getRecordArgABI (Ty, getCXXABI ()))
10383
+ return getNaturalAlignIndirect (Ty, RAA == CGCXXABI::RAA_DirectInMemory);
10384
+
10385
+ // Ignore empty structs/unions.
10386
+ if (isEmptyRecord (getContext (), Ty, true ))
10387
+ return ABIArgInfo::getIgnore ();
10388
+
10389
+ // Lower single-element structs to just pass a regular value. TODO: We
10390
+ // could do reasonable-size multiple-element structs too, using getExpand(),
10391
+ // though watch out for things like bitfields.
10392
+ if (const Type *SeltTy = isSingleElementStruct (Ty, getContext ()))
10393
+ return ABIArgInfo::getDirect (CGT.ConvertType (QualType (SeltTy, 0 )));
10394
+
10395
+ if (const RecordType *RT = Ty->getAs <RecordType>()) {
10396
+ const RecordDecl *RD = RT->getDecl ();
10397
+ if (RD->hasFlexibleArrayMember ())
10398
+ return classifyArgumentType (Ty);
10399
+ }
10400
+
10401
+ // Pack aggregates <= 8 bytes into single vector register or pair.
10402
+ // TODO make this parameterizeable/adjustable depending on spir target
10403
+ // triple abi component.
10404
+ uint64_t Size = getContext ().getTypeSize (Ty);
10405
+ if (Size <= 64 ) {
10406
+ if (Size <= 16 )
10407
+ return ABIArgInfo::getDirect (llvm::Type::getInt16Ty (getVMContext ()));
10408
+
10409
+ if (Size <= 32 )
10410
+ return ABIArgInfo::getDirect (llvm::Type::getInt32Ty (getVMContext ()));
10411
+
10412
+ // XXX: Should this be i64 instead, and should the limit increase?
10413
+ llvm::Type *I32Ty = llvm::Type::getInt32Ty (getVMContext ());
10414
+ return ABIArgInfo::getDirect (llvm::ArrayType::get (I32Ty, 2 ));
10415
+ }
10416
+ return ABIArgInfo::getDirect ();
10417
+ }
10418
+
10419
+ // Otherwise just do the default thing.
10420
+ return classifyArgumentType (Ty);
10319
10421
}
10320
10422
10321
10423
class SPIRVABIInfo : public CommonSPIRABIInfo {
0 commit comments