https://github.com/s-perron updated https://github.com/llvm/llvm-project/pull/186143
>From 4074305f957328670800c7db5e1142e4814702b6 Mon Sep 17 00:00:00 2001 From: Steven Perron <[email protected]> Date: Tue, 10 Mar 2026 13:39:50 -0400 Subject: [PATCH 1/2] [HLSL] Implement Texture2D::mips[][] We implement the Textur2D::mips[][] method. We follow the design in DXC. There is a new member called `mips` with type mips_type. The member will contain a copy of the handle for the texture. The type `mips_type` will have a member function `operator[]` that takes a level, and returns a `mips_slice_type`. The slice will contain the handle and the level. It also has an operator[] member function that take a coordinate. It will do a load from the handle with the level and coordinate, and return that value. Assisted-by: Gemini --- .../clang/Basic/DiagnosticSemaKinds.td | 2 + clang/include/clang/Sema/SemaHLSL.h | 1 + clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 319 ++++++++++++++++-- clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h | 18 +- clang/lib/Sema/HLSLExternalSemaSource.cpp | 1 + clang/lib/Sema/SemaHLSL.cpp | 43 +++ .../resources/Texture2D-Gather.hlsl | 4 +- .../CodeGenHLSL/resources/Texture2D-Mips.hlsl | 65 ++++ .../resources/Texture2D-Sample.hlsl | 4 +- .../resources/Texture2D-SampleBias.hlsl | 4 +- .../resources/Texture2D-SampleCmp.hlsl | 4 +- .../resources/Texture2D-SampleGrad.hlsl | 4 +- .../resources/Texture2D-SampleLevel.hlsl | 4 +- .../Texture2D-default-explicit-binding.hlsl | 4 +- .../resources/Texture2D-default.hlsl | 4 +- .../Texture2D-shorthand-contexts.hlsl | 2 +- .../test/SemaHLSL/Texture2D-mips-errors.hlsl | 19 ++ clang/test/SemaHLSL/Texture2D-mips-errors.ll | 235 +++++++++++++ 18 files changed, 679 insertions(+), 58 deletions(-) create mode 100644 clang/test/CodeGenHLSL/resources/Texture2D-Mips.hlsl create mode 100644 clang/test/SemaHLSL/Texture2D-mips-errors.hlsl create mode 100644 clang/test/SemaHLSL/Texture2D-mips-errors.ll diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e766d6e1dcf06..b7401ba3150a0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13672,6 +13672,8 @@ def warn_hlsl_assigning_local_resource_is_not_unique : Warning<"assignment of %0 to local resource %1 is not to the same " "unique global resource">, InGroup<HLSLExplicitBinding>; +def err_hlsl_intermediate_type_variable : Error< + "intermediate helper type %0 cannot be used as a variable">; def err_hlsl_push_constant_unique : Error<"cannot have more than one push constant block">; diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index cf9b8c39b109e..09b61e2f9dbb2 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -219,6 +219,7 @@ class SemaHLSL : public SemaBase { bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init); bool handleInitialization(VarDecl *VDecl, Expr *&Init); + bool CheckForMipsIntermediateType(QualType T, SourceLocation Loc); void deduceAddressSpace(VarDecl *Decl); QualType checkMatrixComponent(Sema &S, QualType baseType, ExprValueKind &VK, SourceLocation OpLoc, diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index a99b9446fd65f..a95fc5c6dbfc1 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -187,6 +187,7 @@ struct BuiltinTypeMethodBuilder { _5, Handle = 128, CounterHandle, + This, LastStmt }; @@ -226,12 +227,22 @@ struct BuiltinTypeMethodBuilder { template <typename TLHS, typename TRHS> BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS); template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr); + template <typename V, typename S> + BuiltinTypeMethodBuilder &concat(V Vec, S Scalar, QualType ResultTy); template <typename T> BuiltinTypeMethodBuilder &accessHandleFieldOnResource(T ResourceRecord); - template <typename ResourceT, typename ValueT> - BuiltinTypeMethodBuilder &setHandleFieldOnResource(ResourceT ResourceRecord, + template <typename T> + BuiltinTypeMethodBuilder &accessFieldOnResource(T ResourceRecord, + FieldDecl *Field); + template <typename ValueT> + BuiltinTypeMethodBuilder &setHandleFieldOnResource(LocalVar &ResourceRecord, ValueT HandleValue); + template <typename ResourceT, typename ValueT> + BuiltinTypeMethodBuilder &setFieldOnResource(ResourceT ResourceRecord, + ValueT HandleValue, + FieldDecl *HandleField); + void setMipsHandleField(LocalVar &ResourceRecord); template <typename T> BuiltinTypeMethodBuilder & accessCounterHandleFieldOnResource(T ResourceRecord); @@ -253,11 +264,6 @@ struct BuiltinTypeMethodBuilder { if (!Method) createDecl(); } - - template <typename ResourceT, typename ValueT> - BuiltinTypeMethodBuilder &setFieldOnResource(ResourceT ResourceRecord, - ValueT HandleValue, - FieldDecl *HandleField); }; TemplateParameterListBuilder::~TemplateParameterListBuilder() { @@ -414,6 +420,12 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) { return getResourceHandleExpr(); if (PH == PlaceHolder::CounterHandle) return getResourceCounterHandleExpr(); + if (PH == PlaceHolder::This) { + ASTContext &AST = DeclBuilder.SemaRef.getASTContext(); + return CXXThisExpr::Create(AST, SourceLocation(), + Method->getFunctionObjectParameterType(), + /*IsImplicit=*/true); + } if (PH == PlaceHolder::LastStmt) { assert(!StmtsList.empty() && "no statements in the list"); @@ -609,6 +621,44 @@ BuiltinTypeMethodBuilder::declareLocalVar(LocalVar &Var) { return *this; } +template <typename V, typename S> +BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::concat(V Vec, S Scalar, + QualType ResultTy) { + ASTContext &AST = DeclBuilder.SemaRef.getASTContext(); + Expr *VecExpr = convertPlaceholder(Vec); + auto *VecTy = VecExpr->getType()->castAs<VectorType>(); + Expr *ScalarExpr = convertPlaceholder(Scalar); + + // Save the vector to a local variable to avoid evaluating the placeholder + // multiple times or sharing the AST node. + LocalVar VecVar("vec_tmp", VecTy->desugar()); + declareLocalVar(VecVar); + assign(VecVar, VecExpr); + + QualType EltTy = VecTy->getElementType(); + unsigned NumElts = VecTy->getNumElements(); + + SmallVector<Expr *, 4> Elts; + for (unsigned I = 0; I < NumElts; ++I) { + Elts.push_back(new (AST) ArraySubscriptExpr( + convertPlaceholder(VecVar), DeclBuilder.getConstantIntExpr(I), EltTy, + VK_PRValue, OK_Ordinary, SourceLocation())); + } + Elts.push_back(ScalarExpr); + + auto *InitList = + new (AST) InitListExpr(AST, SourceLocation(), Elts, SourceLocation()); + InitList->setType(ResultTy); + + ExprResult Cast = DeclBuilder.SemaRef.BuildCStyleCastExpr( + SourceLocation(), AST.getTrivialTypeSourceInfo(ResultTy), + SourceLocation(), InitList); + assert(!Cast.isInvalid() && "Cast cannot fail!"); + StmtsList.push_back(Cast.get()); + + return *this; +} + BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnThis() { ASTContext &AST = DeclBuilder.SemaRef.getASTContext(); CXXThisExpr *ThisExpr = CXXThisExpr::Create( @@ -705,12 +755,69 @@ BuiltinTypeMethodBuilder::accessHandleFieldOnResource(T ResourceRecord) { return *this; } -template <typename ResourceT, typename ValueT> +template <typename T> +BuiltinTypeMethodBuilder & +BuiltinTypeMethodBuilder::accessFieldOnResource(T ResourceRecord, + FieldDecl *Field) { + ensureCompleteDecl(); + Expr *Base = convertPlaceholder(ResourceRecord); + + ASTContext &AST = DeclBuilder.SemaRef.getASTContext(); + auto *Member = + MemberExpr::CreateImplicit(AST, Base, /*IsArrow=*/false, Field, + Field->getType(), VK_LValue, OK_Ordinary); + StmtsList.push_back(Member); + return *this; +} + +void BuiltinTypeMethodBuilder::setMipsHandleField(LocalVar &ResourceRecord) { + FieldDecl *MipsField = DeclBuilder.Fields.lookup("mips"); + if (!MipsField) + return; + + ASTContext &AST = DeclBuilder.SemaRef.getASTContext(); + QualType MipsTy = MipsField->getType(); + const auto *RT = MipsTy->getAs<RecordType>(); + assert(RT && "mips field must be a record type"); + CXXRecordDecl *MipsRecord = cast<CXXRecordDecl>(RT->getDecl()); + + // The mips record should have a single field that is the handle. + assert(MipsRecord->field_begin() != MipsRecord->field_end() && + "mips_type must have at least one field"); + assert(std::next(MipsRecord->field_begin()) == MipsRecord->field_end() && + "mips_type must have exactly one field"); + FieldDecl *MipsHandleField = *MipsRecord->field_begin(); + + FieldDecl *HandleField = DeclBuilder.getResourceHandleField(); + Expr *HandleResExpr = convertPlaceholder(ResourceRecord); + MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit( + AST, HandleResExpr, false, HandleField, HandleField->getType(), VK_LValue, + OK_Ordinary); + + Expr *ResExpr = convertPlaceholder(ResourceRecord); + MemberExpr *MipsMemberExpr = + MemberExpr::CreateImplicit(AST, ResExpr, false, MipsField, + MipsField->getType(), VK_LValue, OK_Ordinary); + MemberExpr *MipsHandleMemberExpr = MemberExpr::CreateImplicit( + AST, MipsMemberExpr, false, MipsHandleField, MipsHandleField->getType(), + VK_LValue, OK_Ordinary); + + Stmt *AssignStmt = BinaryOperator::Create( + AST, MipsHandleMemberExpr, HandleMemberExpr, BO_Assign, + MipsHandleMemberExpr->getType(), ExprValueKind::VK_LValue, + ExprObjectKind::OK_Ordinary, SourceLocation(), FPOptionsOverride()); + + StmtsList.push_back(AssignStmt); +} + +template <typename ValueT> BuiltinTypeMethodBuilder & -BuiltinTypeMethodBuilder::setHandleFieldOnResource(ResourceT ResourceRecord, +BuiltinTypeMethodBuilder::setHandleFieldOnResource(LocalVar &ResourceRecord, ValueT HandleValue) { - return setFieldOnResource(ResourceRecord, HandleValue, - DeclBuilder.getResourceHandleField()); + setFieldOnResource(ResourceRecord, HandleValue, + DeclBuilder.getResourceHandleField()); + setMipsHandleField(ResourceRecord); + return *this; } template <typename ResourceT, typename ValueT> @@ -819,8 +926,10 @@ BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() { SourceLocation(), SourceLocation())); Method->setLexicalDeclContext(DeclBuilder.Record); Method->setAccess(AS_public); + Method->setImplicitlyInline(); Method->addAttr(AlwaysInlineAttr::CreateImplicit( AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline)); + Method->addAttr(ConvergentAttr::CreateImplicit(AST)); if (!TemplateParamDecls.empty()) { TemplateParams = TemplateParameterList::Create( AST, SourceLocation(), SourceLocation(), TemplateParamDecls, @@ -921,9 +1030,11 @@ BuiltinTypeDeclBuilder & BuiltinTypeDeclBuilder::addBufferHandles(ResourceClass RC, bool IsROV, bool RawBuffer, bool HasCounter, AccessSpecifier Access) { - addHandleMember(RC, ResourceDimension::Unknown, IsROV, RawBuffer, Access); + QualType ElementTy = getHandleElementType(); + addHandleMember(RC, ResourceDimension::Unknown, IsROV, RawBuffer, ElementTy, + Access); if (HasCounter) - addCounterHandleMember(RC, IsROV, RawBuffer, Access); + addCounterHandleMember(RC, IsROV, RawBuffer, ElementTy, Access); return *this; } @@ -931,39 +1042,59 @@ BuiltinTypeDeclBuilder & BuiltinTypeDeclBuilder::addTextureHandle(ResourceClass RC, bool IsROV, ResourceDimension RD, AccessSpecifier Access) { - addHandleMember(RC, RD, IsROV, /*RawBuffer=*/false, Access); + addHandleMember(RC, RD, IsROV, /*RawBuffer=*/false, getHandleElementType(), + Access); return *this; } BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addSamplerHandle() { addHandleMember(ResourceClass::Sampler, ResourceDimension::Unknown, - /*IsROV=*/false, /*RawBuffer=*/false); + /*IsROV=*/false, /*RawBuffer=*/false, getHandleElementType()); return *this; } BuiltinTypeDeclBuilder & -BuiltinTypeDeclBuilder::addHandleMember(ResourceClass RC, ResourceDimension RD, - bool IsROV, bool RawBuffer, - AccessSpecifier Access) { +BuiltinTypeDeclBuilder::addPrivateNestedRecord(StringRef Name, + CXXRecordDecl *&NestedRecord) { + assert(!Record->isCompleteDefinition() && "record is already complete"); + ASTContext &AST = SemaRef.getASTContext(); + IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier); + NestedRecord = CXXRecordDecl::Create(AST, TagDecl::TagKind::Struct, Record, + SourceLocation(), SourceLocation(), &II); + NestedRecord->setImplicit(true); + NestedRecord->setAccess(AccessSpecifier::AS_private); + NestedRecord->setLexicalDeclContext(Record); + Record->addDecl(NestedRecord); + return *this; +} + +BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember( + ResourceClass RC, ResourceDimension RD, bool IsROV, bool RawBuffer, + QualType ElementTy, AccessSpecifier Access) { return addResourceMember("__handle", RC, RD, IsROV, RawBuffer, - /*IsCounter=*/false, Access); + /*IsCounter=*/false, ElementTy, Access); } BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCounterHandleMember( - ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) { + ResourceClass RC, bool IsROV, bool RawBuffer, QualType ElementTy, + AccessSpecifier Access) { return addResourceMember("__counter_handle", RC, ResourceDimension::Unknown, IsROV, RawBuffer, - /*IsCounter=*/true, Access); + /*IsCounter=*/true, ElementTy, Access); } BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addResourceMember( StringRef MemberName, ResourceClass RC, ResourceDimension RD, bool IsROV, - bool RawBuffer, bool IsCounter, AccessSpecifier Access) { + bool RawBuffer, bool IsCounter, QualType ElementTy, + AccessSpecifier Access) { assert(!Record->isCompleteDefinition() && "record is already complete"); ASTContext &Ctx = SemaRef.getASTContext(); + + assert(!ElementTy.isNull() && + "The caller should always pass in the type for the handle."); TypeSourceInfo *ElementTypeInfo = - Ctx.getTrivialTypeSourceInfo(getHandleElementType(), SourceLocation()); + Ctx.getTrivialTypeSourceInfo(ElementTy, SourceLocation()); // add handle member with resource type attributes QualType AttributedResTy = QualType(); @@ -1197,13 +1328,12 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyConstructor() { BuiltinTypeMethodBuilder MMB(*this, /*Name=*/"", AST.VoidTy, /*IsConst=*/false, /*IsCtor=*/true); - MMB.addParam("other", ConstRecordRefType) - .accessHandleFieldOnResource(PH::_0) - .assign(PH::Handle, PH::LastStmt); + MMB.addParam("other", ConstRecordRefType); - if (getResourceCounterHandleField()) - MMB.accessCounterHandleFieldOnResource(PH::_0).assign(PH::CounterHandle, - PH::LastStmt); + for (auto *Field : Record->fields()) { + MMB.accessFieldOnResource(PH::_0, Field) + .setFieldOnResource(PH::This, PH::LastStmt, Field); + } return MMB.finalize(); } @@ -1220,13 +1350,12 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator() { using PH = BuiltinTypeMethodBuilder::PlaceHolder; DeclarationName Name = AST.DeclarationNames.getCXXOperatorName(OO_Equal); BuiltinTypeMethodBuilder MMB(*this, Name, RecordRefType); - MMB.addParam("other", ConstRecordRefType) - .accessHandleFieldOnResource(PH::_0) - .assign(PH::Handle, PH::LastStmt); + MMB.addParam("other", ConstRecordRefType); - if (getResourceCounterHandleField()) - MMB.accessCounterHandleFieldOnResource(PH::_0).assign(PH::CounterHandle, - PH::LastStmt); + for (auto *Field : Record->fields()) { + MMB.accessFieldOnResource(PH::_0, Field) + .setFieldOnResource(PH::This, PH::LastStmt, Field); + } return MMB.returnThis().finalize(); } @@ -1269,6 +1398,126 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadMethods() { return *this; } +CXXRecordDecl *BuiltinTypeDeclBuilder::addMipsSliceType(ResourceDimension Dim, + QualType ReturnType) { + ASTContext &AST = Record->getASTContext(); + uint32_t VecSize = getResourceDimensions(Dim); + QualType IntTy = AST.IntTy; + QualType IndexTy = VecSize > 1 ? AST.getExtVectorType(IntTy, VecSize) : IntTy; + QualType Int3Ty = AST.getExtVectorType(IntTy, VecSize + 1); + using PH = BuiltinTypeMethodBuilder::PlaceHolder; + + // Define the mips_slice_type which is returned by mips_type::operator[]. + // It holds the resource handle and the mip level. It has an operator[] + // that takes the coordinate and performs the actual resource load. + CXXRecordDecl *MipSliceRecord = nullptr; + addPrivateNestedRecord("mips_slice_type", MipSliceRecord); + BuiltinTypeDeclBuilder MipSliceBuilder(SemaRef, MipSliceRecord); + MipSliceBuilder.addHandleMember(getResourceAttrs().ResourceClass, Dim, + getResourceAttrs().IsROV, false, ReturnType, + AccessSpecifier::AS_public); + MipSliceBuilder.addMemberVariable("__level", IntTy, {}, + AccessSpecifier::AS_public); + + MipSliceBuilder.addDefaultHandleConstructor() + .addCopyConstructor() + .addCopyAssignmentOperator(); + + FieldDecl *LevelField = MipSliceBuilder.Fields["__level"]; + assert(LevelField && "Could not find the level field.\n"); + + DeclarationName SubscriptName = + AST.DeclarationNames.getCXXOperatorName(OO_Subscript); + + // operator[](intN coord) on mips_slice_type + BuiltinTypeMethodBuilder(MipSliceBuilder, SubscriptName, ReturnType, + /*IsConst=*/true) + .addParam("Coord", IndexTy) + .accessFieldOnResource(PH::This, LevelField) + .concat(PH::_0, PH::LastStmt, Int3Ty) + .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle, + PH::LastStmt) + .finalize(); + + MipSliceBuilder.completeDefinition(); + return MipSliceRecord; +} + +CXXRecordDecl *BuiltinTypeDeclBuilder::addMipsType(ResourceDimension Dim, + QualType ReturnType) { + ASTContext &AST = Record->getASTContext(); + QualType IntTy = AST.IntTy; + using PH = BuiltinTypeMethodBuilder::PlaceHolder; + + // First, define the mips_slice_type that will be returned by our operator[]. + CXXRecordDecl *MipSliceRecord = addMipsSliceType(Dim, ReturnType); + + // Define the mips_type, which provides the syntax `Resource.mips[level]`. + // It only holds the handle, and its operator[] returns a mips_slice_type + // initialized with the handle and the requested mip level. + CXXRecordDecl *MipRecord = nullptr; + addPrivateNestedRecord("mips_type", MipRecord); + BuiltinTypeDeclBuilder MipBuilder(SemaRef, MipRecord); + MipBuilder.addHandleMember(getResourceAttrs().ResourceClass, Dim, + getResourceAttrs().IsROV, false, ReturnType, + AccessSpecifier::AS_public); + + MipBuilder.addDefaultHandleConstructor() + .addCopyConstructor() + .addCopyAssignmentOperator(); + + QualType MipSliceTy = AST.getTagType( + ElaboratedTypeKeyword::None, + NestedNameSpecifierLoc().getNestedNameSpecifier(), MipSliceRecord, false); + + DeclarationName SubscriptName = + AST.DeclarationNames.getCXXOperatorName(OO_Subscript); + + // Locate the fields in the slice type so we can initialize them. + FieldDecl *MipSliceHandleField = nullptr; + FieldDecl *LevelField = nullptr; + for (auto *F : MipSliceRecord->fields()) { + if (F->getName() == "__handle") + MipSliceHandleField = F; + else if (F->getName() == "__level") + LevelField = F; + } + assert(MipSliceHandleField && LevelField && + "Could not find fields on mips_slice_type"); + + // operator[](int level) on mips_type + BuiltinTypeMethodBuilder::LocalVar MipSliceVar("slice", MipSliceTy); + BuiltinTypeMethodBuilder(MipBuilder, SubscriptName, MipSliceTy, + /*IsConst=*/true) + .addParam("Level", IntTy) + .declareLocalVar(MipSliceVar) + .accessHandleFieldOnResource(PH::This) + .setFieldOnResource(MipSliceVar, PH::LastStmt, MipSliceHandleField) + .setFieldOnResource(MipSliceVar, PH::_0, LevelField) + .returnValue(MipSliceVar) + .finalize(); + + MipBuilder.completeDefinition(); + return MipRecord; +} + +BuiltinTypeDeclBuilder & +BuiltinTypeDeclBuilder::addMipsMember(ResourceDimension Dim) { + assert(!Record->isCompleteDefinition() && "record is already complete"); + ASTContext &AST = Record->getASTContext(); + QualType ReturnType = getHandleElementType(); + + CXXRecordDecl *MipRecord = addMipsType(Dim, ReturnType); + + // Add the mips field to the texture + QualType MipTy = AST.getTagType( + ElaboratedTypeKeyword::None, + NestedNameSpecifierLoc().getNestedNameSpecifier(), MipRecord, false); + addMemberVariable("mips", MipTy, {}, AccessSpecifier::AS_public); + + return *this; +} + BuiltinTypeDeclBuilder & BuiltinTypeDeclBuilder::addTextureLoadMethods(ResourceDimension Dim) { assert(!Record->isCompleteDefinition() && "record is already complete"); diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h index 4fe6acabfac62..c903c5395cc8f 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h @@ -122,23 +122,29 @@ class BuiltinTypeDeclBuilder { BuiltinTypeDeclBuilder &addConsumeMethod(); BuiltinTypeDeclBuilder &addGetDimensionsMethodForBuffer(); + BuiltinTypeDeclBuilder &addMipsMember(ResourceDimension Dim); private: BuiltinTypeDeclBuilder &addCreateFromBinding(); BuiltinTypeDeclBuilder &addCreateFromImplicitBinding(); BuiltinTypeDeclBuilder &addCreateFromBindingWithImplicitCounter(); BuiltinTypeDeclBuilder &addCreateFromImplicitBindingWithImplicitCounter(); - BuiltinTypeDeclBuilder &addResourceMember(StringRef MemberName, - ResourceClass RC, - ResourceDimension RD, bool IsROV, - bool RawBuffer, bool IsCounter, - AccessSpecifier Access); + BuiltinTypeDeclBuilder & + addResourceMember(StringRef MemberName, ResourceClass RC, + ResourceDimension RD, bool IsROV, bool RawBuffer, + bool IsCounter, QualType ElementTy, + AccessSpecifier Access = AccessSpecifier::AS_private); + BuiltinTypeDeclBuilder &addPrivateNestedRecord(StringRef Name, + CXXRecordDecl *&NestedRecord); + CXXRecordDecl *addMipsSliceType(ResourceDimension Dim, QualType ReturnType); + CXXRecordDecl *addMipsType(ResourceDimension Dim, QualType ReturnType); BuiltinTypeDeclBuilder & addHandleMember(ResourceClass RC, ResourceDimension RD, bool IsROV, - bool RawBuffer, + bool RawBuffer, QualType ElementTy, AccessSpecifier Access = AccessSpecifier::AS_private); BuiltinTypeDeclBuilder & addCounterHandleMember(ResourceClass RC, bool IsROV, bool RawBuffer, + QualType ElementTy, AccessSpecifier Access = AccessSpecifier::AS_private); QualType getGatherReturnType(); FieldDecl *getResourceHandleField() const; diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index fb40ccc674349..8f99acb4dd442 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -260,6 +260,7 @@ static BuiltinTypeDeclBuilder setupTextureType(CXXRecordDecl *Decl, Sema &S, .addTextureHandle(RC, IsROV, Dim) .addTextureLoadMethods(Dim) .addArraySubscriptOperators(Dim) + .addMipsMember(Dim) .addDefaultHandleConstructor() .addCopyConstructor() .addCopyAssignmentOperator() diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index e2f2d6cb75c33..c09a059117010 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -5127,7 +5127,45 @@ void SemaHLSL::handleGlobalStructOrArrayOfWithResources(VarDecl *VD) { } } +bool SemaHLSL::CheckForMipsIntermediateType(QualType T, SourceLocation Loc) { + const auto *RT = T->getAs<RecordType>(); + if (!RT) + return false; + + const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); + if (!RD || !RD->isImplicit()) + return false; + + const DeclContext *DC = RD->getDeclContext(); + const auto *ParentRD = dyn_cast<CXXRecordDecl>(DC); + if (!ParentRD) + return false; + + const DeclContext *ParentDC = ParentRD->getDeclContext(); + QualType ParentTy = + SemaRef.getASTContext().getTypeDeclType(cast<TypeDecl>(ParentRD)); + if (!ParentTy->isHLSLResourceRecord()) { + return false; + } + + if (!ParentDC->isNamespace() && + cast<NamespaceDecl>(ParentDC)->getName() != "hlsl") + return false; + + if (RD->getIdentifier() && + (RD->getName() == "mips_type" || RD->getName() == "mips_slice_type")) { + SemaRef.Diag(Loc, diag::err_hlsl_intermediate_type_variable) << T; + return true; + } + return false; +} + void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) { + if (CheckForMipsIntermediateType(VD->getType(), VD->getLocation())) { + VD->setInvalidDecl(); + return; + } + if (VD->hasGlobalStorage()) { // make sure the declaration has a complete type if (SemaRef.RequireCompleteType( @@ -6083,6 +6121,11 @@ bool SemaHLSL::handleInitialization(VarDecl *VDecl, Expr *&Init) { if (VDecl->getType()->isHLSLResourceRecord() && !VDecl->hasGlobalStorage()) trackLocalResource(VDecl, Init); + if (CheckForMipsIntermediateType(VDecl->getType(), VDecl->getLocation())) { + VDecl->setInvalidDecl(); + return false; + } + const HLSLVkConstantIdAttr *ConstIdAttr = VDecl->getAttr<HLSLVkConstantIdAttr>(); if (!ConstIdAttr) diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-Gather.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-Gather.hlsl index 54d428285d88c..2f4cb1d5b98ed 100644 --- a/clang/test/CodeGenHLSL/resources/Texture2D-Gather.hlsl +++ b/clang/test/CodeGenHLSL/resources/Texture2D-Gather.hlsl @@ -1,11 +1,11 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV -// DXIL: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } +// DXIL: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2), %"struct.hlsl::Texture2D<>::mips_type" } // DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) } // DXIL: %"class.hlsl::SamplerComparisonState" = type { target("dx.Sampler", 0) } -// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0) } +// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0), %"struct.hlsl::Texture2D<>::mips_type" } // SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") } // SPIRV: %"class.hlsl::SamplerComparisonState" = type { target("spirv.Sampler") } diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-Mips.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-Mips.hlsl new file mode 100644 index 0000000000000..e934dcef5727e --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/Texture2D-Mips.hlsl @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-pixel -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL + +Texture2D<float4> t; + +// CHECK: define internal {{.*}} <4 x float> @test_mips(float vector[2])(<2 x float> {{.*}} %loc) #1 { +// CHECK: entry: +// CHECK: %[[LOC_ADDR:.*]] = alloca <2 x float>, align 8 +// CHECK: %[[REF_TMP:.*]] = alloca %"struct.hlsl::Texture2D<>::mips_slice_type", align 4 +// CHECK: store <2 x float> %loc, ptr %[[LOC_ADDR]], align 8 +// CHECK: call void @hlsl::Texture2D<float vector[4]>::mips_type::operator[](int) const(ptr {{.*}} %[[REF_TMP]], ptr {{.*}} getelementptr {{.*}} (i8, ptr @t, i32 4), i32 noundef 0) +// CHECK: %[[V0:.*]] = load <2 x float>, ptr %[[LOC_ADDR]], align 8 +// CHECK: %[[CONV:.*]] = fptosi <2 x float> %[[V0]] to <2 x i32> +// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::mips_slice_type::operator[](int vector[2]) const(ptr {{.*}} %[[REF_TMP]], <2 x i32> {{.*}} %[[CONV]]) +// CHECK: ret <4 x float> %[[CALL]] + +[shader("pixel")] +float4 test_mips(float2 loc : LOC) : SV_Target { + return t.mips[0][int2(loc)]; +} + +// TODO: Some of the checks use %{{.*}}. We should be trying to match the ids correctly to make sure we have the right connections. + +// CHECK: define linkonce_odr hidden void @hlsl::Texture2D<float vector[4]>::mips_type::operator[](int) const(ptr {{.*}} %agg.result, ptr {{.*}} %this, i32 {{.*}} %Level) +// CHECK: entry: +// CHECK: %{{.*}} = alloca ptr, align 4 +// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 4 +// CHECK: %[[LEVEL_ADDR:.*]] = alloca i32, align 4 +// CHECK: %[[SLICE:.*]] = alloca %"struct.hlsl::Texture2D<>::mips_slice_type", align 4 +// CHECK: store ptr %agg.result, ptr %{{.*}}, align 4 +// CHECK: store ptr %this, ptr %[[THIS_ADDR]], align 4 +// CHECK: store i32 %Level, ptr %[[LEVEL_ADDR]], align 4 +// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 4 +// CHECK: call void @hlsl::Texture2D<float vector[4]>::mips_slice_type::mips_slice_type()(ptr {{.*}} %[[SLICE]]) +// CHECK: %[[HANDLE_GEP:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2D<>::mips_type", ptr %[[THIS1]], i32 0, i32 0 +// CHECK: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %[[HANDLE_GEP]], align 4 +// CHECK: %[[HANDLE_GEP2:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2D<>::mips_slice_type", ptr %[[SLICE]], i32 0, i32 0 +// CHECK: store target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE]], ptr %[[HANDLE_GEP2]], align 4 +// CHECK: %[[L_VAL:.*]] = load i32, ptr %[[LEVEL_ADDR]], align 4 +// CHECK: %[[LEVEL_GEP:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2D<>::mips_slice_type", ptr %[[SLICE]], i32 0, i32 1 +// CHECK: store i32 %[[L_VAL]], ptr %[[LEVEL_GEP]], align 4 +// CHECK: call void @hlsl::Texture2D<float vector[4]>::mips_slice_type::mips_slice_type(hlsl::Texture2D<float vector[4]>::mips_slice_type const&)(ptr noundef nonnull align 4 dereferenceable(8) %agg.result, ptr noundef nonnull align 4 dereferenceable(8) %[[SLICE]]) + +// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::mips_slice_type::operator[](int vector[2]) const(ptr {{.*}} %[[THIS:.*]], <2 x i32> noundef %[[COORD:.*]]) +// CHECK: entry: +// CHECK: %[[COORD_ADDR:.*]] = alloca <2 x i32>, align 8 +// CHECK: %[[VEC_TMP:.*]] = alloca <2 x i32>, align 8 +// CHECK: store <2 x i32> %[[COORD]], ptr %[[COORD_ADDR]], align 8 +// CHECK: %[[THIS1:.*]] = load ptr, ptr %{{.*}}, align 4 +// CHECK: %[[COORD_PARAM:.*]] = load <2 x i32>, ptr %[[COORD_ADDR]], align 8 +// CHECK: store <2 x i32> %[[COORD_PARAM]], ptr %[[VEC_TMP]], align 8 +// CHECK: %[[HANDLE_PTR:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2D<>::mips_slice_type", ptr %[[THIS1]], i32 0, i32 0 +// CHECK: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %[[HANDLE_PTR]], align 4 +// CHECK: %[[COORD_VAL:.*]] = load <2 x i32>, ptr %[[VEC_TMP]], align 8 +// CHECK: %[[VECEXT:.*]] = extractelement <2 x i32> %[[COORD_VAL]], i32 0 +// CHECK: %[[VECINIT:.*]] = insertelement <3 x i32> poison, i32 %[[VECEXT]], i32 0 +// CHECK: %[[COORD_VAL2:.*]] = load <2 x i32>, ptr %[[VEC_TMP]], align 8 +// CHECK: %[[VECEXT2:.*]] = extractelement <2 x i32> %[[COORD_VAL2]], i32 1 +// CHECK: %[[VECINIT3:.*]] = insertelement <3 x i32> %[[VECINIT]], i32 %[[VECEXT2]], i32 1 +// CHECK: %[[LEVEL_PTR:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2D<>::mips_slice_type", ptr %[[THIS1]], i32 0, i32 1 +// CHECK: %[[LEVEL_VAL:.*]] = load i32, ptr %[[LEVEL_PTR]], align 4 +// CHECK: %[[VECINIT4:.*]] = insertelement <3 x i32> %[[VECINIT3]], i32 %[[LEVEL_VAL]], i32 2 +// CHECK: %[[COORD_X:.*]] = shufflevector <3 x i32> %[[VECINIT4]], <3 x i32> poison, <2 x i32> <i32 0, i32 1> +// CHECK: %[[LOD:.*]] = extractelement <3 x i32> %[[VECINIT4]], i64 2 +// DXIL: %[[RES:.*]] = call {{.*}} <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_0_0_0_2t.v2i32.i32.v2i32(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE]], <2 x i32> %[[COORD_X]], i32 %[[LOD]], <2 x i32> zeroinitializer) +// CHECK: ret <4 x float> %[[RES]] diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-Sample.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-Sample.hlsl index 93bed2f2b7c27..e37e182be6b44 100644 --- a/clang/test/CodeGenHLSL/resources/Texture2D-Sample.hlsl +++ b/clang/test/CodeGenHLSL/resources/Texture2D-Sample.hlsl @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV -// DXIL: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } +// DXIL: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2), %"struct.hlsl::Texture2D<>::mips_type" } // DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) } -// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0) } +// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0), %"struct.hlsl::Texture2D<>::mips_type" } // SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") } Texture2D<float4> t; diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-SampleBias.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-SampleBias.hlsl index c138e7f0a6c8b..481a66c7a59a9 100644 --- a/clang/test/CodeGenHLSL/resources/Texture2D-SampleBias.hlsl +++ b/clang/test/CodeGenHLSL/resources/Texture2D-SampleBias.hlsl @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV -// DXIL: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } +// DXIL: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2), %"struct.hlsl::Texture2D<>::mips_type" } // DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) } -// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0) } +// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0), %"struct.hlsl::Texture2D<>::mips_type" } // SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") } Texture2D<float4> t; diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-SampleCmp.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-SampleCmp.hlsl index b76b02177abbc..5262aed2816ef 100644 --- a/clang/test/CodeGenHLSL/resources/Texture2D-SampleCmp.hlsl +++ b/clang/test/CodeGenHLSL/resources/Texture2D-SampleCmp.hlsl @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV -// DXIL: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } +// DXIL: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2), %"struct.hlsl::Texture2D<>::mips_type" } // DXIL: %"class.hlsl::SamplerComparisonState" = type { target("dx.Sampler", 0) } -// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0) } +// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0), %"struct.hlsl::Texture2D<>::mips_type" } // SPIRV: %"class.hlsl::SamplerComparisonState" = type { target("spirv.Sampler") } Texture2D<float4> t; diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-SampleGrad.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-SampleGrad.hlsl index 279521c0bb988..1a2cd93a34168 100644 --- a/clang/test/CodeGenHLSL/resources/Texture2D-SampleGrad.hlsl +++ b/clang/test/CodeGenHLSL/resources/Texture2D-SampleGrad.hlsl @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV -// DXIL: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } +// DXIL: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2), %"struct.hlsl::Texture2D<>::mips_type" } // DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) } -// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0) } +// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0), %"struct.hlsl::Texture2D<>::mips_type" } // SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") } Texture2D<float4> t; diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-SampleLevel.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-SampleLevel.hlsl index bcd025c164ac0..85fae6ea278f2 100644 --- a/clang/test/CodeGenHLSL/resources/Texture2D-SampleLevel.hlsl +++ b/clang/test/CodeGenHLSL/resources/Texture2D-SampleLevel.hlsl @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV -// DXIL: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } +// DXIL: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2), %"struct.hlsl::Texture2D<>::mips_type" } // DXIL: %"class.hlsl::SamplerState" = type { target("dx.Sampler", 0) } -// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0) } +// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0), %"struct.hlsl::Texture2D<>::mips_type" } // SPIRV: %"class.hlsl::SamplerState" = type { target("spirv.Sampler") } Texture2D<float4> t; diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-default-explicit-binding.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-default-explicit-binding.hlsl index 06b4cb7ec9900..9a7819364ee83 100644 --- a/clang/test/CodeGenHLSL/resources/Texture2D-default-explicit-binding.hlsl +++ b/clang/test/CodeGenHLSL/resources/Texture2D-default-explicit-binding.hlsl @@ -5,8 +5,8 @@ SamplerState g_s : register(s0); Texture2D<> default_template : register(t1, space2); Texture2D implicit_template : register(t0, space1); -// CHECK: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } -// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0) } +// CHECK: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2), %"struct.hlsl::Texture2D<>::mips_type" } +// SPIRV: %"class.hlsl::Texture2D" = type { target("spirv.Image", float, 1, 2, 0, 0, 1, 0), %"struct.hlsl::Texture2D<>::mips_type" } // CHECK: @{{.*}}default_template = internal global %"class.hlsl::Texture2D" poison, align {{[0-9]+}} // CHECK: @{{.*}}implicit_template = internal global %"class.hlsl::Texture2D" poison, align {{[0-9]+}} diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-default.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-default.hlsl index 5b5bb737a7958..8ff981e4fa512 100644 --- a/clang/test/CodeGenHLSL/resources/Texture2D-default.hlsl +++ b/clang/test/CodeGenHLSL/resources/Texture2D-default.hlsl @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -std=hlsl202x -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | FileCheck %s -// CHECK: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } -// CHECK: %"class.hlsl::Texture2D.0" = type { target("dx.Texture", float, 0, 0, 0, 2) } +// CHECK: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2), %"struct.hlsl::Texture2D<>::mips_type" } +// CHECK: %"class.hlsl::Texture2D.0" = type { target("dx.Texture", float, 0, 0, 0, 2), %"struct.hlsl::Texture2D<float>::mips_type" } // CHECK: @{{.*}}t1 = internal global %"class.hlsl::Texture2D" poison, align 4 Texture2D<> t1; diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-shorthand-contexts.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-shorthand-contexts.hlsl index 71ce46232d088..0367e2360242b 100644 --- a/clang/test/CodeGenHLSL/resources/Texture2D-shorthand-contexts.hlsl +++ b/clang/test/CodeGenHLSL/resources/Texture2D-shorthand-contexts.hlsl @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s -// CHECK: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } +// CHECK: %"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2), %"struct.hlsl::Texture2D<>::mips_type" } SamplerState g_s : register(s0); diff --git a/clang/test/SemaHLSL/Texture2D-mips-errors.hlsl b/clang/test/SemaHLSL/Texture2D-mips-errors.hlsl new file mode 100644 index 0000000000000..12b0d17c921c6 --- /dev/null +++ b/clang/test/SemaHLSL/Texture2D-mips-errors.hlsl @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -verify %s + +Texture2D<float4> t; + +void main() { + // expected-error@+3 {{'mips_type' is a private member of 'hlsl::Texture2D<>'}} + // expected-note@*:* {{implicitly declared private here}} + // expected-error@+1 {{intermediate helper type 'Texture2D<float4>::mips_type' cannot be used as a variable}} + Texture2D<float4>::mips_type a; + + // expected-error@+3 {{'mips_slice_type' is a private member of 'hlsl::Texture2D<>'}} + // expected-note@*:* {{implicitly declared private here}} + // expected-error@+1 {{intermediate helper type 'Texture2D<float4>::mips_slice_type' cannot be used as a variable}} + Texture2D<float4>::mips_slice_type b; + + // expected-warning@+2 {{'auto' type specifier is a HLSL 202y extension}} + // expected-error@+1 {{intermediate helper type 'mips_type' cannot be used as a variable}} + auto c = t.mips; +} diff --git a/clang/test/SemaHLSL/Texture2D-mips-errors.ll b/clang/test/SemaHLSL/Texture2D-mips-errors.ll new file mode 100644 index 0000000000000..cf4f3a7f7207e --- /dev/null +++ b/clang/test/SemaHLSL/Texture2D-mips-errors.ll @@ -0,0 +1,235 @@ +; ModuleID = '/usr/local/google/home/stevenperron/spirv/llvm/texture-2d-implementation/clang/test/SemaHLSL/Texture2D-mips-errors.hlsl' +source_filename = "/usr/local/google/home/stevenperron/spirv/llvm/texture-2d-implementation/clang/test/SemaHLSL/Texture2D-mips-errors.hlsl" +target datalayout = "e-m:e-ve-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" +target triple = "dxilv1.0-pc-shadermodel6.0-library" + +%"class.hlsl::Texture2D" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2), %"struct.hlsl::Texture2D<>::mips_type" } +%"struct.hlsl::Texture2D<>::mips_type" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2) } +%"struct.hlsl::Texture2D<>::mips_slice_type" = type { target("dx.Texture", <4 x float>, 0, 0, 0, 2), i32 } + +@_ZL1t = internal global %"class.hlsl::Texture2D" poison, align 4 [email protected] = private unnamed_addr constant [2 x i8] c"t\00", align 1 [email protected]_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_Texture2D_mips_errors.hlsl, ptr null }] + +; Function Attrs: alwaysinline convergent nounwind +define internal void @__cxx_global_var_init() #0 { +entry: + call void @_ZN4hlsl9Texture2DIDv4_fE27__createFromImplicitBindingEjjijPKc(ptr dead_on_unwind writable sret(%"class.hlsl::Texture2D") align 4 @_ZL1t, i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @.str) #3 + ret void +} + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define linkonce_odr hidden void @_ZN4hlsl9Texture2DIDv4_fE27__createFromImplicitBindingEjjijPKc(ptr dead_on_unwind noalias writable sret(%"class.hlsl::Texture2D") align 4 %agg.result, i32 noundef %orderId, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) #1 align 2 { +entry: + %result.ptr = alloca ptr, align 4 + %orderId.addr = alloca i32, align 4 + %spaceNo.addr = alloca i32, align 4 + %range.addr = alloca i32, align 4 + %index.addr = alloca i32, align 4 + %name.addr = alloca ptr, align 4 + %tmp = alloca %"class.hlsl::Texture2D", align 4 + store ptr %agg.result, ptr %result.ptr, align 4 + store i32 %orderId, ptr %orderId.addr, align 4 + store i32 %spaceNo, ptr %spaceNo.addr, align 4 + store i32 %range, ptr %range.addr, align 4 + store i32 %index, ptr %index.addr, align 4 + store ptr %name, ptr %name.addr, align 4 + call void @_ZN4hlsl9Texture2DIDv4_fEC1Ev(ptr noundef nonnull align 4 dereferenceable(8) %tmp) #3 + %0 = load i32, ptr %orderId.addr, align 4 + %1 = load i32, ptr %spaceNo.addr, align 4 + %2 = load i32, ptr %range.addr, align 4 + %3 = load i32, ptr %index.addr, align 4 + %4 = load ptr, ptr %name.addr, align 4 + %5 = call target("dx.Texture", <4 x float>, 0, 0, 0, 2) @llvm.dx.resource.handlefromimplicitbinding.tdx.Texture_v4f32_0_0_0_2t(i32 %0, i32 %1, i32 %2, i32 %3, ptr %4) + %__handle = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %tmp, i32 0, i32 0 + store target("dx.Texture", <4 x float>, 0, 0, 0, 2) %5, ptr %__handle, align 4 + %__handle1 = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %tmp, i32 0, i32 0 + %6 = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %__handle1, align 4 + %mips = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %tmp, i32 0, i32 1 + %__handle2 = getelementptr inbounds nuw %"struct.hlsl::Texture2D<>::mips_type", ptr %mips, i32 0, i32 0 + store target("dx.Texture", <4 x float>, 0, 0, 0, 2) %6, ptr %__handle2, align 4 + call void @_ZN4hlsl9Texture2DIDv4_fEC1ERKS2_(ptr noundef nonnull align 4 dereferenceable(8) %agg.result, ptr noundef nonnull align 4 dereferenceable(8) %tmp) #3 + ret void +} + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define hidden void @_Z4mainv() #1 { +entry: + %a = alloca %"struct.hlsl::Texture2D<>::mips_type", align 4 + %b = alloca %"struct.hlsl::Texture2D<>::mips_slice_type", align 4 + %c = alloca %"struct.hlsl::Texture2D<>::mips_type", align 4 + call void @_ZN4hlsl9Texture2DIDv4_fE9mips_typeC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %a) #3 + call void @_ZN4hlsl9Texture2DIDv4_fE15mips_slice_typeC1Ev(ptr noundef nonnull align 4 dereferenceable(8) %b) #3 + call void @_ZN4hlsl9Texture2DIDv4_fE9mips_typeC1ERKS3_(ptr noundef nonnull align 4 dereferenceable(4) %c, ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds nuw (i8, ptr @_ZL1t, i32 4)) #3 + ret void +} + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define linkonce_odr hidden void @_ZN4hlsl9Texture2DIDv4_fE9mips_typeC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) unnamed_addr #1 align 2 { +entry: + %this.addr = alloca ptr, align 4 + store ptr %this, ptr %this.addr, align 4 + %this1 = load ptr, ptr %this.addr, align 4 + call void @_ZN4hlsl9Texture2DIDv4_fE9mips_typeC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this1) #3 + ret void +} + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define linkonce_odr hidden void @_ZN4hlsl9Texture2DIDv4_fE15mips_slice_typeC1Ev(ptr noundef nonnull align 4 dereferenceable(8) %this) unnamed_addr #1 align 2 { +entry: + %this.addr = alloca ptr, align 4 + store ptr %this, ptr %this.addr, align 4 + %this1 = load ptr, ptr %this.addr, align 4 + call void @_ZN4hlsl9Texture2DIDv4_fE15mips_slice_typeC2Ev(ptr noundef nonnull align 4 dereferenceable(8) %this1) #3 + ret void +} + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define linkonce_odr hidden void @_ZN4hlsl9Texture2DIDv4_fE9mips_typeC1ERKS3_(ptr noundef nonnull align 4 dereferenceable(4) %this, ptr noundef nonnull align 4 dereferenceable(4) %other) unnamed_addr #1 align 2 { +entry: + %this.addr = alloca ptr, align 4 + %other.addr = alloca ptr, align 4 + store ptr %this, ptr %this.addr, align 4 + store ptr %other, ptr %other.addr, align 4 + %this1 = load ptr, ptr %this.addr, align 4 + %0 = load ptr, ptr %other.addr, align 4 + call void @_ZN4hlsl9Texture2DIDv4_fE9mips_typeC2ERKS3_(ptr noundef nonnull align 4 dereferenceable(4) %this1, ptr noundef nonnull align 4 dereferenceable(4) %0) #3 + ret void +} + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define linkonce_odr hidden void @_ZN4hlsl9Texture2DIDv4_fEC1Ev(ptr noundef nonnull align 4 dereferenceable(8) %this) unnamed_addr #1 align 2 { +entry: + %this.addr = alloca ptr, align 4 + store ptr %this, ptr %this.addr, align 4 + %this1 = load ptr, ptr %this.addr, align 4 + call void @_ZN4hlsl9Texture2DIDv4_fEC2Ev(ptr noundef nonnull align 4 dereferenceable(8) %this1) #3 + ret void +} + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) +declare target("dx.Texture", <4 x float>, 0, 0, 0, 2) @llvm.dx.resource.handlefromimplicitbinding.tdx.Texture_v4f32_0_0_0_2t(i32, i32, i32, i32, ptr) #2 + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define linkonce_odr hidden void @_ZN4hlsl9Texture2DIDv4_fEC1ERKS2_(ptr noundef nonnull align 4 dereferenceable(8) %this, ptr noundef nonnull align 4 dereferenceable(8) %other) unnamed_addr #1 align 2 { +entry: + %this.addr = alloca ptr, align 4 + %other.addr = alloca ptr, align 4 + store ptr %this, ptr %this.addr, align 4 + store ptr %other, ptr %other.addr, align 4 + %this1 = load ptr, ptr %this.addr, align 4 + %0 = load ptr, ptr %other.addr, align 4 + call void @_ZN4hlsl9Texture2DIDv4_fEC2ERKS2_(ptr noundef nonnull align 4 dereferenceable(8) %this1, ptr noundef nonnull align 4 dereferenceable(8) %0) #3 + ret void +} + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define linkonce_odr hidden void @_ZN4hlsl9Texture2DIDv4_fEC2Ev(ptr noundef nonnull align 4 dereferenceable(8) %this) unnamed_addr #1 align 2 { +entry: + %this.addr = alloca ptr, align 4 + store ptr %this, ptr %this.addr, align 4 + %this1 = load ptr, ptr %this.addr, align 4 + %mips = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %this1, i32 0, i32 1 + call void @_ZN4hlsl9Texture2DIDv4_fE9mips_typeC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %mips) #3 + %__handle = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %this1, i32 0, i32 0 + store target("dx.Texture", <4 x float>, 0, 0, 0, 2) poison, ptr %__handle, align 4 + ret void +} + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define linkonce_odr hidden void @_ZN4hlsl9Texture2DIDv4_fEC2ERKS2_(ptr noundef nonnull align 4 dereferenceable(8) %this, ptr noundef nonnull align 4 dereferenceable(8) %other) unnamed_addr #1 align 2 { +entry: + %this.addr = alloca ptr, align 4 + %other.addr = alloca ptr, align 4 + store ptr %this, ptr %this.addr, align 4 + store ptr %other, ptr %other.addr, align 4 + %this1 = load ptr, ptr %this.addr, align 4 + %mips = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %this1, i32 0, i32 1 + call void @_ZN4hlsl9Texture2DIDv4_fE9mips_typeC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %mips) #3 + %0 = load ptr, ptr %other.addr, align 4, !nonnull !3, !align !4 + %__handle = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %0, i32 0, i32 0 + %1 = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %__handle, align 4 + %__handle2 = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %this1, i32 0, i32 0 + store target("dx.Texture", <4 x float>, 0, 0, 0, 2) %1, ptr %__handle2, align 4 + %2 = load ptr, ptr %other.addr, align 4, !nonnull !3, !align !4 + %mips3 = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %2, i32 0, i32 1 + %mips4 = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %this1, i32 0, i32 1 + %call = call noundef nonnull align 4 dereferenceable(4) ptr @_ZN4hlsl9Texture2DIDv4_fE9mips_typeaSERKS3_(ptr noundef nonnull align 4 dereferenceable(4) %mips4, ptr noundef nonnull align 4 dereferenceable(4) %mips3) #3 + ret void +} + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define linkonce_odr hidden noundef nonnull align 4 dereferenceable(4) ptr @_ZN4hlsl9Texture2DIDv4_fE9mips_typeaSERKS3_(ptr noundef nonnull align 4 dereferenceable(4) %this, ptr noundef nonnull align 4 dereferenceable(4) %other) #1 align 2 { +entry: + %this.addr = alloca ptr, align 4 + %other.addr = alloca ptr, align 4 + store ptr %this, ptr %this.addr, align 4 + store ptr %other, ptr %other.addr, align 4 + %this1 = load ptr, ptr %this.addr, align 4 + %0 = load ptr, ptr %other.addr, align 4, !nonnull !3, !align !4 + %__handle = getelementptr inbounds nuw %"struct.hlsl::Texture2D<>::mips_type", ptr %0, i32 0, i32 0 + %1 = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %__handle, align 4 + %__handle2 = getelementptr inbounds nuw %"struct.hlsl::Texture2D<>::mips_type", ptr %this1, i32 0, i32 0 + store target("dx.Texture", <4 x float>, 0, 0, 0, 2) %1, ptr %__handle2, align 4 + ret ptr %this1 +} + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define linkonce_odr hidden void @_ZN4hlsl9Texture2DIDv4_fE9mips_typeC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) unnamed_addr #1 align 2 { +entry: + %this.addr = alloca ptr, align 4 + store ptr %this, ptr %this.addr, align 4 + %this1 = load ptr, ptr %this.addr, align 4 + %__handle = getelementptr inbounds nuw %"struct.hlsl::Texture2D<>::mips_type", ptr %this1, i32 0, i32 0 + store target("dx.Texture", <4 x float>, 0, 0, 0, 2) poison, ptr %__handle, align 4 + ret void +} + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define linkonce_odr hidden void @_ZN4hlsl9Texture2DIDv4_fE15mips_slice_typeC2Ev(ptr noundef nonnull align 4 dereferenceable(8) %this) unnamed_addr #1 align 2 { +entry: + %this.addr = alloca ptr, align 4 + store ptr %this, ptr %this.addr, align 4 + %this1 = load ptr, ptr %this.addr, align 4 + %__handle = getelementptr inbounds nuw %"struct.hlsl::Texture2D<>::mips_slice_type", ptr %this1, i32 0, i32 0 + store target("dx.Texture", <4 x float>, 0, 0, 0, 2) poison, ptr %__handle, align 4 + ret void +} + +; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind +define linkonce_odr hidden void @_ZN4hlsl9Texture2DIDv4_fE9mips_typeC2ERKS3_(ptr noundef nonnull align 4 dereferenceable(4) %this, ptr noundef nonnull align 4 dereferenceable(4) %other) unnamed_addr #1 align 2 { +entry: + %this.addr = alloca ptr, align 4 + %other.addr = alloca ptr, align 4 + store ptr %this, ptr %this.addr, align 4 + store ptr %other, ptr %other.addr, align 4 + %this1 = load ptr, ptr %this.addr, align 4 + %0 = load ptr, ptr %other.addr, align 4, !nonnull !3, !align !4 + %__handle = getelementptr inbounds nuw %"struct.hlsl::Texture2D<>::mips_type", ptr %0, i32 0, i32 0 + %1 = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %__handle, align 4 + %__handle2 = getelementptr inbounds nuw %"struct.hlsl::Texture2D<>::mips_type", ptr %this1, i32 0, i32 0 + store target("dx.Texture", <4 x float>, 0, 0, 0, 2) %1, ptr %__handle2, align 4 + ret void +} + +; Function Attrs: alwaysinline convergent nounwind +define internal void @_GLOBAL__sub_I_Texture2D_mips_errors.hlsl() #0 { +entry: + call void @__cxx_global_var_init() + ret void +} + +attributes #0 = { alwaysinline convergent nounwind "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #1 = { alwaysinline convergent mustprogress norecurse nounwind "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #2 = { nocallback nofree nosync nounwind willreturn memory(none) } +attributes #3 = { convergent } + +!dx.valver = !{!0} +!llvm.module.flags = !{!1} +!llvm.ident = !{!2} + +!0 = !{i32 1, i32 8} +!1 = !{i32 4, !"dx.disable_optimizations", i32 1} +!2 = !{!"clang version 23.0.0git ([email protected]:llvm/llvm-project.git 61ec7e51067976def87b0fd8e88f084182349d51)"} +!3 = !{} +!4 = !{i64 4} >From e106d121fd2a1c8c641ee5511b9bc1bad8240918 Mon Sep 17 00:00:00 2001 From: Steven Perron <[email protected]> Date: Tue, 24 Mar 2026 09:35:37 -0400 Subject: [PATCH 2/2] Remove alignment checks in new test. No necessary. --- .../CodeGenHLSL/resources/Texture2D-Mips.hlsl | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-Mips.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-Mips.hlsl index e934dcef5727e..9ab2eb08e2d00 100644 --- a/clang/test/CodeGenHLSL/resources/Texture2D-Mips.hlsl +++ b/clang/test/CodeGenHLSL/resources/Texture2D-Mips.hlsl @@ -4,11 +4,11 @@ Texture2D<float4> t; // CHECK: define internal {{.*}} <4 x float> @test_mips(float vector[2])(<2 x float> {{.*}} %loc) #1 { // CHECK: entry: -// CHECK: %[[LOC_ADDR:.*]] = alloca <2 x float>, align 8 -// CHECK: %[[REF_TMP:.*]] = alloca %"struct.hlsl::Texture2D<>::mips_slice_type", align 4 -// CHECK: store <2 x float> %loc, ptr %[[LOC_ADDR]], align 8 +// CHECK: %[[LOC_ADDR:.*]] = alloca <2 x float> +// CHECK: %[[REF_TMP:.*]] = alloca %"struct.hlsl::Texture2D<>::mips_slice_type" +// CHECK: store <2 x float> %loc, ptr %[[LOC_ADDR]] // CHECK: call void @hlsl::Texture2D<float vector[4]>::mips_type::operator[](int) const(ptr {{.*}} %[[REF_TMP]], ptr {{.*}} getelementptr {{.*}} (i8, ptr @t, i32 4), i32 noundef 0) -// CHECK: %[[V0:.*]] = load <2 x float>, ptr %[[LOC_ADDR]], align 8 +// CHECK: %[[V0:.*]] = load <2 x float>, ptr %[[LOC_ADDR]] // CHECK: %[[CONV:.*]] = fptosi <2 x float> %[[V0]] to <2 x i32> // CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::mips_slice_type::operator[](int vector[2]) const(ptr {{.*}} %[[REF_TMP]], <2 x i32> {{.*}} %[[CONV]]) // CHECK: ret <4 x float> %[[CALL]] @@ -22,42 +22,42 @@ float4 test_mips(float2 loc : LOC) : SV_Target { // CHECK: define linkonce_odr hidden void @hlsl::Texture2D<float vector[4]>::mips_type::operator[](int) const(ptr {{.*}} %agg.result, ptr {{.*}} %this, i32 {{.*}} %Level) // CHECK: entry: -// CHECK: %{{.*}} = alloca ptr, align 4 -// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 4 -// CHECK: %[[LEVEL_ADDR:.*]] = alloca i32, align 4 -// CHECK: %[[SLICE:.*]] = alloca %"struct.hlsl::Texture2D<>::mips_slice_type", align 4 -// CHECK: store ptr %agg.result, ptr %{{.*}}, align 4 -// CHECK: store ptr %this, ptr %[[THIS_ADDR]], align 4 -// CHECK: store i32 %Level, ptr %[[LEVEL_ADDR]], align 4 -// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 4 +// CHECK: %{{.*}} = alloca ptr +// CHECK: %[[THIS_ADDR:.*]] = alloca ptr +// CHECK: %[[LEVEL_ADDR:.*]] = alloca i32 +// CHECK: %[[SLICE:.*]] = alloca %"struct.hlsl::Texture2D<>::mips_slice_type" +// CHECK: store ptr %agg.result, ptr %{{.*}} +// CHECK: store ptr %this, ptr %[[THIS_ADDR]] +// CHECK: store i32 %Level, ptr %[[LEVEL_ADDR]] +// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]] // CHECK: call void @hlsl::Texture2D<float vector[4]>::mips_slice_type::mips_slice_type()(ptr {{.*}} %[[SLICE]]) // CHECK: %[[HANDLE_GEP:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2D<>::mips_type", ptr %[[THIS1]], i32 0, i32 0 -// CHECK: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %[[HANDLE_GEP]], align 4 +// CHECK: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %[[HANDLE_GEP]] // CHECK: %[[HANDLE_GEP2:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2D<>::mips_slice_type", ptr %[[SLICE]], i32 0, i32 0 -// CHECK: store target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE]], ptr %[[HANDLE_GEP2]], align 4 -// CHECK: %[[L_VAL:.*]] = load i32, ptr %[[LEVEL_ADDR]], align 4 +// CHECK: store target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE]], ptr %[[HANDLE_GEP2]] +// CHECK: %[[L_VAL:.*]] = load i32, ptr %[[LEVEL_ADDR]] // CHECK: %[[LEVEL_GEP:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2D<>::mips_slice_type", ptr %[[SLICE]], i32 0, i32 1 -// CHECK: store i32 %[[L_VAL]], ptr %[[LEVEL_GEP]], align 4 +// CHECK: store i32 %[[L_VAL]], ptr %[[LEVEL_GEP]] // CHECK: call void @hlsl::Texture2D<float vector[4]>::mips_slice_type::mips_slice_type(hlsl::Texture2D<float vector[4]>::mips_slice_type const&)(ptr noundef nonnull align 4 dereferenceable(8) %agg.result, ptr noundef nonnull align 4 dereferenceable(8) %[[SLICE]]) // CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::Texture2D<float vector[4]>::mips_slice_type::operator[](int vector[2]) const(ptr {{.*}} %[[THIS:.*]], <2 x i32> noundef %[[COORD:.*]]) // CHECK: entry: -// CHECK: %[[COORD_ADDR:.*]] = alloca <2 x i32>, align 8 -// CHECK: %[[VEC_TMP:.*]] = alloca <2 x i32>, align 8 -// CHECK: store <2 x i32> %[[COORD]], ptr %[[COORD_ADDR]], align 8 -// CHECK: %[[THIS1:.*]] = load ptr, ptr %{{.*}}, align 4 -// CHECK: %[[COORD_PARAM:.*]] = load <2 x i32>, ptr %[[COORD_ADDR]], align 8 -// CHECK: store <2 x i32> %[[COORD_PARAM]], ptr %[[VEC_TMP]], align 8 +// CHECK: %[[COORD_ADDR:.*]] = alloca <2 x i32> +// CHECK: %[[VEC_TMP:.*]] = alloca <2 x i32> +// CHECK: store <2 x i32> %[[COORD]], ptr %[[COORD_ADDR]] +// CHECK: %[[THIS1:.*]] = load ptr, ptr %{{.*}} +// CHECK: %[[COORD_PARAM:.*]] = load <2 x i32>, ptr %[[COORD_ADDR]] +// CHECK: store <2 x i32> %[[COORD_PARAM]], ptr %[[VEC_TMP]] // CHECK: %[[HANDLE_PTR:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2D<>::mips_slice_type", ptr %[[THIS1]], i32 0, i32 0 -// CHECK: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %[[HANDLE_PTR]], align 4 -// CHECK: %[[COORD_VAL:.*]] = load <2 x i32>, ptr %[[VEC_TMP]], align 8 +// CHECK: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %[[HANDLE_PTR]] +// CHECK: %[[COORD_VAL:.*]] = load <2 x i32>, ptr %[[VEC_TMP]] // CHECK: %[[VECEXT:.*]] = extractelement <2 x i32> %[[COORD_VAL]], i32 0 // CHECK: %[[VECINIT:.*]] = insertelement <3 x i32> poison, i32 %[[VECEXT]], i32 0 -// CHECK: %[[COORD_VAL2:.*]] = load <2 x i32>, ptr %[[VEC_TMP]], align 8 +// CHECK: %[[COORD_VAL2:.*]] = load <2 x i32>, ptr %[[VEC_TMP]] // CHECK: %[[VECEXT2:.*]] = extractelement <2 x i32> %[[COORD_VAL2]], i32 1 // CHECK: %[[VECINIT3:.*]] = insertelement <3 x i32> %[[VECINIT]], i32 %[[VECEXT2]], i32 1 // CHECK: %[[LEVEL_PTR:.*]] = getelementptr {{.*}} %"struct.hlsl::Texture2D<>::mips_slice_type", ptr %[[THIS1]], i32 0, i32 1 -// CHECK: %[[LEVEL_VAL:.*]] = load i32, ptr %[[LEVEL_PTR]], align 4 +// CHECK: %[[LEVEL_VAL:.*]] = load i32, ptr %[[LEVEL_PTR]] // CHECK: %[[VECINIT4:.*]] = insertelement <3 x i32> %[[VECINIT3]], i32 %[[LEVEL_VAL]], i32 2 // CHECK: %[[COORD_X:.*]] = shufflevector <3 x i32> %[[VECINIT4]], <3 x i32> poison, <2 x i32> <i32 0, i32 1> // CHECK: %[[LOD:.*]] = extractelement <3 x i32> %[[VECINIT4]], i64 2 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
