-
Notifications
You must be signed in to change notification settings - Fork 13.7k
[HLSL] Add Increment
/DecrementCounter
methods to structured buffers
#117608
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Introduces `__builtin_hlsl_buffer_update_counter` clang buildin that is used to implement IncrementCounter and DecrementCounter methods on RWStructuredBuffer and RasterizerOrderedStructuredBuffer. The builtin is translated to LLVM intrisics llvm.dx.bufferUpdateCounter/llvm.spv.bufferUpdateCounter. Introduces `BuiltinTypeMethodBuilder` helper in `HLSLExternalSemaSource` that 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(); Fixes llvm#113513
…der, fix generated CallExpr type
Do not complete definition if we already got one from precompiled headers.
… to simplify method building code
Few changes to minimize conflicts with another PR in progress. Update handle field name and tests.
…onExpr declaration
@llvm/pr-subscribers-hlsl Author: Helena Kotas (hekota) ChangesIntroduces The builtin is translated to LLVM intrisic Introduces
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:
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]
|
Introduces
__builtin_hlsl_buffer_update_counter
clang buildin that is used to implement theIncrementCounter
andDecrementCounter
methods onRWStructuredBuffer
andRasterizerOrderedStructuredBuffer
(see Note).The builtin is translated to LLVM intrisic
llvm.dx.bufferUpdateCounter
orllvm.spv.bufferUpdateCounter
.Introduces
BuiltinTypeMethodBuilder
helper inHLSLExternalSemaSource
that enables adding methods to builtin types using builder pattern like this:Fixes #113513
First version of this PR was reverted because of build break.