@@ -57,6 +57,29 @@ CXXConstructorDecl *lookupCopyConstructor(QualType ResTy) {
5757 return CD;
5858 return nullptr ;
5959}
60+
61+ ParameterABI
62+ convertParamModifierToParamABI (HLSLParamModifierAttr::Spelling Modifier) {
63+ assert (Modifier != HLSLParamModifierAttr::Spelling::Keyword_in &&
64+ " HLSL 'in' parameters modifier cannot be converted to ParameterABI" );
65+ switch (Modifier) {
66+ case HLSLParamModifierAttr::Spelling::Keyword_out:
67+ return ParameterABI::HLSLOut;
68+ case HLSLParamModifierAttr::Spelling::Keyword_inout:
69+ return ParameterABI::HLSLInOut;
70+ default :
71+ llvm_unreachable (" Invalid HLSL parameter modifier" );
72+ }
73+ }
74+
75+ QualType getInoutParameterType (ASTContext &AST, QualType Ty) {
76+ assert (!Ty->isReferenceType () &&
77+ " Pointer and reference types cannot be inout or out parameters" );
78+ Ty = AST.getLValueReferenceType (Ty);
79+ Ty.addRestrict ();
80+ return Ty;
81+ }
82+
6083} // namespace
6184
6285// Builder for template arguments of builtin types. Used internally
@@ -421,13 +444,32 @@ BuiltinTypeMethodBuilder::addParam(StringRef Name, QualType Ty,
421444void BuiltinTypeMethodBuilder::createDecl () {
422445 assert (Method == nullptr && " Method or constructor is already created" );
423446
424- // create method or constructor type
447+ // create function prototype
425448 ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
426449 SmallVector<QualType> ParamTypes;
427- for (Param &MP : Params)
428- ParamTypes.emplace_back (MP.Ty );
450+ SmallVector<FunctionType::ExtParameterInfo> ParamExtInfos (Params.size ());
451+ uint32_t ArgIndex = 0 ;
452+ bool IsTemplate = DeclBuilder.Template != nullptr ;
453+ bool UseParamExtInfo = false ;
454+ for (Param &MP : Params) {
455+ QualType Ty = MP.Ty ;
456+ if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
457+ UseParamExtInfo = true ;
458+ ParamExtInfos[ArgIndex].withABI (
459+ convertParamModifierToParamABI (MP.Modifier ));
460+ // Only update types on inout and out parameters for non-templated
461+ // methods. Templated types will have their inout/out parameters
462+ // converted to references during template instantiation.
463+ if (!IsTemplate)
464+ Ty = getInoutParameterType (AST, Ty);
465+ }
466+ ParamTypes.emplace_back (Ty);
467+ ++ArgIndex;
468+ }
429469
430470 FunctionProtoType::ExtProtoInfo ExtInfo;
471+ if (UseParamExtInfo)
472+ ExtInfo.ExtParameterInfos = ParamExtInfos.data ();
431473 if (IsConst)
432474 ExtInfo.TypeQuals .addConst ();
433475
@@ -459,6 +501,7 @@ void BuiltinTypeMethodBuilder::createDecl() {
459501 AST.getTrivialTypeSourceInfo (MP.Ty , SourceLocation ()), SC_None,
460502 nullptr );
461503 if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
504+ Parm->setType (getInoutParameterType (AST, Parm->getType ()));
462505 auto *Mod =
463506 HLSLParamModifierAttr::Create (AST, SourceRange (), MP.Modifier );
464507 Parm->addAttr (Mod);
@@ -1127,5 +1170,37 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addConsumeMethod() {
11271170 .finalize ();
11281171}
11291172
1173+ BuiltinTypeDeclBuilder &
1174+ BuiltinTypeDeclBuilder::addGetDimensionsMethodForBuffer () {
1175+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
1176+ ASTContext &AST = SemaRef.getASTContext ();
1177+ QualType UIntTy = AST.UnsignedIntTy ;
1178+
1179+ QualType HandleTy = getResourceHandleField ()->getType ();
1180+ auto *AttrResTy = cast<HLSLAttributedResourceType>(HandleTy.getTypePtr ());
1181+
1182+ // Structured buffers except {RW}ByteAddressBuffer have overload
1183+ // GetDimensions(out uint numStructs, out uint stride).
1184+ if (AttrResTy->getAttrs ().RawBuffer &&
1185+ AttrResTy->getContainedType () != AST.Char8Ty ) {
1186+ return BuiltinTypeMethodBuilder (*this , " GetDimensions" , AST.VoidTy )
1187+ .addParam (" numStructs" , UIntTy, HLSLParamModifierAttr::Keyword_out)
1188+ .addParam (" stride" , UIntTy, HLSLParamModifierAttr::Keyword_out)
1189+ .callBuiltin (" __builtin_hlsl_buffer_getdimensions" , QualType (),
1190+ PH::Handle, PH::_0)
1191+ .callBuiltin (" __builtin_hlsl_buffer_getstride" , QualType (), PH::Handle,
1192+ PH::_1)
1193+ .finalize ();
1194+ }
1195+
1196+ // Typed buffers and {RW}ByteAddressBuffer have overload
1197+ // GetDimensions(out uint dim).
1198+ return BuiltinTypeMethodBuilder (*this , " GetDimensions" , AST.VoidTy )
1199+ .addParam (" dim" , UIntTy, HLSLParamModifierAttr::Keyword_out)
1200+ .callBuiltin (" __builtin_hlsl_buffer_getdimensions" , QualType (),
1201+ PH::Handle, PH::_0)
1202+ .finalize ();
1203+ }
1204+
11301205} // namespace hlsl
11311206} // namespace clang
0 commit comments