Skip to content

[LLD] LTO internalizing global marked with 'STV_PROTECTED' #128747

Open
@jhuber6

Description

@jhuber6

I'm trying to compile the following files targeting the AMDGPU architecture.

target triple = "amdgcn-amd-amdhsa"

@__llvm_libc_heap_ptr = external hidden addrspace(1) global ptr, align 8

; Function Attrs: convergent mustprogress noinline nounwind optnone
define protected amdgpu_kernel void @kernel(ptr noundef %out) #0 {
entry:
  %out.addr = alloca ptr, align 8, addrspace(5)
  %out.addr.ascast = addrspacecast ptr addrspace(5) %out.addr to ptr
  store ptr %out, ptr %out.addr.ascast, align 8
  %0 = load ptr, ptr addrspacecast (ptr addrspace(1) @__llvm_libc_heap_ptr to ptr), align 8
  %1 = load ptr, ptr %out.addr.ascast, align 8
  store ptr %0, ptr %1, align 8
  ret void
}

attributes #0 = { convergent mustprogress noinline nounwind optnone "frame-pointer"="all" "no-builtin-printf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }

!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.ident = !{!4}

!0 = !{i32 1, !"amdhsa_code_object_version", i32 500}
!1 = !{i32 1, !"wchar_size", i32 4}
!2 = !{i32 8, !"PIC Level", i32 2}
!3 = !{i32 7, !"frame-pointer", i32 2}
!4 = !{!"clang version 21.0.0git"}
target triple = "amdgcn-amd-amdhsa"

@__llvm_libc_heap_ptr = protected local_unnamed_addr addrspace(1) global ptr null, align 8
@__llvm_libc_heap_size = protected local_unnamed_addr addrspace(1) global i64 0, align 8

!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"frame-pointer", i32 2}
!3 = !{i32 1, !"ThinLTO", i32 0}
!4 = !{i32 1, !"EnableSplitLTOUnit", i32 1}
!5 = !{!"clang version 21.0.0git"}

If I take these two files and run them through ld.lld I notice that the reference to the protected variable gets internalized. In the resolutions.txt file, it claims that it is not visible to the regular object because it is not exported. But, this is a -shared build and a protected symbol should not be internalized like this.

ld.lld foo.o bar.o -shared -save-temps

Reading the temporary outputs shows the internalization happening.

$ opt -S a.out.0.0.preopt.bc
@__llvm_libc_heap_size = protected local_unnamed_addr addrspace(1) global i64 0, align 8
@__llvm_libc_heap_ptr = protected local_unnamed_addr addrspace(1) global ptr null, align 8
...
$ opt -S a.out.0.2.internalize.bc
@__llvm_libc_heap_size = protected addrspace(1) global i64 0, align 8
@__llvm_libc_heap_ptr = internal addrspace(1) global ptr null, align 8
...

Metadata

Metadata

Assignees

No one assigned

    Labels

    LTOLink time optimization (regular/full LTO or ThinLTO)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions