[clang] [llvm] [HLSL] Add `Increment`/`DecrementCounter` methods to structured buffers (PR #117608)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 26 10:50:06 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-hlsl
Author: Helena Kotas (hekota)
<details>
<summary>Changes</summary>
Introduces `__builtin_hlsl_buffer_update_counter` clang buildin that is used to implement the `IncrementCounter` and `DecrementCounter` methods on `RWStructuredBuffer` and `RasterizerOrderedStructuredBuffer` (see Note).
The builtin is translated to LLVM intrisic `llvm.dx.bufferUpdateCounter` or `llvm.spv.bufferUpdateCounter`.
Introduces `BuiltinTypeMethodBuilder` helper in `HLSLExternalSemaSource` that enables adding methods to builtin types using builder pattern like this:
```
BuiltinTypeMethodBuilder(Sema, RecordBuilder, "MethodName", ReturnType)
.addParam("param_name", Type, InOutModifier)
.callBuiltin("buildin_name", { BuiltinParams })
.finalizeMethod();
```
Fixes #<!-- -->113513
[First version](llvm/llvm-project#<!-- -->114148) of this PR was reverted because of build break.
---
Patch is 46.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/117608.diff
15 Files Affected:
- (modified) clang/include/clang/Basic/Builtins.td (+6-1)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+6)
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+9)
- (modified) clang/lib/CodeGen/CGHLSLRuntime.h (+1)
- (modified) clang/lib/Sema/HLSLExternalSemaSource.cpp (+321-93)
- (modified) clang/lib/Sema/SemaExpr.cpp (+3)
- (modified) clang/lib/Sema/SemaHLSL.cpp (+54)
- (modified) clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl (+26)
- (added) clang/test/CodeGenHLSL/builtins/StructuredBuffers-methods-lib.hlsl (+25)
- (added) clang/test/CodeGenHLSL/builtins/StructuredBuffers-methods-ps.hlsl (+28)
- (added) clang/test/SemaHLSL/BuiltIns/buffer_update_counter-errors.hlsl (+48)
- (modified) llvm/include/llvm/IR/IntrinsicsDirectX.td (+1-1)
- (modified) llvm/include/llvm/IR/IntrinsicsSPIRV.td (+5)
- (modified) llvm/lib/Target/DirectX/DXILOpLowering.cpp (+1-1)
- (renamed) llvm/test/CodeGen/DirectX/bufferUpdateCounter.ll (+3-3)
``````````diff
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 83c90b3d6e681b..eaff744924805e 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4882,7 +4882,6 @@ def HLSLSaturate : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
-
def HLSLSelect : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_select"];
let Attributes = [NoThrow, Const];
@@ -4907,6 +4906,12 @@ def HLSLRadians : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
+def HLSLBufferUpdateCounter : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_buffer_update_counter"];
+ let Attributes = [NoThrow];
+ let Prototype = "uint32_t(...)";
+}
+
def HLSLSplitDouble: LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_elementwise_splitdouble"];
let Attributes = [NoThrow, Const];
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6ff24c2bc8faad..834e588c18e376 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7287,6 +7287,8 @@ def err_typecheck_illegal_increment_decrement : Error<
"cannot %select{decrement|increment}1 value of type %0">;
def err_typecheck_expect_int : Error<
"used type %0 where integer is required">;
+def err_typecheck_expect_hlsl_resource : Error<
+ "used type %0 where __hlsl_resource_t is required">;
def err_typecheck_arithmetic_incomplete_or_sizeless_type : Error<
"arithmetic on a pointer to %select{an incomplete|sizeless}0 type %1">;
def err_typecheck_pointer_arith_function_type : Error<
@@ -12528,6 +12530,10 @@ def warn_attr_min_eq_max: Warning<
def err_hlsl_attribute_number_arguments_insufficient_shader_model: Error<
"attribute %0 with %1 arguments requires shader model %2 or greater">;
+def err_hlsl_expect_arg_const_int_one_or_neg_one: Error<
+ "argument %0 must be constant integer 1 or -1">;
+def err_invalid_hlsl_resource_type: Error<
+ "invalid __hlsl_resource_t type attributes">;
// Layout randomization diagnostics.
def err_non_designated_init_used : Error<
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 91b70b4fdf3d20..f32d5a2f43559a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19409,6 +19409,15 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
CGM.getHLSLRuntime().getRadiansIntrinsic(), ArrayRef<Value *>{Op0},
nullptr, "hlsl.radians");
}
+ case Builtin::BI__builtin_hlsl_buffer_update_counter: {
+ Value *ResHandle = EmitScalarExpr(E->getArg(0));
+ Value *Offset = EmitScalarExpr(E->getArg(1));
+ Value *OffsetI8 = Builder.CreateIntCast(Offset, Int8Ty, true);
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/Offset->getType(),
+ CGM.getHLSLRuntime().getBufferUpdateCounterIntrinsic(),
+ ArrayRef<Value *>{ResHandle, OffsetI8}, nullptr);
+ }
case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
assert((E->getArg(0)->getType()->hasFloatingRepresentation() &&
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index a8e0ed42b79a35..854214d6bc0677 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -102,6 +102,7 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp, uclamp)
GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, handle_fromBinding)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, bufferUpdateCounter)
//===----------------------------------------------------------------------===//
// End of reserved area for HLSL intrinsic getters.
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 0f37738b217c6d..886a4c098580ae 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -12,7 +12,9 @@
#include "clang/Sema/HLSLExternalSemaSource.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Lookup.h"
@@ -20,36 +22,43 @@
#include "clang/Sema/SemaHLSL.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Frontend/HLSL/HLSLResource.h"
+#include "llvm/Support/ErrorHandling.h"
#include <functional>
using namespace clang;
using namespace llvm::hlsl;
+static FunctionDecl *lookupBuiltinFunction(Sema &S, StringRef Name);
+
namespace {
struct TemplateParameterListBuilder;
struct BuiltinTypeDeclBuilder {
+ Sema &SemaRef;
CXXRecordDecl *Record = nullptr;
ClassTemplateDecl *Template = nullptr;
ClassTemplateDecl *PrevTemplate = nullptr;
NamespaceDecl *HLSLNamespace = nullptr;
llvm::StringMap<FieldDecl *> Fields;
- BuiltinTypeDeclBuilder(CXXRecordDecl *R) : Record(R) {
+ BuiltinTypeDeclBuilder(Sema &SemaRef, CXXRecordDecl *R)
+ : SemaRef(SemaRef), Record(R) {
Record->startDefinition();
Template = Record->getDescribedClassTemplate();
}
- BuiltinTypeDeclBuilder(Sema &S, NamespaceDecl *Namespace, StringRef Name)
- : HLSLNamespace(Namespace) {
- ASTContext &AST = S.getASTContext();
+ BuiltinTypeDeclBuilder(Sema &SemaRef, NamespaceDecl *Namespace,
+ StringRef Name)
+ : SemaRef(SemaRef), HLSLNamespace(Namespace) {
+ ASTContext &AST = SemaRef.getASTContext();
IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
- LookupResult Result(S, &II, SourceLocation(), Sema::LookupTagName);
+ LookupResult Result(SemaRef, &II, SourceLocation(), Sema::LookupTagName);
CXXRecordDecl *PrevDecl = nullptr;
- if (S.LookupQualifiedName(Result, HLSLNamespace)) {
+ if (SemaRef.LookupQualifiedName(Result, HLSLNamespace)) {
+ // Declaration already exists (from precompiled headers)
NamedDecl *Found = Result.getFoundDecl();
if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
PrevDecl = TD->getTemplatedDecl();
@@ -61,6 +70,7 @@ struct BuiltinTypeDeclBuilder {
if (PrevDecl && PrevDecl->isCompleteDefinition()) {
Record = PrevDecl;
+ Template = PrevTemplate;
return;
}
@@ -84,8 +94,7 @@ struct BuiltinTypeDeclBuilder {
BuiltinTypeDeclBuilder &
addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef<Attr *> Attrs,
AccessSpecifier Access = AccessSpecifier::AS_private) {
- if (Record->isCompleteDefinition())
- return *this;
+ assert(!Record->isCompleteDefinition() && "record is already complete");
assert(Record->isBeingDefined() &&
"Definition must be started before adding members!");
ASTContext &AST = Record->getASTContext();
@@ -109,22 +118,16 @@ struct BuiltinTypeDeclBuilder {
}
BuiltinTypeDeclBuilder &
- addHandleMember(Sema &S, ResourceClass RC, ResourceKind RK, bool IsROV,
- bool RawBuffer,
+ addHandleMember(ResourceClass RC, ResourceKind RK, bool IsROV, bool RawBuffer,
AccessSpecifier Access = AccessSpecifier::AS_private) {
- if (Record->isCompleteDefinition())
- return *this;
+ assert(!Record->isCompleteDefinition() && "record is already complete");
- ASTContext &Ctx = S.getASTContext();
+ ASTContext &Ctx = SemaRef.getASTContext();
TypeSourceInfo *ElementTypeInfo = nullptr;
QualType ElemTy = Ctx.Char8Ty;
- if (Template) {
- if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
- Template->getTemplateParameters()->getParam(0))) {
- ElemTy = QualType(TTD->getTypeForDecl(), 0);
- }
- }
+ if (Template)
+ ElemTy = getFirstTemplateTypeParam();
ElementTypeInfo = Ctx.getTrivialTypeSourceInfo(ElemTy, SourceLocation());
// add handle member with resource type attributes
@@ -137,32 +140,13 @@ struct BuiltinTypeDeclBuilder {
? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
: nullptr};
Attr *ResourceAttr = HLSLResourceAttr::CreateImplicit(Ctx, RK);
- if (CreateHLSLAttributedResourceType(S, Ctx.HLSLResourceTy, Attrs,
+ if (CreateHLSLAttributedResourceType(SemaRef, Ctx.HLSLResourceTy, Attrs,
AttributedResTy))
addMemberVariable("__handle", AttributedResTy, {ResourceAttr}, Access);
return *this;
}
- static DeclRefExpr *lookupBuiltinFunction(ASTContext &AST, Sema &S,
- StringRef Name) {
- IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
- DeclarationNameInfo NameInfo =
- DeclarationNameInfo(DeclarationName(&II), SourceLocation());
- LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
- // AllowBuiltinCreation is false but LookupDirect will create
- // the builtin when searching the global scope anyways...
- S.LookupName(R, S.getCurScope());
- // FIXME: If the builtin function was user-declared in global scope,
- // this assert *will* fail. Should this call LookupBuiltin instead?
- assert(R.isSingleResult() &&
- "Since this is a builtin it should always resolve!");
- auto *VD = cast<ValueDecl>(R.getFoundDecl());
- QualType Ty = VD->getType();
- return DeclRefExpr::Create(AST, NestedNameSpecifierLoc(), SourceLocation(),
- VD, false, NameInfo, Ty, VK_PRValue);
- }
-
- BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S) {
+ BuiltinTypeDeclBuilder &addDefaultHandleConstructor() {
if (Record->isCompleteDefinition())
return *this;
ASTContext &AST = Record->getASTContext();
@@ -187,25 +171,18 @@ struct BuiltinTypeDeclBuilder {
}
BuiltinTypeDeclBuilder &addArraySubscriptOperators() {
- if (Record->isCompleteDefinition())
- return *this;
addArraySubscriptOperator(true);
addArraySubscriptOperator(false);
return *this;
}
BuiltinTypeDeclBuilder &addArraySubscriptOperator(bool IsConst) {
- if (Record->isCompleteDefinition())
- return *this;
+ assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = Record->getASTContext();
QualType ElemTy = AST.Char8Ty;
- if (Template) {
- if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
- Template->getTemplateParameters()->getParam(0))) {
- ElemTy = QualType(TTD->getTypeForDecl(), 0);
- }
- }
+ if (Template)
+ ElemTy = getFirstTemplateTypeParam();
QualType ReturnTy = ElemTy;
FunctionProtoType::ExtProtoInfo ExtInfo;
@@ -271,16 +248,31 @@ struct BuiltinTypeDeclBuilder {
return *this;
}
+ FieldDecl *getResourceHandleField() {
+ auto I = Fields.find("__handle");
+ assert(I != Fields.end() &&
+ I->second->getType()->isHLSLAttributedResourceType() &&
+ "record does not have resource handle field");
+ return I->second;
+ }
+
+ QualType getFirstTemplateTypeParam() {
+ assert(Template && "record it not a template");
+ if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
+ Template->getTemplateParameters()->getParam(0))) {
+ return QualType(TTD->getTypeForDecl(), 0);
+ }
+ return QualType();
+ }
+
BuiltinTypeDeclBuilder &startDefinition() {
- if (Record->isCompleteDefinition())
- return *this;
+ assert(!Record->isCompleteDefinition() && "record is already complete");
Record->startDefinition();
return *this;
}
BuiltinTypeDeclBuilder &completeDefinition() {
- if (Record->isCompleteDefinition())
- return *this;
+ assert(!Record->isCompleteDefinition() && "record is already complete");
assert(Record->isBeingDefined() &&
"Definition must be started before completing it.");
@@ -288,38 +280,47 @@ struct BuiltinTypeDeclBuilder {
return *this;
}
- TemplateParameterListBuilder addTemplateArgumentList(Sema &S);
- BuiltinTypeDeclBuilder &
- addSimpleTemplateParams(Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD);
- BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S);
+ Expr *getConstantIntExpr(int value) {
+ ASTContext &AST = SemaRef.getASTContext();
+ return IntegerLiteral::Create(
+ AST, llvm::APInt(AST.getTypeSize(AST.IntTy), value, true), AST.IntTy,
+ SourceLocation());
+ }
+
+ TemplateParameterListBuilder addTemplateArgumentList();
+ BuiltinTypeDeclBuilder &addSimpleTemplateParams(ArrayRef<StringRef> Names,
+ ConceptDecl *CD);
+
+ // Builtin types methods
+ BuiltinTypeDeclBuilder &addIncrementCounterMethod();
+ BuiltinTypeDeclBuilder &addDecrementCounterMethod();
};
struct TemplateParameterListBuilder {
BuiltinTypeDeclBuilder &Builder;
- Sema &S;
llvm::SmallVector<NamedDecl *> Params;
- TemplateParameterListBuilder(Sema &S, BuiltinTypeDeclBuilder &RB)
- : Builder(RB), S(S) {}
+ TemplateParameterListBuilder(BuiltinTypeDeclBuilder &RB) : Builder(RB) {}
~TemplateParameterListBuilder() { finalizeTemplateArgs(); }
TemplateParameterListBuilder &
addTypeParameter(StringRef Name, QualType DefaultValue = QualType()) {
- if (Builder.Record->isCompleteDefinition())
- return *this;
+ assert(!Builder.Record->isCompleteDefinition() &&
+ "record is already complete");
+ ASTContext &AST = Builder.SemaRef.getASTContext();
unsigned Position = static_cast<unsigned>(Params.size());
auto *Decl = TemplateTypeParmDecl::Create(
- S.Context, Builder.Record->getDeclContext(), SourceLocation(),
+ AST, Builder.Record->getDeclContext(), SourceLocation(),
SourceLocation(), /* TemplateDepth */ 0, Position,
- &S.Context.Idents.get(Name, tok::TokenKind::identifier),
+ &AST.Idents.get(Name, tok::TokenKind::identifier),
/* Typename */ true,
/* ParameterPack */ false,
/* HasTypeConstraint*/ false);
if (!DefaultValue.isNull())
- Decl->setDefaultArgument(
- S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(),
- SourceLocation()));
+ Decl->setDefaultArgument(AST,
+ Builder.SemaRef.getTrivialTemplateArgumentLoc(
+ DefaultValue, QualType(), SourceLocation()));
Params.emplace_back(Decl);
return *this;
@@ -421,14 +422,14 @@ struct TemplateParameterListBuilder {
BuiltinTypeDeclBuilder &finalizeTemplateArgs(ConceptDecl *CD = nullptr) {
if (Params.empty())
return Builder;
- ConceptSpecializationExpr *CSE =
- CD ? constructConceptSpecializationExpr(S, CD) : nullptr;
- auto *ParamList = TemplateParameterList::Create(S.Context, SourceLocation(),
- SourceLocation(), Params,
- SourceLocation(), CSE);
+ ASTContext &AST = Builder.SemaRef.Context;
+ ConceptSpecializationExpr *CSE =
+ CD ? constructConceptSpecializationExpr(Builder.SemaRef, CD) : nullptr;
+ auto *ParamList = TemplateParameterList::Create(
+ AST, SourceLocation(), SourceLocation(), Params, SourceLocation(), CSE);
Builder.Template = ClassTemplateDecl::Create(
- S.Context, Builder.Record->getDeclContext(), SourceLocation(),
+ AST, Builder.Record->getDeclContext(), SourceLocation(),
DeclarationName(Builder.Record->getIdentifier()), ParamList,
Builder.Record);
@@ -443,26 +444,233 @@ struct TemplateParameterListBuilder {
Params.clear();
QualType T = Builder.Template->getInjectedClassNameSpecialization();
- T = S.Context.getInjectedClassNameType(Builder.Record, T);
+ T = AST.getInjectedClassNameType(Builder.Record, T);
return Builder;
}
};
+
+// Builder for methods of builtin types. Allows adding methods to builtin types
+// using the builder pattern like this:
+//
+// BuiltinTypeMethodBuilder(Sema, RecordBuilder, "MethodName", ReturnType)
+// .addParam("param_name", Type, InOutModifier)
+// .callBuiltin("buildin_name", { BuiltinParams })
+// .finalizeMethod();
+//
+// The builder needs to have all of the method parameters before it can create
+// a CXXMethodDecl. It collects them in addParam calls and when a first
+// method that builds the body is called or when access to 'this` is needed it
+// creates the CXXMethodDecl and ParmVarDecls instances. These can then be
+// referenced from the body building methods. Destructor or an explicit call to
+// finalizeMethod() will complete the method definition.
+//
+// The callBuiltin helper method passes in the resource handle as the first
+// argument of the builtin call. If this is not desired it takes a bool flag to
+// disable this.
+//
+// If the method that is being built has a non-void return type the
+// finalizeMethod will create a return statent with the value of the last
+// statement (unless the last statement is already a ReturnStmt).
+struct BuiltinTypeMethodBuilder {
+ struct MethodParam {
+ const IdentifierInfo &NameII;
+ QualType Ty;
+ HLSLParamModifierAttr::Spelling Modifier;
+ MethodParam(const IdentifierInfo &NameII, QualType Ty,
+ HLSLParamModifierAttr::Spelling Modifier)
+ : NameII(NameII), Ty(Ty), Modifier(Modifier) {}
+ };
+
+ BuiltinTypeDeclBuilder &DeclBuilder;
+ DeclarationNameInfo NameInfo;
+ QualType ReturnTy;
+ CXXMethodDecl *Method;
+ llvm::SmallVector<MethodParam> Params;
+ llvm::SmallVector<Stmt *> StmtsList;
+
+public:
+ BuiltinTypeMethodBuilder(Sema &S, BuiltinTypeDeclBuilder &DB, StringRef Name,
+ QualType ReturnTy)
+ : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr) {
+ const IdentifierInfo &II =
+ S.getASTContext().Idents.get(Name, tok::TokenKind::identifier);
+ NameInfo = DeclarationNameInfo(DeclarationName(&II), SourceLocation());
+ }
+
+ BuiltinTypeMethodBuilder &addParam(StringRef Name, QualType Ty,
+ HLSLParamModifierAttr::Spelling Modifier =
+ HLSLParamModifierAttr::Keyword_in) {
+ assert(Method == nullptr && "Cannot add param, method already created");
+ llvm_unreachable("not yet implemented");
+ }
+
+private:
+ void createMethodDecl() {
+ assert(Method == nullptr && "Method already created");
+
+ // create method type
+ ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+ SmallVector<QualType> ParamTypes;
+ for (MethodParam &MP : Params)
+ ParamTypes.emplace_back(MP.Ty);
+ QualType MethodTy = AST.getFunctionType(ReturnTy, ParamTypes,
+ FunctionProtoType::ExtProtoInfo());
+
+ // create method decl
+ auto *TSInfo = AST.getTrivialTypeSourceInfo(MethodTy, SourceLocation());
+ Method =
+ CXXMethodDecl::Create(AST, DeclBuilder.Record, SourceLocation(),
+ NameInfo, MethodTy, TSInfo, SC_None, false, false,
+ ConstexprSpecKind::Unspecified, SourceLocation());
+
+ // create params & set them to the function prototype
+ SmallVector<ParmVarDecl *> ParmDecls;
+ auto FnProtoLoc =
+ Method->getTypeSourceInfo()->getTypeLoc().getAs<FunctionProtoTypeLoc>();
+ for (int I = 0, E = Params.size(); I != E; I++) {
+ MethodParam &MP = Params[I];
+ ParmVarDecl *Parm = ParmVarDecl::Create(
+ AST, Method->getDeclContext(), SourceLocation(), SourceLocation(),
+ &MP.NameII, MP.Ty,
+ AST.getTrivialTypeSourceInfo(MP.Ty, SourceLocation()), SC_None,
+ nullptr);
+ if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
+ auto *Mod =
+ HLSLParamModifierAttr::Create(AST, SourceRange(), MP.Modifier);
+ Parm->addAttr(Mod);
+ }
+ ParmDecls.push_back(Parm);
+ FnProtoLoc.setParam(I, Parm);
+ }
+ Method->setParams({ParmDecls});
+ }
+
+public:
+ ~BuiltinTypeMethodBuilder() { finalizeMethod(); }
+
+ Expr *getResourceHandleExpr() {
+ // The first statement added to a method or access to 'this' creates the
+ // declaration.
+ if (!Method)
+ createMethodDecl();
+
+ ASTContext &AST = DeclBuilder.SemaRef....
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/117608
More information about the cfe-commits
mailing list