Skip to content

[HLSL] Use hidden visibility for external linkage. #140292

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions clang/lib/CodeGen/CGHLSLRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,14 +471,6 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
}
}

void CGHLSLRuntime::setHLSLFunctionAttributes(const FunctionDecl *FD,
llvm::Function *Fn) {
if (FD->isInExportDeclContext()) {
const StringRef ExportAttrKindStr = "hlsl.export";
Fn->addFnAttr(ExportAttrKindStr);
}
}

static void gatherFunctions(SmallVectorImpl<Function *> &Fns, llvm::Module &M,
bool CtorOrDtor) {
const auto *GV =
Expand Down
1 change: 0 additions & 1 deletion clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1267,7 +1267,6 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
if (FD->hasAttr<HLSLShaderAttr>()) {
CGM.getHLSLRuntime().emitEntryFunction(FD, Fn);
}
CGM.getHLSLRuntime().setHLSLFunctionAttributes(FD, Fn);
}

EmitFunctionProlog(*CurFnInfo, CurFn, Args);
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1666,6 +1666,11 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
return;
}

if (Context.getLangOpts().HLSL && !D->isInExportDeclContext()) {
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GV at line 379 should also be updated, as well as the one for HLSLBufferDecl no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll look into this for a follow up PR if necessary. This change affects many tests, and I don't want it to go stale.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify what code you are referring it? Like 379 in this file does not have to do with global variables. As for the HLSLBufferDecl, I'll look into some examples tomorrow. I don't think it will be a problem though. The buffers decls for cbuffer require special handling that is not implemented for Spir-v yet. I think it is still unclear how that should be handled.

return;
}

