diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index ecf9cfde8aa72..d4b134d11deff 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -17,6 +17,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" +#include "clang/AST/Stmt.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" @@ -48,6 +49,14 @@ static FunctionDecl *lookupBuiltinFunction(Sema &S, StringRef Name) { "Since this is a builtin it should always resolve!"); return cast(R.getFoundDecl()); } + +CXXConstructorDecl *lookupCopyConstructor(QualType ResTy) { + assert(ResTy->isRecordType() && "not a CXXRecord type"); + for (auto *CD : ResTy->getAsCXXRecordDecl()->ctors()) + if (CD->isCopyConstructor()) + return CD; + return nullptr; +} } // namespace // Builder for template arguments of builtin types. Used internally @@ -580,6 +589,23 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnValue(T ReturnValue) { Expr *ReturnValueExpr = convertPlaceholder(ReturnValue); ASTContext &AST = DeclBuilder.SemaRef.getASTContext(); + + QualType Ty = ReturnValueExpr->getType(); + if (Ty->isRecordType()) { + // For record types, create a call to copy constructor to ensure proper copy + // semantics. + auto *ICE = + ImplicitCastExpr::Create(AST, Ty.withConst(), CK_NoOp, ReturnValueExpr, + nullptr, VK_XValue, FPOptionsOverride()); + CXXConstructorDecl *CD = lookupCopyConstructor(Ty); + assert(CD && "no copy constructor found"); + ReturnValueExpr = CXXConstructExpr::Create( + AST, Ty, SourceLocation(), CD, /*Elidable=*/false, {ICE}, + /*HadMultipleCandidates=*/false, /*ListInitialization=*/false, + /*StdInitListInitialization=*/false, + /*ZeroInitListInitialization=*/false, CXXConstructionKind::Complete, + SourceRange()); + } StmtsList.push_back( ReturnStmt::Create(AST, SourceLocation(), ReturnValueExpr, nullptr)); return *this; diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 21203b67a2657..dc12ca2b81cb6 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1212,6 +1212,15 @@ struct PerVisibilityBindingChecker { } }; +static CXXMethodDecl *lookupMethod(Sema &S, CXXRecordDecl *RecordDecl, + StringRef Name, SourceLocation Loc) { + DeclarationName DeclName(&S.getASTContext().Idents.get(Name)); + LookupResult Result(S, DeclName, Loc, Sema::LookupMemberName); + if (!S.LookupQualifiedName(Result, static_cast(RecordDecl))) + return nullptr; + return cast(Result.getFoundDecl()); +} + } // end anonymous namespace bool SemaHLSL::handleRootSignatureElements( @@ -3738,26 +3747,6 @@ void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) { deduceAddressSpace(VD); } -static bool initVarDeclWithCtor(Sema &S, VarDecl *VD, - MutableArrayRef Args) { - InitializedEntity Entity = InitializedEntity::InitializeVariable(VD); - InitializationKind Kind = InitializationKind::CreateDirect( - VD->getLocation(), SourceLocation(), SourceLocation()); - - InitializationSequence InitSeq(S, Entity, Kind, Args); - if (InitSeq.Failed()) - return false; - - ExprResult Init = InitSeq.Perform(S, Entity, Kind, Args); - if (!Init.get()) - return false; - - VD->setInit(S.MaybeCreateExprWithCleanups(Init.get())); - VD->setInitStyle(VarDecl::CallInit); - S.CheckCompleteVariableDeclaration(VD); - return true; -} - void SemaHLSL::createResourceRecordCtorArgs( const Type *ResourceTy, StringRef VarName, HLSLResourceBindingAttr *RBA, HLSLVkBindingAttr *VkBinding, uint32_t ArrayIndex, @@ -3808,11 +3797,106 @@ void SemaHLSL::createResourceRecordCtorArgs( } bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) { - SmallVector Args; - createResourceRecordCtorArgs(VD->getType().getTypePtr(), VD->getName(), - VD->getAttr(), - VD->getAttr(), 0, Args); - return initVarDeclWithCtor(SemaRef, VD, Args); + assert(VD->getType()->isHLSLResourceRecord() && + "expected resource record type"); + + ASTContext &AST = SemaRef.getASTContext(); + uint64_t UIntTySize = AST.getTypeSize(AST.UnsignedIntTy); + uint64_t IntTySize = AST.getTypeSize(AST.IntTy); + + // Gather resource binding information from attributes. + HLSLResourceBindingAttr *RBA = VD->getAttr(); + HLSLVkBindingAttr *VkBinding = VD->getAttr(); + std::optional RegisterSlot; + uint32_t SpaceNo = 0; + if (VkBinding) { + RegisterSlot = VkBinding->getBinding(); + SpaceNo = VkBinding->getSet(); + } else if (RBA) { + if (RBA->hasRegisterSlot()) + RegisterSlot = RBA->getSlotNumber(); + SpaceNo = RBA->getSpaceNumber(); + } + + // Find correct initialization method and create its arguments. + QualType ResourceTy = VD->getType(); + CXXRecordDecl *ResourceDecl = ResourceTy->getAsCXXRecordDecl(); + CXXMethodDecl *CreateMethod = nullptr; + llvm::SmallVector Args; + + if (RegisterSlot.has_value()) { + // The resource has explicit binding. + CreateMethod = lookupMethod(SemaRef, ResourceDecl, "__createFromBinding", + VD->getLocation()); + IntegerLiteral *RegSlot = IntegerLiteral::Create( + AST, llvm::APInt(UIntTySize, RegisterSlot.value()), AST.UnsignedIntTy, + SourceLocation()); + Args.push_back(RegSlot); + } else { + // The resource has implicit binding. + CreateMethod = + lookupMethod(SemaRef, ResourceDecl, "__createFromImplicitBinding", + VD->getLocation()); + uint32_t OrderID = (RBA && RBA->hasImplicitBindingOrderID()) + ? RBA->getImplicitBindingOrderID() + : getNextImplicitBindingOrderID(); + IntegerLiteral *OrderId = + IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, OrderID), + AST.UnsignedIntTy, SourceLocation()); + Args.push_back(OrderId); + } + + if (!CreateMethod) + // This can happen if someone creates a struct that looks like an HLSL + // resource record but does not have the required static create method. + // No binding will be generated for it. + return false; + + IntegerLiteral *Space = + IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, SpaceNo), + AST.UnsignedIntTy, SourceLocation()); + Args.push_back(Space); + + IntegerLiteral *RangeSize = IntegerLiteral::Create( + AST, llvm::APInt(IntTySize, 1), AST.IntTy, SourceLocation()); + Args.push_back(RangeSize); + + IntegerLiteral *Index = IntegerLiteral::Create( + AST, llvm::APInt(UIntTySize, 0), AST.UnsignedIntTy, SourceLocation()); + Args.push_back(Index); + + StringRef VarName = VD->getName(); + StringLiteral *Name = StringLiteral::Create( + AST, VarName, StringLiteralKind::Ordinary, false, + AST.getStringLiteralArrayType(AST.CharTy.withConst(), VarName.size()), + SourceLocation()); + ImplicitCastExpr *NameCast = ImplicitCastExpr::Create( + AST, AST.getPointerType(AST.CharTy.withConst()), CK_ArrayToPointerDecay, + Name, nullptr, VK_PRValue, FPOptionsOverride()); + Args.push_back(NameCast); + + // Make sure the create method template is instantiated and emitted. + if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation()) + SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod, + true); + + // Create CallExpr with a call to the static method and set it as the decl + // initialization. + DeclRefExpr *DRE = DeclRefExpr::Create( + AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod, false, + CreateMethod->getNameInfo(), CreateMethod->getType(), VK_PRValue); + + auto *ImpCast = ImplicitCastExpr::Create( + AST, AST.getPointerType(CreateMethod->getType()), + CK_FunctionToPointerDecay, DRE, nullptr, VK_PRValue, FPOptionsOverride()); + + CallExpr *InitExpr = + CallExpr::Create(AST, ImpCast, Args, ResourceTy, VK_PRValue, + SourceLocation(), FPOptionsOverride()); + VD->setInit(InitExpr); + VD->setInitStyle(VarDecl::CallInit); + SemaRef.CheckCompleteVariableDeclaration(VD); + return true; } bool SemaHLSL::initGlobalResourceArrayDecl(VarDecl *VD) { diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl index 8d2e36f4bb7d1..528fe9d1722be 100644 --- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl @@ -34,7 +34,7 @@ RESOURCE Buffer; #endif -// CHECK: CXXRecordDecl {{.*}} implicit referenced class [[RESOURCE]] definition +// CHECK: CXXRecordDecl {{.*}} implicit referenced class [[RESOURCE]] definition // CHECK: FinalAttr {{.*}} Implicit final // CHECK-NEXT: FieldDecl {{.*}} implicit __handle '__hlsl_resource_t // CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] @@ -107,6 +107,8 @@ RESOURCE Buffer; // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int' // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *' // CHECK-NEXT: ReturnStmt +// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]' 'void (const hlsl::[[RESOURCE]] &)' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'const hlsl::[[RESOURCE]]' xvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]' // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline @@ -135,6 +137,8 @@ RESOURCE Buffer; // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int' // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *' // CHECK-NEXT: ReturnStmt +// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]' 'void (const hlsl::[[RESOURCE]] &)' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'const hlsl::[[RESOURCE]]' xvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]' // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline diff --git a/clang/test/AST/HLSL/vk_binding_attr.hlsl b/clang/test/AST/HLSL/vk_binding_attr.hlsl index 4cb2abdaef01a..d08165d7c593d 100644 --- a/clang/test/AST/HLSL/vk_binding_attr.hlsl +++ b/clang/test/AST/HLSL/vk_binding_attr.hlsl @@ -2,18 +2,23 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.8-library -finclude-default-header -ast-dump -o - %s | FileCheck %s -check-prefixes=DXIL,CHECK // CHECK: VarDecl {{.*}} Buf 'StructuredBuffer':'hlsl::StructuredBuffer' -// SPV-NEXT: CXXConstructExpr {{.*}} 'StructuredBuffer':'hlsl::StructuredBuffer' 'void (unsigned int, unsigned int, int, unsigned int, const char *)' +// CHECK-NEXT: CallExpr {{.*}} 'StructuredBuffer':'hlsl::StructuredBuffer' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::StructuredBuffer (*)(unsigned int, unsigned int, int, unsigned int, const char *)' +// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::StructuredBuffer (unsigned int, unsigned int, int, unsigned int, const char *)' +// CHECK-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::StructuredBuffer (unsigned int, unsigned int, int, unsigned int, const char *)' // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23 // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 102 -// DXIL-NEXT: CXXConstructExpr {{.*}} 'StructuredBuffer':'hlsl::StructuredBuffer' 'void (unsigned int, int, unsigned int, unsigned int, const char *)' // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0 -// DXIL-NEXT: IntegerLiteral {{.*}} 'int' 1 +// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0 // SPV: HLSLVkBindingAttr {{.*}} 23 102 // DXIL-NOT: HLSLVkBindingAttr [[vk::binding(23, 102)]] StructuredBuffer Buf; // CHECK: VarDecl {{.*}} Buf2 'StructuredBuffer':'hlsl::StructuredBuffer' -// CHECK-NEXT: CXXConstructExpr {{.*}} 'StructuredBuffer':'hlsl::StructuredBuffer' 'void (unsigned int, unsigned int, int, unsigned int, const char *)' +// CHECK-NEXT: CallExpr {{.*}} 'StructuredBuffer':'hlsl::StructuredBuffer' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::StructuredBuffer (*)(unsigned int, unsigned int, int, unsigned int, const char *)' +// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::StructuredBuffer (unsigned int, unsigned int, int, unsigned int, const char *)' +// CHECK-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::StructuredBuffer (unsigned int, unsigned int, int, unsigned int, const char *)' // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 14 // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 1 // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23 @@ -24,7 +29,10 @@ [[vk::binding(14, 1)]] StructuredBuffer Buf2 : register(t23, space102); // CHECK: VarDecl {{.*}} Buf3 'StructuredBuffer':'hlsl::StructuredBuffer' -// CHECK-NEXT: CXXConstructExpr {{.*}} 'StructuredBuffer':'hlsl::StructuredBuffer' 'void (unsigned int, unsigned int, int, unsigned int, const char *)' +// CHECK-NEXT: CallExpr {{.*}} 'StructuredBuffer':'hlsl::StructuredBuffer' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::StructuredBuffer (*)(unsigned int, unsigned int, int, unsigned int, const char *)' +// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::StructuredBuffer (unsigned int, unsigned int, int, unsigned int, const char *)' +// CHECK-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::StructuredBuffer (unsigned int, unsigned int, int, unsigned int, const char *)' // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 14 // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0 // DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23 @@ -43,28 +51,46 @@ } // CHECK: VarDecl {{.*}} Buf4 'Buffer':'hlsl::Buffer' -// SPV-NEXT: CXXConstructExpr {{.*}} 'Buffer':'hlsl::Buffer' 'void (unsigned int, unsigned int, int, unsigned int, const char *)' +// CHECK-NEXT: CallExpr {{.*}} 'Buffer':'hlsl::Buffer' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::Buffer (*)(unsigned int, unsigned int, int, unsigned int, const char *)' +// SPV-NEXT: DeclRefExpr {{.*}} 'hlsl::Buffer (unsigned int, unsigned int, int, unsigned int, const char *)' +// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'Buffer (unsigned int, unsigned int, int, unsigned int, const char *)' // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 24 // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 103 -// DXL-NEXT: CXXConstructExpr {{.*}} 'Buffer':'hlsl::Buffer' 'void (unsigned int, int, unsigned int, unsigned int, const char *)' +// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::Buffer (unsigned int, unsigned int, int, unsigned int, const char *)' +// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromImplicitBinding' 'Buffer (unsigned int, unsigned int, int, unsigned int, const char *)' +// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 2 +// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0 // SPV: HLSLVkBindingAttr {{.*}} 24 103 // DXIL-NOT: HLSLVkBindingAttr [[vk::binding(24, 103)]] Buffer Buf4; // CHECK: VarDecl {{.*}} Buf5 'RWBuffer':'hlsl::RWBuffer>' -// SPV-NEXT: CXXConstructExpr {{.*}} 'RWBuffer':'hlsl::RWBuffer>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)' +// CHECK-NEXT: CallExpr {{.*}} 'RWBuffer':'hlsl::RWBuffer>' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::RWBuffer> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' +// SPV-NEXT: DeclRefExpr {{.*}} 'hlsl::RWBuffer> (unsigned int, unsigned int, int, unsigned int, const char *)' +// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'Buffer (unsigned int, unsigned int, int, unsigned int, const char *)' // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 25 // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 104 -// DXL-NEXT: CXXConstructExpr {{.*}} 'Buffer':'hlsl::Buffer' 'void (unsigned int, int, unsigned int, unsigned int, const char *)' +// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::RWBuffer> (unsigned int, unsigned int, int, unsigned int, const char *)' +// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromImplicitBinding' 'Buffer (unsigned int, unsigned int, int, unsigned int, const char *)' +// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 3 +// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0 // SPV: HLSLVkBindingAttr {{.*}} 25 104 // DXIL-NOT: HLSLVkBindingAttr [[vk::binding(25, 104)]] RWBuffer Buf5; // CHECK: VarDecl {{.*}} Buf6 'RWStructuredBuffer':'hlsl::RWStructuredBuffer' -// SPV-NEXT: CXXConstructExpr {{.*}} 'RWStructuredBuffer':'hlsl::RWStructuredBuffer' 'void (unsigned int, unsigned int, int, unsigned int, const char *)' +// CHECK-NEXT: CallExpr {{.*}} 'RWStructuredBuffer':'hlsl::RWStructuredBuffer' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::RWStructuredBuffer (*)(unsigned int, unsigned int, int, unsigned int, const char *)' +// SPV-NEXT: DeclRefExpr {{.*}} 'hlsl::RWStructuredBuffer (unsigned int, unsigned int, int, unsigned int, const char *)' +// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::RWStructuredBuffer (unsigned int, unsigned int, int, unsigned int, const char *)' // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 26 // SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 105 -// DXL-NEXT: CXXConstructExpr {{.*}} 'Buffer':'hlsl::Buffer' 'void (unsigned int, int, unsigned int, unsigned int, const char *)' +// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::RWStructuredBuffer (unsigned int, unsigned int, int, unsigned int, const char *)' +// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::RWStructuredBuffer (unsigned int, unsigned int, int, unsigned int, const char *)' +// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 4 +// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0 // SPV: HLSLVkBindingAttr {{.*}} 26 105 // DXIL-NOT: HLSLVkBindingAttr [[vk::binding(26, 105)]] RWStructuredBuffer Buf6; diff --git a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl index afda714106fac..0ef4b432019bb 100644 --- a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl +++ b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,INLINE +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,NOINLINE +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -O0 %s -o - | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,INLINE // Make sure global variable for ctors exist for lib profile. // CHECK:@llvm.global_ctors @@ -13,7 +13,7 @@ void FirstEntry() {} // CHECK: define void @FirstEntry() // CHECK-NEXT: entry: // NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() -// NOINLINE-NEXT: call void @_Z10FirstEntryv() +// NOINLINE-NEXT: call void @FirstEntry() // Verify inlining leaves only calls to "llvm." intrinsics // INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}} // CHECK: ret void @@ -25,15 +25,24 @@ void SecondEntry() {} // CHECK: define void @SecondEntry() // CHECK-NEXT: entry: // NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() -// NOINLINE-NEXT: call void @_Z11SecondEntryv() +// NOINLINE-NEXT: call void @SecondEntry() // Verify inlining leaves only calls to "llvm." intrinsics // INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}} // CHECK: ret void -// Verify the constructor is alwaysinline +// Verify the constructors are alwaysinline // NOINLINE: ; Function Attrs: {{.*}}alwaysinline -// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EjijjPKc({{.*}} [[CtorAttr:\#[0-9]+]] +// NOINLINE-NEXT: define linkonce_odr hidden void @hlsl::RWBuffer::RWBuffer()({{.*}}){{.*}} [[CtorAttr:\#[0-9]+]] + +// NOINLINE: ; Function Attrs: {{.*}}alwaysinline +// NOINLINE-NEXT: define linkonce_odr hidden void @hlsl::RWBuffer::RWBuffer(hlsl::RWBuffer const&)({{.*}}){{.*}} [[CtorAttr]] + +// NOINLINE: ; Function Attrs: {{.*}}alwaysinline +// NOINLINE-NEXT: define linkonce_odr hidden void @hlsl::RWBuffer::RWBuffer()(ptr noundef nonnull align 4 dereferenceable(4) %this){{.*}} [[CtorAttr:\#[0-9]+]] + +// NOINLINE: ; Function Attrs: {{.*}}alwaysinline +// NOINLINE-NEXT: define linkonce_odr hidden void @hlsl::RWBuffer::RWBuffer(hlsl::RWBuffer const&)({{.*}}){{.*}} [[CtorAttr]] // NOINLINE: ; Function Attrs: {{.*}}alwaysinline // NOINLINE-NEXT: define internal void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() [[InitAttr:\#[0-9]+]] diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl index 5db156ed325da..9354ee714f86e 100644 --- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl +++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-constructors.hlsl @@ -1,6 +1,8 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | \ +// RUN: llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL // FIXME: SPIR-V codegen of llvm.spv.resource.handlefrombinding and resource types is not yet implemented -// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV +// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | \ +// llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV // NOTE: Itanium ABI for C++ requires Clang to generate 2 constructors types to support polymorphism: // - C1 - Complete object constructor - constructs the complete object, including virtual base classes. @@ -23,69 +25,61 @@ export void foo() { // CHECK: %"class.hlsl::RWByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 0) } // CHECK: %"class.hlsl::RasterizerOrderedByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 1) } -// CHECK: @_ZL4Buf1 = internal global %"class.hlsl::ByteAddressBuffer" poison, align 4 +// CHECK: @Buf1 = internal global %"class.hlsl::ByteAddressBuffer" poison, align 4 // CHECK: @[[Buf1Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf1\00", align 1 -// CHECK: @_ZL4Buf2 = internal global %"class.hlsl::RWByteAddressBuffer" poison, align 4 +// CHECK: @Buf2 = internal global %"class.hlsl::RWByteAddressBuffer" poison, align 4 // CHECK: @[[Buf2Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf2\00", align 1 -// Buf1 initialization part 1 - global init function that calls ByteAddressBuffer C1 constructor with explicit binding +// Buf1 initialization part 1 - global init function that calls ByteAddressBuffer::__createFromBinding // CHECK: define internal void @__cxx_global_var_init() // CHECK-NEXT: entry: -// CHECK-NEXT: call void @_ZN4hlsl17ByteAddressBufferC1EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf1, -// CHECK-SAME: i32 noundef 1, i32 noundef 2, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]]) - -// Buf1 initialization part 2 - body of ByteAddressBuffer C1 constructor with explicit binding that calls the C2 constructor -// CHECK: define linkonce_odr hidden void @_ZN4hlsl17ByteAddressBufferC1EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, -// CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) -// CHECK: call void @_ZN4hlsl17ByteAddressBufferC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) -// CHECK-SAME: %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, ptr noundef %{{.*}}) - -// Buf2 initialization part 1 - global init function that calls RWByteAddressBuffer C1 constructor with implicit binding +// CHECK-NEXT: call void @hlsl::ByteAddressBuffer::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: (ptr {{.*}} @Buf1, i32 noundef 1, i32 noundef 2, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]]) + +// Buf1 initialization part 2 - body of ByteAddressBuffer::__createFromBinding +// CHECK: define {{.*}} void @hlsl::ByteAddressBuffer::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::ByteAddressBuffer") align 4 %[[RetValue1:.*]], i32 noundef %registerNo, +// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) +// CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::ByteAddressBuffer", align 4 +// CHECK: %[[Handle1:.*]] = call target("dx.RawBuffer", i8, 0, 0) +// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t( +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %[[Tmp1]], i32 0, i32 0 +// CHECK-DXIL: store target("dx.RawBuffer", i8, 0, 0) %[[Handle1]], ptr %__handle, align 4 +// CHECK: call void @hlsl::ByteAddressBuffer::ByteAddressBuffer(hlsl::ByteAddressBuffer const&)(ptr {{.*}} %[[RetValue1]], ptr {{.*}} %[[Tmp1]]) + +// Buf2 initialization part 1 - global init function that calls RWByteAddressBuffer::__createFromImplicitBinding // CHECK: define internal void @__cxx_global_var_init.1() // CHECK-NEXT: entry: -// CHECK-NEXT: call void @_ZN4hlsl19RWByteAddressBufferC1EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf2, -// CHECK-SAME: i32 noundef 0, i32 noundef 1, i32 noundef 0, i32 noundef 0, ptr noundef @[[Buf2Str]]) - -// Buf2 initialization part 2 - body of RWByteAddressBuffer C1 constructor with implicit binding that calls the C2 constructor -// CHECK: define linkonce_odr hidden void @_ZN4hlsl19RWByteAddressBufferC1EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, -// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name) -// CHECK: call void @_ZN4hlsl19RWByteAddressBufferC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this1, -// CHECK-SAME: i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, ptr noundef %{{.*}}) +// CHECK-NEXT: call void @hlsl::RWByteAddressBuffer::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: (ptr {{.*}} @Buf2, i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]]) + +// Buf2 initialization part 2 - body of RWByteAddressBuffer::__createFromImplicitBinding +// CHECK: define hidden void @hlsl::RWByteAddressBuffer::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWByteAddressBuffer") align 4 %[[RetValue2:.*]], i32 noundef %orderId, +// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) +// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWByteAddressBuffer", align 4 +// CHECK: %[[Handle2:.*]] = call target("dx.RawBuffer", i8, 1, 0) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i8_1_0t( +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %[[Tmp2]], i32 0, i32 0 +// CHECK-DXIL: store target("dx.RawBuffer", i8, 1, 0) %[[Handle2]], ptr %__handle, align 4 +// CHECK: call void @hlsl::RWByteAddressBuffer::RWByteAddressBuffer(hlsl::RWByteAddressBuffer const&)(ptr {{.*}} %[[RetValue2]], ptr {{.*}} %[[Tmp2]]) // Buf3 initialization part 1 - local variable declared in function foo() is initialized by // RasterizerOrderedByteAddressBuffer C1 default constructor -// CHECK: define void @_Z3foov() +// CHECK: define void @foo() // CHECK-NEXT: entry: // CHECK-NEXT: %Buf3 = alloca %"class.hlsl::RasterizerOrderedByteAddressBuffer", align 4 -// CHECK-NEXT: call void @_ZN4hlsl34RasterizerOrderedByteAddressBufferC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %Buf3) +// CHECK-NEXT: call void @hlsl::RasterizerOrderedByteAddressBuffer::RasterizerOrderedByteAddressBuffer()(ptr {{.*}} %Buf3) // Buf3 initialization part 2 - body of RasterizerOrderedByteAddressBuffer default C1 constructor that // calls the default C2 constructor -// CHECK: define linkonce_odr hidden void @_ZN4hlsl34RasterizerOrderedByteAddressBufferC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) -// CHECK: call void @_ZN4hlsl34RasterizerOrderedByteAddressBufferC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %{{.*}}) +// CHECK: define linkonce_odr hidden void @hlsl::RasterizerOrderedByteAddressBuffer::RasterizerOrderedByteAddressBuffer()(ptr {{.*}} %this) +// CHECK: call void @hlsl::RasterizerOrderedByteAddressBuffer::RasterizerOrderedByteAddressBuffer()(ptr {{.*}} %this1) // CHECK-NEXT: ret void -// Buf1 initialization part 3 - ByteAddressBuffer C2 constructor with explicit binding that initializes -// handle with @llvm.dx.resource.handlefrombinding -// CHECK: define linkonce_odr hidden void @_ZN4hlsl17ByteAddressBufferC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, -// CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) -// CHECK-DXIL: %[[HANDLE:.*]] = call target("dx.RawBuffer", i8, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t( -// CHECK-DXIL-SAME: i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr %{{.*}}) -// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0 -// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]], ptr %__handle, align 4 - -// Buf2 initialization part 3 - body of RWByteAddressBuffer C2 constructor with implicit binding that initializes -// handle with @llvm.dx.resource.handlefromimplicitbinding -// CHECK: define linkonce_odr hidden void @_ZN4hlsl19RWByteAddressBufferC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, -// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name) -// CHECK: %[[HANDLE:.*]] = call target("dx.RawBuffer", i8, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i8_1_0t -// CHECK-SAME: (i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr %{{.*}}) -// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %this1, i32 0, i32 0 -// CHECK-NEXT: store target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], ptr %__handle, align 4 - // Buf3 initialization part 3 - body of RasterizerOrderedByteAddressBuffer default C2 constructor that // initializes handle to poison -// CHECK: define linkonce_odr hidden void @_ZN4hlsl34RasterizerOrderedByteAddressBufferC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) +// CHECK: define linkonce_odr hidden void @hlsl::RasterizerOrderedByteAddressBuffer::RasterizerOrderedByteAddressBuffer()(ptr {{.*}} %this) // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK: store target("dx.RawBuffer", i8, 1, 1) poison, ptr %__handle, align 4 diff --git a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl index 127498460b039..ca33c4220dd73 100644 --- a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl +++ b/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl @@ -1,6 +1,8 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | \ +// RUN: llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL // FIXME: SPIR-V codegen of llvm.spv.resource.handlefrombinding and resource types is not yet implemented -// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV +// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | \ +// llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV // NOTE: Itanium ABI for C++ requires Clang to generate 2 constructors types to support polymorphism: // - C1 - Complete object constructor - constructs the complete object, including virtual base classes. @@ -23,65 +25,57 @@ export void foo() { // CHECK: %"class.hlsl::RWBuffer.0" = type { target("dx.TypedBuffer", double, 1, 0, 0) } // CHECK: %"class.hlsl::RWBuffer.1" = type { target("dx.TypedBuffer", i32, 1, 0, 1) } -// CHECK: @_ZL4Buf1 = internal global %"class.hlsl::RWBuffer" poison, align 4 +// CHECK: @Buf1 = internal global %"class.hlsl::RWBuffer" poison, align 4 // CHECK: @[[Buf1Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf1\00", align 1 -// CHECK: @_ZL4Buf2 = internal global %"class.hlsl::RWBuffer.0" poison, align 4 +// CHECK: @Buf2 = internal global %"class.hlsl::RWBuffer.0" poison, align 4 // CHECK: @[[Buf2Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf2\00", align 1 -// Buf1 initialization part 1 - global init function that calls RWBuffer C1 constructor with explicit binding +// Buf1 initialization part 1 - global init function that calls RWBuffer::__createFromBinding // CHECK: define internal void @__cxx_global_var_init() // CHECK-NEXT: entry: -// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf1, -// CHECK-SAME: i32 noundef 5, i32 noundef 3, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]]) - -// Buf1 initialization part 2 - body of RWBuffer C1 constructor with explicit binding that calls the C2 constructor -// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC1EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, -// CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) -// CHECK: call void @_ZN4hlsl8RWBufferIfEC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) -// CHECK-SAME: %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, ptr noundef %{{.*}}) - -// Buf2 initialization part 1 - global init function that calls RWBuffer C1 constructor with implicit binding +// CHECK-NEXT: call void @hlsl::RWBuffer::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 @Buf1, i32 noundef 5, i32 noundef 3, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]]) + +// Buf1 initialization part 2 - body of RWBuffer::__createFromBinding +// CHECK: define {{.*}} void @hlsl::RWBuffer::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 %[[RetValue1:.*]], i32 noundef %registerNo, +// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) +// CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::RWBuffer", align 4 +// CHECK: %[[Handle1:.*]] = call target("dx.TypedBuffer", float, 1, 0, 0) +// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t( +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %[[Tmp1]], i32 0, i32 0 +// CHECK-DXIL: store target("dx.TypedBuffer", float, 1, 0, 0) %[[Handle1]], ptr %__handle, align 4 +// CHECK: call void @hlsl::RWBuffer::RWBuffer(hlsl::RWBuffer const&)(ptr {{.*}} %[[RetValue1]], ptr {{.*}} %[[Tmp1]]) + +// Buf2 initialization part 1 - global init function that RWBuffer::__createFromImplicitBinding // CHECK: define internal void @__cxx_global_var_init.1() // CHECK-NEXT: entry: -// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIdEC1EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf2, -// CHECK-SAME: i32 noundef 0, i32 noundef 1, i32 noundef 0, i32 noundef 0, ptr noundef @[[Buf2Str]]) - -// Buf2 initialization part 2 - body of RWBuffer C1 constructor with implicit binding that calls the C2 constructor -// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIdEC1EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, -// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name) -// CHECK: call void @_ZN4hlsl8RWBufferIdEC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) -// CHECK-SAME: %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, ptr noundef %{{.*}}) +// CHECK-NEXT: call void @hlsl::RWBuffer::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: (ptr {{.*}} @Buf2, i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]]) + +// Buf2 initialization part 2 - body of RWBuffer::__createFromImplicitBinding call +// CHECK: define linkonce_odr hidden void @hlsl::RWBuffer::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[RetValue2:.*]], i32 noundef %orderId, +// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) +// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer.0", align 4 +// CHECK: %[[Handle2:.*]] = call target("dx.TypedBuffer", double, 1, 0, 0) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.TypedBuffer_f64_1_0_0t( +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %[[Tmp2]], i32 0, i32 0 +// CHECK-DXIL: store target("dx.TypedBuffer", double, 1, 0, 0) %[[Handle2]], ptr %__handle, align 4 +// CHECK: call void @hlsl::RWBuffer::RWBuffer(hlsl::RWBuffer const&)(ptr {{.*}} %[[RetValue2]], ptr {{.*}} %[[Tmp2]]) // Buf3 initialization part 1 - local variable declared in function foo() is initialized by RWBuffer C1 default constructor -// CHECK: define void @_Z3foov() +// CHECK: define void @foo() // CHECK-NEXT: entry: // CHECK-NEXT: %Buf3 = alloca %"class.hlsl::RWBuffer.1", align 4 -// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %Buf3) +// CHECK-NEXT: call void @hlsl::RWBuffer::RWBuffer()(ptr {{.*}} %Buf3) // Buf3 initialization part 2 - body of RWBuffer default C1 constructor that calls the default C2 constructor -// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) -// CHECK: call void @_ZN4hlsl8RWBufferIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %{{.*}}) - -// Buf1 initialization part 3 - body of RWBuffer C2 constructor with explicit binding that initializes -// handle with @llvm.dx.resource.handlefrombinding -// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, -// CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) -// CHECK-DXIL: %[[HANDLE:.*]] = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t( -// CHECK-DXIL-SAME: i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr %{{.*}}) -// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0 -// CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %[[HANDLE]], ptr %__handle, align 4 - -// Buf2 initialization part 3 - body of RWBuffer C2 constructor with implicit binding that initializes -// handle with @llvm.dx.resource.handlefromimplicitbinding -// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIdEC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, -// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name) -// CHECK: %[[HANDLE:.*]] = call target("dx.TypedBuffer", double, 1, 0, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.TypedBuffer_f64_1_0_0t -// CHECK-SAME: (i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr %{{.*}}) -// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %{{.*}}, i32 0, i32 0 -// CHECK-NEXT: store target("dx.TypedBuffer", double, 1, 0, 0) %[[HANDLE]], ptr %__handle, align 4 +// CHECK: define linkonce_odr hidden void @hlsl::RWBuffer::RWBuffer()(ptr {{.*}} %this) +// CHECK: call void @hlsl::RWBuffer::RWBuffer()(ptr {{.*}} %{{.*}}) // Buf3 initialization part 3 - body of RWBuffer default C2 constructor that initializes handle to poison -// CHECK: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) +// CHECK: define linkonce_odr hidden void @hlsl::RWBuffer::RWBuffer()(ptr {{.*}} %this) // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.1", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: store target("dx.TypedBuffer", i32, 1, 0, 1) poison, ptr %__handle, align 4 diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl index 91410e600c6e0..4f005eab5c71a 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl @@ -1,6 +1,8 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | \ +// RUN: llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL // FIXME: SPIR-V codegen of llvm.spv.resource.handlefrombinding and resource types is not yet implemented -// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV +// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | \ +// llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV // NOTE: Itanium ABI for C++ requires Clang to generate 2 constructors types to support polymorphism: // - C1 - Complete object constructor - constructs the complete object, including virtual base classes. @@ -18,77 +20,68 @@ export void foo() { AppendStructuredBuffer Buf3; } -// CHECK: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0) } -// CHECK: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) } -// CHECK: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) } +// CHECK-DXIL: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0) } +// CHECK-DXIL: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) } +// CHECK-DXIL: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) } -// CHECK: @_ZL4Buf1 = internal global %"class.hlsl::StructuredBuffer" poison, align 4 +// CHECK: @Buf1 = internal global %"class.hlsl::StructuredBuffer" poison, align 4 // CHECK: @[[Buf1Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf1\00", align 1 -// CHECK: @_ZL4Buf2 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4 +// CHECK: @Buf2 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4 // CHECK: @[[Buf2Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf2\00", align 1 -// Buf1 initialization part 1 - global init function that calls StructuredBuffer C1 constructor +// Buf1 initialization part 1 - global init function that calls StructuredBuffer::__createFromBinding // with explicit binding // CHECK: define internal void @__cxx_global_var_init() // CHECK-NEXT: entry: -// CHECK-NEXT: call void @_ZN4hlsl16StructuredBufferIfEC1EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf1, -// CHECK-SAME: i32 noundef 10, i32 noundef 2, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]]) - -// Buf1 initialization part 2 - body of StructuredBuffer C1 constructor with explicit binding -// that calls the C2 constructor -// CHECK: define linkonce_odr hidden void @_ZN4hlsl16StructuredBufferIfEC1EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, -// CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) -// CHECK: call void @_ZN4hlsl16StructuredBufferIfEC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) -// CHECK-SAME: %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, ptr noundef %{{.*}}) - -// Buf2 initialization part 1 - global init function that calls RWStructuredBuffer C1 constructor with -// implicit binding +// CHECK-NEXT: call void @hlsl::StructuredBuffer::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: (ptr {{.*}} @Buf1, i32 noundef 10, i32 noundef 2, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf1Str]]) + +// Buf1 initialization part 2 - body of StructuredBuffer::::__createFromBinding + +// CHECK: define {{.*}} void @hlsl::StructuredBuffer::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: ptr {{.*}} sret(%"class.hlsl::StructuredBuffer") align 4 %[[RetValue1:.*]], i32 noundef %registerNo, +// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) +// CHECK: %[[Tmp1:.*]] = alloca %"class.hlsl::StructuredBuffer", align 4 +// CHECK-DXIL: %[[Handle1:.*]] = call target("dx.RawBuffer", float, 0, 0) +// CHECK-DXIL-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t( +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %[[Tmp1]], i32 0, i32 0 +// CHECK-DXIL: store target("dx.RawBuffer", float, 0, 0) %[[Handle1]], ptr %__handle, align 4 +// CHECK: call void @hlsl::StructuredBuffer::StructuredBuffer(hlsl::StructuredBuffer const&)(ptr {{.*}} %[[RetValue1]], ptr {{.*}} %[[Tmp1]]) + +// Buf2 initialization part 1 - global init function that calls RWStructuredBuffer::__createFromImplicitBinding // CHECK: define internal void @__cxx_global_var_init.1() // CHECK-NEXT: entry: -// CHECK-NEXT: call void @_ZN4hlsl18RWStructuredBufferIfEC1EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) @_ZL4Buf2, -// CHECK-SAME: i32 noundef 0, i32 noundef 1, i32 noundef 0, i32 noundef 0, ptr noundef @[[Buf2Str]]) - -// Buf2 initialization part 2 - body of RWStructuredBuffer C1 constructor with implicit binding that calls the C2 constructor -// CHECK: define linkonce_odr hidden void @_ZN4hlsl18RWStructuredBufferIfEC1EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, -// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name) -// CHECK: call void @_ZN4hlsl18RWStructuredBufferIfEC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) -// CHECK-SAME: %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}, ptr noundef %{{.*}}) +// CHECK-NEXT: call void @hlsl::RWStructuredBuffer::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: (ptr {{.*}} @Buf2, i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]]) + +// Buf2 initialization part 2 - body of RWStructuredBuffer::__createFromImplicitBinding +// CHECK: define linkonce_odr hidden void @hlsl::RWStructuredBuffer::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWStructuredBuffer") align 4 %[[RetValue2:.*]], i32 noundef %orderId, +// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) +// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWStructuredBuffer", align 4 +// CHECK-DXIL: %[[Handle2:.*]] = call target("dx.RawBuffer", float, 1, 0) +// CHECK-DXIL-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f32_1_0t( +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %[[Tmp2]], i32 0, i32 0 +// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) %[[Handle2]], ptr %__handle, align 4 +// CHECK: call void @hlsl::RWStructuredBuffer::RWStructuredBuffer(hlsl::RWStructuredBuffer const&)(ptr {{.*}} %[[RetValue2]], ptr {{.*}} %[[Tmp2]]) // Buf3 initialization part 1 - local variable declared in function foo() is initialized by // AppendStructuredBuffer C1 default constructor -// CHECK: define void @_Z3foov() +// CHECK: define void @foo() // CHECK-NEXT: entry: // CHECK-NEXT: %Buf3 = alloca %"class.hlsl::AppendStructuredBuffer", align 4 -// CHECK-NEXT: call void @_ZN4hlsl22AppendStructuredBufferIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %Buf3) +// CHECK-NEXT: call void @hlsl::AppendStructuredBuffer::AppendStructuredBuffer()(ptr {{.*}} %Buf3) // Buf3 initialization part 2 - body of AppendStructuredBuffer default C1 constructor that calls // the default C2 constructor -// CHECK: define linkonce_odr hidden void @_ZN4hlsl22AppendStructuredBufferIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) -// CHECK: call void @_ZN4hlsl22AppendStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %{{.*}}) - -// Buf1 initialization part 3 - body of AppendStructuredBuffer C2 constructor with explicit binding -// that initializes handle with @llvm.dx.resource.handlefrombinding -// CHECK: define linkonce_odr hidden void @_ZN4hlsl16StructuredBufferIfEC2EjjijPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, -// CHECK-SAME: i32 noundef %registerNo, i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) -// CHECK-DXIL: %[[HANDLE:.*]] = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t( -// CHECK-SAME: i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr %{{.*}}) -// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0 -// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 0, 0) %[[HANDLE]], ptr %__handle, align 4 - -// Buf2 initialization part 3 - body of RWStructuredBuffer C2 constructor with implicit binding that initializes -// handle with @llvm.dx.resource.handlefromimplicitbinding -// CHECK: define linkonce_odr hidden void @_ZN4hlsl18RWStructuredBufferIfEC2EjijjPKc(ptr noundef nonnull align 4 dereferenceable(4) %this, -// CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, i32 noundef %orderId, ptr noundef %name) -// CHECK: %[[HANDLE:.*]] = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f32_1_0t -// CHECK-SAME: (i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr %{{.*}}) -// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 -// CHECK-NEXT: store target("dx.RawBuffer", float, 1, 0) %[[HANDLE]], ptr %__handle, align 4 +// CHECK: define linkonce_odr hidden void @hlsl::StructuredBuffer::StructuredBuffer()(ptr {{.*}} %this) +// CHECK: call void @hlsl::StructuredBuffer::StructuredBuffer()(ptr {{.*}} %this1) // Buf3 initialization part 3 - body of AppendStructuredBuffer default C2 constructor that // initializes handle to poison -// CHECK: define linkonce_odr hidden void @_ZN4hlsl22AppendStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) +// CHECK: define linkonce_odr hidden void @hlsl::StructuredBuffer::StructuredBuffer()(ptr {{.*}} %this) // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::AppendStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 -// CHECK: store target("dx.RawBuffer", float, 1, 0) poison, ptr %__handle, align 4 +// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) poison, ptr %__handle, align 4 // Module initialization // CHECK: define internal void @_GLOBAL__sub_I_StructuredBuffers_constructors.hlsl() diff --git a/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl b/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl index 27af47e9587cc..4ffa7cfc84e17 100644 --- a/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl +++ b/clang/test/CodeGenHLSL/resources/resource-bindings.hlsl @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple dxil--shadermodel6.6-compute -x hlsl -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple dxil--shadermodel6.6-compute -x hlsl -finclude-default-header \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s // CHECK: %"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", <4 x float>, 1, 0, 0) } // CHECK: %"class.hlsl::RWBuffer.0" = type { target("dx.TypedBuffer", float, 1, 0, 0) } @@ -12,32 +13,20 @@ // CHECK: @_ZL4T3S0 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4 // CHECK: @_ZL5Array = internal global [10 x %"class.hlsl::RWBuffer.1"] poison, align 4 -// CHECK: %[[HANDLE:.*]] = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) +// CHECK: call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) // CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_1_0_0t( -// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, ptr %{{.*}}) -// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %this{{[0-9]*}}, i32 0, i32 0 -// CHECK: store target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %[[HANDLE]], ptr %[[HANDLE_PTR]], align 4 RWBuffer U0S0 : register(u0); -// CHECK: %[[HANDLE:.*]] = call target("dx.TypedBuffer", float, 1, 0, 0) +// CHECK: call target("dx.TypedBuffer", float, 1, 0, 0) // CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t( -// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, ptr %{{.*}}) -// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %this{{[0-9]*}}, i32 0, i32 0 -// CHECK: store target("dx.TypedBuffer", float, 1, 0, 0) %[[HANDLE]], ptr %[[HANDLE_PTR]], align 4 RWBuffer U5S3 : register(u5, space3); -// CHECK: %[[HANDLE:.*]] = call target("dx.RawBuffer", i32, 0, 0) +// CHECK: call target("dx.RawBuffer", i32, 0, 0) // CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t( -// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, ptr %{{.*}}) -// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %this{{[0-9]*}}, i32 0, i32 0 -// CHECK: store target("dx.RawBuffer", i32, 0, 0) %[[HANDLE]], ptr %[[HANDLE_PTR]], align 4 StructuredBuffer T2S2 : register(t2, space2); -// CHECK: %[[HANDLE:.*]] = call target("dx.RawBuffer", %struct.S, 1, 0) +// CHECK: call target("dx.RawBuffer", %struct.S, 1, 0) // CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_s_struct.Ss_1_0t( -// CHECK-SAME: i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, ptr %{{.*}}) -// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %this{{[0-9]*}}, i32 0, i32 0 -// CHECK: store target("dx.RawBuffer", %struct.S, 1, 0) %[[HANDLE]], ptr %[[HANDLE_PTR]], align 4 struct S { float4 f; int i; diff --git a/clang/test/CodeGenHLSL/static-local-ctor.hlsl b/clang/test/CodeGenHLSL/static-local-ctor.hlsl index 9a4bf66f030ed..bb575d23216b0 100644 --- a/clang/test/CodeGenHLSL/static-local-ctor.hlsl +++ b/clang/test/CodeGenHLSL/static-local-ctor.hlsl @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -disable-llvm-passes %s | \ +// RUN: llvm-cxxfilt | FileCheck %s // Verify that no per variable _Init_thread instructions are emitted for non-trivial static locals // These would normally be emitted by the MicrosoftCXXABI, but the DirectX backend should exlude them @@ -13,17 +14,17 @@ void InitBuf(RWBuffer buf) { } // CHECK-NOT: _Init_thread_epoch -// CHECK: define internal void @_Z4mainv +// CHECK: define internal void @main // CHECK-NEXT: entry: // CHECK-NEXT: [[Tmp0:%.*]] = alloca %"class.hlsl::RWBuffer" // CHECK-NEXT: [[Tmp1:%.*]] = alloca %"class.hlsl::RWBuffer" -// CHECK-NEXT: [[Tmp2:%.*]] = load i8, ptr @_ZGVZ4mainvE5mybuf +// CHECK-NEXT: [[Tmp2:%.*]] = load i8, ptr @guard variable for main()::mybuf // CHECK-NEXT: [[Tmp3:%.*]] = icmp eq i8 [[Tmp2]], 0 // CHECK-NEXT: br i1 [[Tmp3]] // CHECK-NOT: _Init_thread_header // CHECK: init.check: -// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIiEC1EjijjPKc( -// CHECK-NEXT: store i8 1, ptr @_ZGVZ4mainvE5mybuf +// CHECK-NEXT: call void @hlsl::RWBuffer::__createFromImplicitBinding +// CHECK-NEXT: store i8 1, ptr @guard variable for main()::mybuf // CHECK-NOT: _Init_thread_footer