[clang] [HLSL] Use hlsl_device address space for getpointer. (PR #127675)
Steven Perron via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 10 10:10:16 PDT 2025
https://github.com/s-perron updated https://github.com/llvm/llvm-project/pull/127675
>From 769344277c6a870b149467fedbe6bcd668c83e95 Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenperron at google.com>
Date: Wed, 12 Feb 2025 15:45:32 -0500
Subject: [PATCH] [HLSL] Use hlsl_device address space for getpointer.
We add the hlsl_device address space to represent the device memory
space as defined in section 1.7.1.3 of the [HLSL
spec](https://microsoft.github.io/hlsl-specs/specs/hlsl.pdf).
Fixes https://github.com/llvm/llvm-project/issues/127075
---
clang/include/clang/Basic/AddressSpaces.h | 1 +
clang/lib/AST/Type.cpp | 8 +++--
clang/lib/AST/TypePrinter.cpp | 2 ++
clang/lib/Basic/Targets/AArch64.h | 1 +
clang/lib/Basic/Targets/AMDGPU.cpp | 2 ++
clang/lib/Basic/Targets/DirectX.h | 1 +
clang/lib/Basic/Targets/NVPTX.h | 1 +
clang/lib/Basic/Targets/SPIR.h | 2 ++
clang/lib/Basic/Targets/SystemZ.h | 1 +
clang/lib/Basic/Targets/TCE.h | 1 +
clang/lib/Basic/Targets/WebAssembly.h | 1 +
clang/lib/Basic/Targets/X86.h | 1 +
clang/lib/CodeGen/CGHLSLBuiltins.cpp | 4 +--
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 21 ++++++++-----
clang/lib/Sema/SemaHLSL.cpp | 6 ++--
clang/test/AST/HLSL/OutArgExpr.hlsl | 14 ++++-----
.../test/AST/HLSL/StructuredBuffers-AST.hlsl | 30 +++++++++----------
clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 22 +++++++-------
.../builtins/RWBuffer-subscript.hlsl | 16 +++++-----
.../StructuredBuffers-subscripts.hlsl | 15 ++++++++++
20 files changed, 94 insertions(+), 56 deletions(-)
diff --git a/clang/include/clang/Basic/AddressSpaces.h b/clang/include/clang/Basic/AddressSpaces.h
index 5787e6dac0e36..519d959bb636c 100644
--- a/clang/include/clang/Basic/AddressSpaces.h
+++ b/clang/include/clang/Basic/AddressSpaces.h
@@ -60,6 +60,7 @@ enum class LangAS : unsigned {
hlsl_groupshared,
hlsl_constant,
hlsl_private,
+ hlsl_device,
// Wasm specific address spaces.
wasm_funcref,
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index f6dffeb0a1a8f..4d9268c1772a9 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -94,10 +94,12 @@ bool Qualifiers::isTargetAddressSpaceSupersetOf(LangAS A, LangAS B,
(A == LangAS::Default &&
(B == LangAS::cuda_constant || B == LangAS::cuda_device ||
B == LangAS::cuda_shared)) ||
- // `this` overloading depending on address space is not ready,
- // so this is a hack to allow generating addrspacecasts.
- // IR legalization will be required when this address space is used.
+ // In HLSL, the this pointer for member functions points to the default
+ // address space. This causes a problem if the structure is in
+ // a different address space. We want to allow casting from these
+ // address spaces to default to work around this problem.
(A == LangAS::Default && B == LangAS::hlsl_private) ||
+ (A == LangAS::Default && B == LangAS::hlsl_device) ||
// Conversions from target specific address spaces may be legal
// depending on the target information.
Ctx.getTargetInfo().isAddressSpaceSupersetOf(A, B);
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 4f2b00d19a446..0075a863620e6 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2583,6 +2583,8 @@ std::string Qualifiers::getAddrSpaceAsString(LangAS AS) {
return "hlsl_constant";
case LangAS::hlsl_private:
return "hlsl_private";
+ case LangAS::hlsl_device:
+ return "hlsl_device";
case LangAS::wasm_funcref:
return "__funcref";
default:
diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index 58822e467ce39..2fab88cfca901 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -46,6 +46,7 @@ static const unsigned ARM64AddrSpaceMap[] = {
0, // hlsl_groupshared
0, // hlsl_constant
0, // hlsl_private
+ 0, // hlsl_device
// Wasm address space values for this target are dummy values,
// as it is only enabled for Wasm targets.
20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp
index f81cdac3b7422..c368200f3f739 100644
--- a/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -63,6 +63,7 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsGenMap = {
// FIXME(pr/122103): hlsl_private -> PRIVATE is wrong, but at least this
// will break loudly.
llvm::AMDGPUAS::PRIVATE_ADDRESS, // hlsl_private
+ llvm::AMDGPUAS::GLOBAL_ADDRESS, // hlsl_device
};
const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
@@ -89,6 +90,7 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_groupshared
llvm::AMDGPUAS::CONSTANT_ADDRESS, // hlsl_constant
llvm::AMDGPUAS::PRIVATE_ADDRESS, // hlsl_private
+ llvm::AMDGPUAS::GLOBAL_ADDRESS, // hlsl_device
};
} // namespace targets
} // namespace clang
diff --git a/clang/lib/Basic/Targets/DirectX.h b/clang/lib/Basic/Targets/DirectX.h
index 4ff66cdd9f8fa..566acd6bb3cf3 100644
--- a/clang/lib/Basic/Targets/DirectX.h
+++ b/clang/lib/Basic/Targets/DirectX.h
@@ -44,6 +44,7 @@ static const unsigned DirectXAddrSpaceMap[] = {
3, // hlsl_groupshared
2, // hlsl_constant
0, // hlsl_private
+ 0, // hlsl_device
// Wasm address space values for this target are dummy values,
// as it is only enabled for Wasm targets.
20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h
index 041596929ff5b..dc1ecc30980b7 100644
--- a/clang/lib/Basic/Targets/NVPTX.h
+++ b/clang/lib/Basic/Targets/NVPTX.h
@@ -48,6 +48,7 @@ static const unsigned NVPTXAddrSpaceMap[] = {
0, // hlsl_groupshared
0, // hlsl_constant
0, // hlsl_private
+ 0, // hlsl_device
// Wasm address space values for this target are dummy values,
// as it is only enabled for Wasm targets.
20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index 5ea727364d24b..4509748589b76 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -49,6 +49,7 @@ static const unsigned SPIRDefIsPrivMap[] = {
0, // hlsl_groupshared
2, // hlsl_constant
10, // hlsl_private
+ 11, // hlsl_device
// Wasm address space values for this target are dummy values,
// as it is only enabled for Wasm targets.
20, // wasm_funcref
@@ -84,6 +85,7 @@ static const unsigned SPIRDefIsGenMap[] = {
0, // hlsl_groupshared
0, // hlsl_constant
10, // hlsl_private
+ 11, // hlsl_device
// Wasm address space values for this target are dummy values,
// as it is only enabled for Wasm targets.
20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index 4d1509b84e82b..dc4534642b9b7 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -44,6 +44,7 @@ static const unsigned ZOSAddressMap[] = {
0, // hlsl_groupshared
0, // hlsl_constant
0, // hlsl_private
+ 0, // hlsl_device
0 // wasm_funcref
};
diff --git a/clang/lib/Basic/Targets/TCE.h b/clang/lib/Basic/Targets/TCE.h
index 44de8aae52a16..f6e582120447f 100644
--- a/clang/lib/Basic/Targets/TCE.h
+++ b/clang/lib/Basic/Targets/TCE.h
@@ -53,6 +53,7 @@ static const unsigned TCEOpenCLAddrSpaceMap[] = {
0, // hlsl_groupshared
0, // hlsl_constant
0, // hlsl_private
+ 0, // hlsl_device
// Wasm address space values for this target are dummy values,
// as it is only enabled for Wasm targets.
20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h
index e786f9a3db68e..04f0cb5df4601 100644
--- a/clang/lib/Basic/Targets/WebAssembly.h
+++ b/clang/lib/Basic/Targets/WebAssembly.h
@@ -44,6 +44,7 @@ static const unsigned WebAssemblyAddrSpaceMap[] = {
0, // hlsl_groupshared
0, // hlsl_constant
0, // hlsl_private
+ 0, // hlsl_device
20, // wasm_funcref
};
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index d44561dd42997..bc8d60f592548 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -48,6 +48,7 @@ static const unsigned X86AddrSpaceMap[] = {
0, // hlsl_groupshared
0, // hlsl_constant
0, // hlsl_private
+ 0, // hlsl_device
// Wasm address space values for this target are dummy values,
// as it is only enabled for Wasm targets.
20, // wasm_funcref
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 99c62808c323d..044d427688267 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -280,9 +280,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
Value *HandleOp = EmitScalarExpr(E->getArg(0));
Value *IndexOp = EmitScalarExpr(E->getArg(1));
- // TODO: Map to an hlsl_device address space.
- llvm::Type *RetTy = llvm::PointerType::getUnqual(getLLVMContext());
-
+ llvm::Type *RetTy = ConvertType(E->getType());
return Builder.CreateIntrinsic(
RetTy, CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(),
ArrayRef<Value *>{HandleOp, IndexOp});
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 2d3e1088557ab..1e022c82b959f 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -751,13 +751,14 @@ BuiltinTypeDeclBuilder::addHandleAccessFunction(DeclarationName &Name,
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
QualType ElemTy = getHandleElementType();
- // TODO: Map to an hlsl_device address space.
- QualType ElemPtrTy = AST.getPointerType(ElemTy);
- QualType ReturnTy = ElemTy;
+ QualType AddrSpaceElemTy =
+ AST.getAddrSpaceQualType(ElemTy, LangAS::hlsl_device);
+ QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
+ // QualType ReturnTy = (IsRef ? AST.getLValueReferenceType(ElemTy) : ElemTy);
+ QualType ReturnTy =
+ (IsRef ? AST.getLValueReferenceType(AddrSpaceElemTy) : ElemTy);
if (IsConst)
ReturnTy.addConst();
- if (IsRef)
- ReturnTy = AST.getLValueReferenceType(ReturnTy);
return BuiltinTypeMethodBuilder(*this, Name, ReturnTy, IsConst)
.addParam("Index", AST.UnsignedIntTy)
@@ -771,12 +772,15 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addAppendMethod() {
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
ASTContext &AST = SemaRef.getASTContext();
QualType ElemTy = getHandleElementType();
+ QualType AddrSpaceElemTy =
+ AST.getAddrSpaceQualType(ElemTy, LangAS::hlsl_device);
return BuiltinTypeMethodBuilder(*this, "Append", AST.VoidTy)
.addParam("value", ElemTy)
.callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
PH::Handle, getConstantIntExpr(1))
.callBuiltin("__builtin_hlsl_resource_getpointer",
- AST.getPointerType(ElemTy), PH::Handle, PH::LastStmt)
+ AST.getPointerType(AddrSpaceElemTy), PH::Handle,
+ PH::LastStmt)
.dereference(PH::LastStmt)
.assign(PH::LastStmt, PH::_0)
.finalize();
@@ -786,11 +790,14 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addConsumeMethod() {
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
ASTContext &AST = SemaRef.getASTContext();
QualType ElemTy = getHandleElementType();
+ QualType AddrSpaceElemTy =
+ AST.getAddrSpaceQualType(ElemTy, LangAS::hlsl_device);
return BuiltinTypeMethodBuilder(*this, "Consume", ElemTy)
.callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
PH::Handle, getConstantIntExpr(-1))
.callBuiltin("__builtin_hlsl_resource_getpointer",
- AST.getPointerType(ElemTy), PH::Handle, PH::LastStmt)
+ AST.getPointerType(AddrSpaceElemTy), PH::Handle,
+ PH::LastStmt)
.dereference(PH::LastStmt)
.finalize();
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 0b442b75d174d..1f763dfc44650 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2379,8 +2379,10 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
auto *ResourceTy =
TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
QualType ContainedTy = ResourceTy->getContainedType();
- // TODO: Map to an hlsl_device address space.
- TheCall->setType(getASTContext().getPointerType(ContainedTy));
+ auto returnType =
+ SemaRef.Context.getAddrSpaceQualType(ContainedTy, LangAS::hlsl_device);
+ returnType = SemaRef.Context.getPointerType(returnType);
+ TheCall->setType(returnType);
TheCall->setValueKind(VK_LValue);
break;
diff --git a/clang/test/AST/HLSL/OutArgExpr.hlsl b/clang/test/AST/HLSL/OutArgExpr.hlsl
index b07c2efadbf4a..04ce635e721bf 100644
--- a/clang/test/AST/HLSL/OutArgExpr.hlsl
+++ b/clang/test/AST/HLSL/OutArgExpr.hlsl
@@ -30,10 +30,10 @@ void zero(out int Z) { Z = 0; }
// AST-NEXT: ImplicitCastExpr {{.*}} 'void (*)(inout int)' <FunctionToPointerDecay>
// AST-NEXT: DeclRefExpr {{.*}} 'void (inout int)' lvalue Function
// AST-NEXT: HLSLOutArgExpr {{.*}} 'int' lvalue inout
-// AST-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'float' lvalue
-// AST-NEXT: CXXOperatorCallExpr {{.*}} 'float' lvalue '[]'
-// AST-NEXT: ImplicitCastExpr {{.*}} 'float &(*)(unsigned int)' <FunctionToPointerDecay>
-// AST-NEXT: DeclRefExpr {{.*}} 'float &(unsigned int)' lvalue CXXMethod {{.*}} 'operator[]' 'float &(unsigned int)'
+// AST-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'hlsl_device float' lvalue
+// AST-NEXT: CXXOperatorCallExpr {{.*}} 'hlsl_device float' lvalue '[]'
+// AST-NEXT: ImplicitCastExpr {{.*}} 'hlsl_device float &(*)(unsigned int)' <FunctionToPointerDecay>
+// AST-NEXT: DeclRefExpr {{.*}} 'hlsl_device float &(unsigned int)' lvalue CXXMethod {{.*}} 'operator[]' 'hlsl_device float &(unsigned int)'
// AST-NEXT: DeclRefExpr {{.*}} 'RWBuffer<float>':'hlsl::RWBuffer<float>' lvalue Var {{.*}} 'Buf' 'RWBuffer<float>':'hlsl::RWBuffer<float>'
// AST-NEXT: ImplicitCastExpr {{.*}} 'uint':'unsigned int' <LValueToRValue>
// AST-NEXT: DeclRefExpr {{.*}} 'uint':'unsigned int' lvalue ParmVar {{.*}} 'GI' 'uint':'unsigned int'
@@ -41,10 +41,10 @@ void zero(out int Z) { Z = 0; }
// AST-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue
// AST-NEXT: ImplicitCastExpr {{.*}} 'int' <FloatingToIntegral>
// AST-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
-// AST-NEXT: OpaqueValueExpr [[LVOpV]] <col:15, col:21> 'float' lvalue
+// AST-NEXT: OpaqueValueExpr [[LVOpV]] <col:15, col:21> 'hlsl_device float' lvalue
-// AST: BinaryOperator {{.*}} 'float' lvalue '='
-// AST-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'float' lvalue
+// AST: BinaryOperator {{.*}} 'hlsl_device float' lvalue '='
+// AST-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'hlsl_device float' lvalue
// AST: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
// AST-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
// AST-NEXT: OpaqueValueExpr [[TmpOpV]] {{.*}} 'int' lvalue
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index dcead068f481e..75dd4fe23121b 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -89,12 +89,12 @@ RESOURCE<float> Buffer;
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
-// CHECK-SUBSCRIPT: CXXMethodDecl {{.*}} operator[] 'const element_type &(unsigned int) const'
+// CHECK-SUBSCRIPT: CXXMethodDecl {{.*}} operator[] 'hlsl_device element_type &const (unsigned int) const'
// CHECK-SUBSCRIPT-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-SUBSCRIPT-NEXT: CompoundStmt
// CHECK-SUBSCRIPT-NEXT: ReturnStmt
-// CHECK-SUBSCRIPT-NEXT: UnaryOperator {{.*}} 'element_type' prefix '*' cannot overflow
-// CHECK-SUBSCRIPT-NEXT: CallExpr {{.*}} 'element_type *'
+// CHECK-SUBSCRIPT-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-SUBSCRIPT-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
// CHECK-SUBSCRIPT-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
// CHECK-SUBSCRIPT-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
// CHECK-SUBSCRIPT-SAME{LITERAL}: [[hlsl::resource_class(
@@ -105,12 +105,12 @@ RESOURCE<float> Buffer;
// CHECK-SUBSCRIPT-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-SUBSCRIPT-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-SUBSCRIPT-NEXT: CXXMethodDecl {{.*}} operator[] 'element_type &(unsigned int)'
+// CHECK-SUBSCRIPT-NEXT: CXXMethodDecl {{.*}} operator[] 'hlsl_device element_type &(unsigned int)'
// CHECK-SUBSCRIPT-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-SUBSCRIPT-NEXT: CompoundStmt
// CHECK-SUBSCRIPT-NEXT: ReturnStmt
-// CHECK-SUBSCRIPT-NEXT: UnaryOperator {{.*}} 'element_type' prefix '*' cannot overflow
-// CHECK-SUBSCRIPT-NEXT: CallExpr {{.*}} 'element_type *'
+// CHECK-SUBSCRIPT-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-SUBSCRIPT-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
// CHECK-SUBSCRIPT-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
// CHECK-SUBSCRIPT-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
// CHECK-SUBSCRIPT-SAME{LITERAL}: [[hlsl::resource_class(
@@ -121,15 +121,15 @@ RESOURCE<float> Buffer;
// CHECK-SUBSCRIPT-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-SUBSCRIPT-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'const element_type &(unsigned int) const'
-// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'element_type &(unsigned int)'
+// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'hlsl_device element_type &const (unsigned int) const'
+// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'hlsl_device element_type &(unsigned int)'
// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int)'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
-// CHECK-LOAD-NEXT: UnaryOperator {{.*}} 'element_type' prefix '*' cannot overflow
-// CHECK-LOAD-NEXT: CallExpr {{.*}} 'element_type *'
+// CHECK-LOAD-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
// CHECK-LOAD-SAME{LITERAL}: [[hlsl::resource_class(
@@ -168,9 +168,9 @@ RESOURCE<float> Buffer;
// CHECK-APPEND: CXXMethodDecl {{.*}} Append 'void (element_type)'
// CHECK-APPEND-NEXT: ParmVarDecl {{.*}} value 'element_type'
// CHECK-APPEND-NEXT: CompoundStmt
-// CHECK-APPEND-NEXT: BinaryOperator {{.*}} 'element_type' '='
-// CHECK-APPEND-NEXT: UnaryOperator {{.*}} 'element_type' prefix '*' cannot overflow
-// CHECK-APPEND-NEXT: CallExpr {{.*}} 'element_type *'
+// CHECK-APPEND-NEXT: BinaryOperator {{.*}} 'hlsl_device element_type' '='
+// CHECK-APPEND-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-APPEND-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
// CHECK-APPEND-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
// CHECK-APPEND-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
// CHECK-APPEND-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
@@ -190,8 +190,8 @@ RESOURCE<float> Buffer;
// CHECK-CONSUME: CXXMethodDecl {{.*}} Consume 'element_type ()'
// CHECK-CONSUME-NEXT: CompoundStmt
// CHECK-CONSUME-NEXT: ReturnStmt
-// CHECK-CONSUME-NEXT: UnaryOperator {{.*}} 'element_type' prefix '*' cannot overflow
-// CHECK-CONSUME-NEXT: CallExpr {{.*}} 'element_type *'
+// CHECK-CONSUME-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-CONSUME-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
// CHECK-CONSUME-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
// CHECK-CONSUME-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
// CHECK-CONSUME-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index f665b06d691e8..1da474469c0c0 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -56,32 +56,32 @@ RESOURCE<float> Buffer;
// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
-// CHECK: CXXMethodDecl {{.*}} operator[] 'const element_type &(unsigned int) const'
+// CHECK: CXXMethodDecl {{.*}} operator[] 'hlsl_device element_type &const (unsigned int) const'
// CHECK-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: ReturnStmt
-// CHECK-NEXT: UnaryOperator {{.*}} 'element_type' prefix '*' cannot overflow
-// CHECK-NEXT: CallExpr {{.*}} 'element_type *'
+// CHECK-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
-// CHECK-SAME: ' lvalue .__handle {{.*}}
+// CHECK-SAME: ' lvalue .__handle {{.*}}
// CHECK-NEXT: CXXThisExpr {{.*}} 'const [[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-NEXT: CXXMethodDecl {{.*}} operator[] 'element_type &(unsigned int)'
+// CHECK-NEXT: CXXMethodDecl {{.*}} operator[] 'hlsl_device element_type &(unsigned int)'
// CHECK-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: ReturnStmt
-// CHECK-NEXT: UnaryOperator {{.*}} 'element_type' prefix '*' cannot overflow
-// CHECK-NEXT: CallExpr {{.*}} 'element_type *'
+// CHECK-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
-// CHECK-SAME: ' lvalue .__handle {{.*}}
+// CHECK-SAME: ' lvalue .__handle {{.*}}
// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
@@ -90,13 +90,13 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: ReturnStmt
-// CHECK-NEXT: UnaryOperator {{.*}} 'element_type' prefix '*' cannot overflow
-// CHECK-NEXT: CallExpr {{.*}} 'element_type *'
+// CHECK-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
-// CHECK-SAME: ' lvalue .__handle {{.*}}
+// CHECK-SAME: ' lvalue .__handle {{.*}}
// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
index 2ad5b82a02912..cf810ed909eb7 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
@@ -9,18 +9,18 @@ void main(unsigned GI : SV_GroupIndex) {
// CHECK: define void @main()
// DXC: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
- // SPIRV: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}})
- // CHECK: %[[LOAD:.*]] = load i32, ptr %[[INPTR]]
+ // SPIRV: %[[INPTR:.*]] = call noundef align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}})
+ // CHECK: %[[LOAD:.*]] = load i32, ptr {{.*}}%[[INPTR]]
// DXC: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
- // SPIRV: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}})
- // CHECK: store i32 %[[LOAD]], ptr %[[OUTPTR]]
+ // SPIRV: %[[OUTPTR:.*]] = call noundef align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}})
+ // CHECK: store i32 %[[LOAD]], ptr {{.*}}%[[OUTPTR]]
Out[GI] = In[GI];
// DXC: %[[INPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
- // SPIRV: %[[INPTR:.*]] = call ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}})
- // CHECK: %[[LOAD:.*]] = load i32, ptr %[[INPTR]]
+ // SPIRV: %[[INPTR:.*]] = call ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}})
+ // CHECK: %[[LOAD:.*]] = load i32, ptr {{.*}}%[[INPTR]]
// DXC: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
- // SPIRV: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}})
- // CHECK: store i32 %[[LOAD]], ptr %[[OUTPTR]]
+ // SPIRV: %[[OUTPTR:.*]] = call noundef align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}})
+ // CHECK: store i32 %[[LOAD]], ptr {{.*}}%[[OUTPTR]]
Out[GI] = In.Load(GI);
}
diff --git a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-subscripts.hlsl b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-subscripts.hlsl
index 2af7c3ed3219f..93d07c9be5964 100644
--- a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-subscripts.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-subscripts.hlsl
@@ -1,7 +1,12 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s
+struct S {
+ float f;
+};
+
StructuredBuffer<int> In;
RWStructuredBuffer<int> Out1;
+RWStructuredBuffer<S> RWSB3;
RasterizerOrderedStructuredBuffer<int> Out2;
[numthreads(1,1,1)]
@@ -19,4 +24,14 @@ void main(unsigned GI : SV_GroupIndex) {
// CHECK: %[[OUT2PTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_1t(target("dx.RawBuffer", i32, 1, 1) %{{.*}}, i32 %{{.*}})
// CHECK: store i32 %[[LOAD]], ptr %[[OUT2PTR]]
Out2[GI] = In[GI];
+
+ // For SPIR-V, the addrspacecast comes from `S::operator=` member function, which expects
+ // parameters in address space 0. This is why hlsl_device is a sub address
+ // space of the default address space.
+
+ // For DXIL, hlsl_device and the default address space map to the same target address space. No need for an address space cast.
+ // CHECK: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_s_struct.Ss_1_0t(target("dx.RawBuffer", %struct.S, 1, 0) %{{.*}}, i32 %{{.*}})
+ // CHECK: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_s_struct.Ss_1_0t(target("dx.RawBuffer", %struct.S, 1, 0) %{{.*}}, i32 %{{.*}})
+ // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[OUTPTR]], ptr align 4 %[[INPTR]], i32 4, i1 false)
+ RWSB3[0] = RWSB3[1];
}
More information about the cfe-commits
mailing list