if (GV->hasDLLExportStorageClass() || GV->hasDLLImportStorageClass()) {
// Reject incompatible dlllstorage and visibility annotations.
if (!LV.isVisibilityExplicit())
Expand Down
30 changes: 15 additions & 15 deletions clang/test/CodeGenHLSL/ArrayAssignable.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ struct S {

// CHECK: [[CBLayout:%.*]] = type <{ [2 x float], [2 x <4 x i32>], [2 x [2 x i32]], [1 x target("dx.Layout", %S, 8, 0, 4)] }>
// CHECK: @CBArrays.cb = global target("dx.CBuffer", target("dx.Layout", [[CBLayout]], 136, 0, 32, 64, 128))
// CHECK: @c1 = external addrspace(2) global [2 x float], align 4
// CHECK: @c2 = external addrspace(2) global [2 x <4 x i32>], align 16
// CHECK: @c3 = external addrspace(2) global [2 x [2 x i32]], align 4
// CHECK: @c4 = external addrspace(2) global [1 x target("dx.Layout", %S, 8, 0, 4)], align 1
// CHECK: @c1 = external hidden addrspace(2) global [2 x float], align 4
// CHECK: @c2 = external hidden addrspace(2) global [2 x <4 x i32>], align 16
// CHECK: @c3 = external hidden addrspace(2) global [2 x [2 x i32]], align 4
// CHECK: @c4 = external hidden addrspace(2) global [1 x target("dx.Layout", %S, 8, 0, 4)], align 1

cbuffer CBArrays : register(b0) {
float c1[2];
Expand All @@ -19,7 +19,7 @@ cbuffer CBArrays : register(b0) {
S c4[1];
}

// CHECK-LABEL: define void {{.*}}arr_assign1
// CHECK-LABEL: define hidden void {{.*}}arr_assign1
// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Arr2:%.*]] = alloca [2 x i32], align 4
// CHECK-NOT: alloca
Expand All @@ -33,7 +33,7 @@ void arr_assign1() {
Arr = Arr2;
}

// CHECK-LABEL: define void {{.*}}arr_assign2
// CHECK-LABEL: define hidden void {{.*}}arr_assign2
// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Arr2:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Arr3:%.*]] = alloca [2 x i32], align 4
Expand All @@ -51,7 +51,7 @@ void arr_assign2() {
Arr = Arr2 = Arr3;
}

// CHECK-LABEL: define void {{.*}}arr_assign3
// CHECK-LABEL: define hidden void {{.*}}arr_assign3
// CHECK: [[Arr3:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NEXT: [[Arr4:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NOT: alloca
Expand All @@ -65,7 +65,7 @@ void arr_assign3() {
Arr2 = Arr3;
}

// CHECK-LABEL: define void {{.*}}arr_assign4
// CHECK-LABEL: define hidden void {{.*}}arr_assign4
// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Arr2:%.*]] = alloca [2 x i32], align 4
// CHECK-NOT: alloca
Expand All @@ -81,7 +81,7 @@ void arr_assign4() {
(Arr = Arr2)[0] = 6;
}

// CHECK-LABEL: define void {{.*}}arr_assign5
// CHECK-LABEL: define hidden void {{.*}}arr_assign5
// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Arr2:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Arr3:%.*]] = alloca [2 x i32], align 4
Expand All @@ -101,7 +101,7 @@ void arr_assign5() {
(Arr = Arr2 = Arr3)[0] = 6;
}

// CHECK-LABEL: define void {{.*}}arr_assign6
// CHECK-LABEL: define hidden void {{.*}}arr_assign6
// CHECK: [[Arr3:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NEXT: [[Arr4:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NOT: alloca
Expand All @@ -118,7 +118,7 @@ void arr_assign6() {
(Arr = Arr2)[0][0] = 6;
}

// CHECK-LABEL: define void {{.*}}arr_assign7
// CHECK-LABEL: define hidden void {{.*}}arr_assign7
// CHECK: [[Arr:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NEXT: [[Arr2:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NOT: alloca
Expand All @@ -138,7 +138,7 @@ void arr_assign7() {

// Verify you can assign from a cbuffer array

// CHECK-LABEL: define void {{.*}}arr_assign8
// CHECK-LABEL: define hidden void {{.*}}arr_assign8
// CHECK: [[C:%.*]] = alloca [2 x float], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[C]], ptr align 4 {{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p2.i32(ptr align 4 [[C]], ptr addrspace(2) align 4 @c1, i32 8, i1 false)
Expand All @@ -148,7 +148,7 @@ void arr_assign8() {
C = c1;
}

// CHECK-LABEL: define void {{.*}}arr_assign9
// CHECK-LABEL: define hidden void {{.*}}arr_assign9
// CHECK: [[C:%.*]] = alloca [2 x <4 x i32>], align 16
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[C]], ptr align 16 {{.*}}, i32 32, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p2.i32(ptr align 16 [[C]], ptr addrspace(2) align 16 @c2, i32 32, i1 false)
Expand All @@ -158,7 +158,7 @@ void arr_assign9() {
C = c2;
}

// CHECK-LABEL: define void {{.*}}arr_assign10
// CHECK-LABEL: define hidden void {{.*}}arr_assign10
// CHECK: [[C:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[C]], ptr align 4 {{.*}}, i32 16, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p2.i32(ptr align 4 [[C]], ptr addrspace(2) align 4 @c3, i32 16, i1 false)
Expand All @@ -168,7 +168,7 @@ void arr_assign10() {
C = c3;
}

// CHECK-LABEL: define void {{.*}}arr_assign11
// CHECK-LABEL: define hidden void {{.*}}arr_assign11
// CHECK: [[C:%.*]] = alloca [1 x %struct.S], align 1
// CHECK: call void @llvm.memcpy.p0.p2.i32(ptr align 1 [[C]], ptr addrspace(2) align 1 @c4, i32 8, i1 false)
// CHECK-NEXT: ret void
Expand Down
12 changes: 6 additions & 6 deletions clang/test/CodeGenHLSL/ArrayTemporary.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

void fn(float x[2]) { }

// CHECK-LABEL: define void {{.*}}call{{.*}}
// CHECK-LABEL: define hidden void {{.*}}call{{.*}}
// CHECK: [[Arr:%.*]] = alloca [2 x float]
// CHECK: [[Tmp:%.*]] = alloca [2 x float]
// CHECK: call void @llvm.memset.p0.i32(ptr align 4 [[Arr]], i8 0, i32 8, i1 false)
Expand All @@ -21,7 +21,7 @@ struct Obj {

void fn2(Obj O[4]) { }

// CHECK-LABEL: define void {{.*}}call2{{.*}}
// CHECK-LABEL: define hidden void {{.*}}call2{{.*}}
// CHECK: [[Arr:%.*]] = alloca [4 x %struct.Obj]
// CHECK: [[Tmp:%.*]] = alloca [4 x %struct.Obj]
// CHECK: call void @llvm.memset.p0.i32(ptr align 1 [[Arr]], i8 0, i32 32, i1 false)
Expand All @@ -35,7 +35,7 @@ void call2() {

void fn3(float x[2][2]) { }

// CHECK-LABEL: define void {{.*}}call3{{.*}}
// CHECK-LABEL: define hidden void {{.*}}call3{{.*}}
// CHECK: [[Arr:%.*]] = alloca [2 x [2 x float]]
// CHECK: [[Tmp:%.*]] = alloca [2 x [2 x float]]
// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 {{.*}}, i32 16, i1 false)
Expand All @@ -46,7 +46,7 @@ void call3() {
fn3(Arr);
}

// CHECK-LABEL: define void {{.*}}call4{{.*}}(ptr
// CHECK-LABEL: define hidden void {{.*}}call4{{.*}}(ptr
// CHECK-SAME: noundef byval([2 x [2 x float]]) align 4 [[Arr:%.*]])
// CHECK: [[Tmp:%.*]] = alloca [2 x [2 x float]]
// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 16, i1 false)
Expand All @@ -59,7 +59,7 @@ void call4(float Arr[2][2]) {
// Verify that each template instantiation codegens to a unique and correctly
// mangled function name.

// CHECK-LABEL: define void {{.*}}template_call{{.*}}(ptr
// CHECK-LABEL: define hidden void {{.*}}template_call{{.*}}(ptr

// CHECK-SAME: noundef byval([2 x float]) align 4 [[FA2:%[0-9A-Z]+]],
// CHECK-SAME: ptr noundef byval([4 x float]) align 4 [[FA4:%[0-9A-Z]+]],
Expand All @@ -86,7 +86,7 @@ void template_call(float FA2[2], float FA4[4], int IA3[3]) {


// Verify that Array parameter element access correctly codegens.
// CHECK-LABEL: define void {{.*}}element_access{{.*}}(ptr
// CHECK-LABEL: define hidden void {{.*}}element_access{{.*}}(ptr
// CHECK-SAME: noundef byval([2 x float]) align 4 [[FA2:%[0-9A-Z]+]]

// CHECK: [[Addr:%.*]] = getelementptr inbounds [2 x float], ptr [[FA2]], i32 0, i32 0
Expand Down
14 changes: 7 additions & 7 deletions clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void increment(inout int Arr[2]) {
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
// CHECK-NEXT: call void @{{.*}}increment{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) #3
// CHECK-NEXT: call void @{{.*}}increment{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0
// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4
Expand All @@ -32,7 +32,7 @@ void fn2(out int Arr[2]) {
// CHECK: [[A:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @{{.*}}fn2{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) #3
// CHECK-NEXT: call void @{{.*}}fn2{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0
// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4
Expand All @@ -56,7 +56,7 @@ void nestedCall(inout int Arr[2], uint index) {
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
// CHECK-NEXT: call void @{{.*}}nestedCall{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]], i32 noundef 0) #3
// CHECK-NEXT: call void @{{.*}}nestedCall{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]], i32 noundef 0)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 1
// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4
Expand All @@ -70,7 +70,7 @@ export int arrayCall3() {
// CHECK-LABEL: outerCall
// CHECK: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 %{{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void {{.*}}increment{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) #3
// CHECK-NEXT: call void {{.*}}increment{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 {{.*}}, ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: ret void
void outerCall(inout int Arr[2]) {
Expand All @@ -82,7 +82,7 @@ void outerCall(inout int Arr[2]) {
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
// CHECK-NEXT: call void @{{.*}}outerCall{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) #3
// CHECK-NEXT: call void @{{.*}}outerCall{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0
// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4
Expand All @@ -99,7 +99,7 @@ void fn3(int Arr[2]) {}
// CHECK-LABEL: outerCall2
// CHECK: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 {{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void {{.*}}fn3{{.*}}(ptr noundef byval([2 x i32]) align 4 [[Tmp]]) #3
// CHECK-NEXT: call void {{.*}}fn3{{.*}}(ptr noundef byval([2 x i32]) align 4 [[Tmp]])
// CHECK-NEXT: ret void
void outerCall2(inout int Arr[2]) {
fn3(Arr);
Expand All @@ -110,7 +110,7 @@ void outerCall2(inout int Arr[2]) {
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
// CHECK-NEXT: call void @{{.*}}outerCall2{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) #3
// CHECK-NEXT: call void @{{.*}}outerCall2{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0
// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4
Expand Down
Loading
Loading