Skip to content

Emit global strings in the correct address space. #516

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 3 commits into from
Jun 17, 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
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "LLVM"
uuid = "929cbde3-209d-540e-8aea-75f648917ca0"
version = "9.4.0"
version = "9.4.1"

[deps]
CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82"
Expand All @@ -19,7 +19,7 @@ BFloat16sExt = "BFloat16s"
[compat]
BFloat16s = "0.4, 0.5"
CEnum = "0.2, 0.3, 0.4, 0.5"
LLVMExtra_jll = "=0.0.36"
LLVMExtra_jll = "=0.0.37"
Libdl = "1.8"
Preferences = "1.4"
Printf = "1.8"
Expand Down
3 changes: 3 additions & 0 deletions deps/LLVMExtra/include/LLVMExtra.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,5 +255,8 @@ LLVMErrorRef LLVMRunJuliaPassesOnFunction(LLVMValueRef F, const char *Passes,
LLVMPassBuilderOptionsRef Options,
LLVMPassBuilderExtensionsRef Extensions);

// More DataLayout queries
unsigned LLVMGlobalsAddressSpace(LLVMTargetDataRef TD);

LLVM_C_EXTERN_C_END
#endif
11 changes: 10 additions & 1 deletion deps/LLVMExtra/lib/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,8 @@ void LLVMSetAtomicSyncScopeID(LLVMValueRef AtomicInst, unsigned SSID) {
setAtomicSyncScopeID(I, SSID);
}

#endif


//
// more LLVMContextRef getters
Expand All @@ -797,4 +799,11 @@ LLVMContextRef LLVMGetBuilderContext(LLVMBuilderRef Builder) {

#endif

#endif

//
// More DataLayout queries
//

unsigned LLVMGlobalsAddressSpace(LLVMTargetDataRef TD) {
return unwrap(TD)->getDefaultGlobalsAddressSpace();
}
1 change: 1 addition & 0 deletions docs/src/lib/codegen.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ dispose(::DataLayout)
byteorder
pointersize
intptr
globals_addrspace
sizeof(::DataLayout, ::LLVMType)
storage_size
abi_size
Expand Down
1 change: 1 addition & 0 deletions docs/src/man/codegen.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ generating IR:
- `byteorder`
- `pointersize`
- `intptr`
- `globals_addrspace`
- `sizeof`
- `storage_size`
- `abi_alignment`
Expand Down
4 changes: 4 additions & 0 deletions lib/15/libLLVM_extra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -401,3 +401,7 @@ function LLVMRunJuliaPassesOnFunction(F, Passes, TM, Options, Extensions)
ccall((:LLVMRunJuliaPassesOnFunction, libLLVMExtra), LLVMErrorRef, (LLVMValueRef, Cstring, LLVMTargetMachineRef, LLVMPassBuilderOptionsRef, LLVMPassBuilderExtensionsRef), F, Passes, TM, Options, Extensions)
end

function LLVMGlobalsAddressSpace(TD)
ccall((:LLVMGlobalsAddressSpace, libLLVMExtra), Cuint, (LLVMTargetDataRef,), TD)
end

4 changes: 4 additions & 0 deletions lib/16/libLLVM_extra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -401,3 +401,7 @@ function LLVMRunJuliaPassesOnFunction(F, Passes, TM, Options, Extensions)
ccall((:LLVMRunJuliaPassesOnFunction, libLLVMExtra), LLVMErrorRef, (LLVMValueRef, Cstring, LLVMTargetMachineRef, LLVMPassBuilderOptionsRef, LLVMPassBuilderExtensionsRef), F, Passes, TM, Options, Extensions)
end

function LLVMGlobalsAddressSpace(TD)
ccall((:LLVMGlobalsAddressSpace, libLLVMExtra), Cuint, (LLVMTargetDataRef,), TD)
end

4 changes: 4 additions & 0 deletions lib/17/libLLVM_extra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -361,3 +361,7 @@ function LLVMRunJuliaPassesOnFunction(F, Passes, TM, Options, Extensions)
ccall((:LLVMRunJuliaPassesOnFunction, libLLVMExtra), LLVMErrorRef, (LLVMValueRef, Cstring, LLVMTargetMachineRef, LLVMPassBuilderOptionsRef, LLVMPassBuilderExtensionsRef), F, Passes, TM, Options, Extensions)
end

function LLVMGlobalsAddressSpace(TD)
ccall((:LLVMGlobalsAddressSpace, libLLVMExtra), Cuint, (LLVMTargetDataRef,), TD)
end

4 changes: 4 additions & 0 deletions lib/18/libLLVM_extra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,7 @@ function LLVMRunJuliaPassesOnFunction(F, Passes, TM, Options, Extensions)
ccall((:LLVMRunJuliaPassesOnFunction, libLLVMExtra), LLVMErrorRef, (LLVMValueRef, Cstring, LLVMTargetMachineRef, LLVMPassBuilderOptionsRef, LLVMPassBuilderExtensionsRef), F, Passes, TM, Options, Extensions)
end

function LLVMGlobalsAddressSpace(TD)
ccall((:LLVMGlobalsAddressSpace, libLLVMExtra), Cuint, (LLVMTargetDataRef,), TD)
end

4 changes: 4 additions & 0 deletions lib/19/libLLVM_extra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,7 @@ function LLVMRunJuliaPassesOnFunction(F, Passes, TM, Options, Extensions)
ccall((:LLVMRunJuliaPassesOnFunction, libLLVMExtra), LLVMErrorRef, (LLVMValueRef, Cstring, LLVMTargetMachineRef, LLVMPassBuilderOptionsRef, LLVMPassBuilderExtensionsRef), F, Passes, TM, Options, Extensions)
end

function LLVMGlobalsAddressSpace(TD)
ccall((:LLVMGlobalsAddressSpace, libLLVMExtra), Cuint, (LLVMTargetDataRef,), TD)
end

4 changes: 4 additions & 0 deletions lib/20/libLLVM_extra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,7 @@ function LLVMRunJuliaPassesOnFunction(F, Passes, TM, Options, Extensions)
ccall((:LLVMRunJuliaPassesOnFunction, libLLVMExtra), LLVMErrorRef, (LLVMValueRef, Cstring, LLVMTargetMachineRef, LLVMPassBuilderOptionsRef, LLVMPassBuilderExtensionsRef), F, Passes, TM, Options, Extensions)
end

function LLVMGlobalsAddressSpace(TD)
ccall((:LLVMGlobalsAddressSpace, libLLVMExtra), Cuint, (LLVMTargetDataRef,), TD)
end

91 changes: 49 additions & 42 deletions src/datalayout.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## data layout

export DataLayout, dispose,
byteorder, pointersize, intptr,
byteorder, pointersize, intptr, globals_addrspace,
sizeof, storage_size, abi_size,
abi_alignment, frame_alignment, preferred_alignment,
element_at, offsetof
Expand Down Expand Up @@ -38,119 +38,126 @@ This object needs to be disposed of using [`dispose`](@ref).
DataLayout(tm::TargetMachine) = mark_alloc(DataLayout(API.LLVMCreateTargetDataLayout(tm)))

"""
dispose(data::DataLayout)
dispose(dl::DataLayout)
Dispose of the given target data layout.
"""
dispose(data::DataLayout) = mark_dispose(API.LLVMDisposeTargetData, data)
dispose(dl::DataLayout) = mark_dispose(API.LLVMDisposeTargetData, dl)

function DataLayout(f::Core.Function, args...; kwargs...)
data = DataLayout(args...; kwargs...)
dl = DataLayout(args...; kwargs...)
try
f(data)
f(dl)
finally
dispose(data)
dispose(dl)
end
end

Base.string(data::DataLayout) =
unsafe_message(API.LLVMCopyStringRepOfTargetData(data))
Base.string(dl::DataLayout) =
unsafe_message(API.LLVMCopyStringRepOfTargetData(dl))

function Base.show(io::IO, data::DataLayout)
@printf(io, "DataLayout(%s)", string(data))
function Base.show(io::IO, dl::DataLayout)
@printf(io, "DataLayout(%s)", string(dl))
end

"""
byteorder(data::DataLayout)
byteorder(dl::DataLayout)
Get the byte order of the target data layout.
"""
byteorder(data::DataLayout) = API.LLVMByteOrder(data)
byteorder(dl::DataLayout) = API.LLVMByteOrder(dl)

"""
pointersize(data::DataLayout, [addrspace::Integer])
pointersize(dl::DataLayout, [addrspace::Integer])
Get the pointer size of the target data layout.
"""
pointersize(data::DataLayout, addrspace::Integer=0) =
API.LLVMPointerSizeForAS(data, addrspace)
pointersize(dl::DataLayout, addrspace::Integer=0) =
API.LLVMPointerSizeForAS(dl, addrspace)

"""
intptr(data::DataLayout, [addrspace::Integer])
intptr(dl::DataLayout, [addrspace::Integer])
Get the integer type that is the same size as a pointer for the target data layout.
"""
intptr(data::DataLayout, addrspace::Integer=0) =
IntegerType(API.LLVMIntPtrTypeForASInContext(context(), data, addrspace))
intptr(dl::DataLayout, addrspace::Integer=0) =
IntegerType(API.LLVMIntPtrTypeForASInContext(context(), dl, addrspace))

"""
sizeof(data::DataLayout, typ::LLVMType)
globals_addrspace(dl::DataLayout)
Get the address space used for global variables in the target data layout.
"""
globals_addrspace(dl::DataLayout) = API.LLVMGlobalsAddressSpace(dl) |> Int

"""
sizeof(dl::DataLayout, typ::LLVMType)
Get the size of the given type in bytes for the target data layout.
"""
Base.sizeof(data::DataLayout, typ::LLVMType) = Int(API.LLVMSizeOfTypeInBits(data, typ) / 8)
Base.sizeof(dl::DataLayout, typ::LLVMType) = Int(API.LLVMSizeOfTypeInBits(dl, typ) / 8)

"""
storage_size(data::DataLayout, typ::LLVMType)
storage_size(dl::DataLayout, typ::LLVMType)
Get the storage size of the given type in bytes for the target data layout.
"""
storage_size(data::DataLayout, typ::LLVMType) = API.LLVMStoreSizeOfType(data, typ)
storage_size(dl::DataLayout, typ::LLVMType) = API.LLVMStoreSizeOfType(dl, typ)

"""
abi_size(data::DataLayout, typ::LLVMType)
abi_size(dl::DataLayout, typ::LLVMType)
Get the ABI size of the given type in bytes for the target data layout.
"""
abi_size(data::DataLayout, typ::LLVMType) = API.LLVMABISizeOfType(data, typ)
abi_size(dl::DataLayout, typ::LLVMType) = API.LLVMABISizeOfType(dl, typ)

"""
abi_alignment(data::DataLayout, typ::LLVMType)
abi_alignment(dl::DataLayout, typ::LLVMType)
Get the ABI alignment of the given type in bytes for the target data layout.
"""
abi_alignment(data::DataLayout, typ::LLVMType) =
API.LLVMABIAlignmentOfType(data, typ)
abi_alignment(dl::DataLayout, typ::LLVMType) =
API.LLVMABIAlignmentOfType(dl, typ)

"""
frame_alignment(data::DataLayout, typ::LLVMType)
frame_alignment(dl::DataLayout, typ::LLVMType)
Get the call frame alignment of the given type in bytes for the target data layout.
"""
frame_alignment(data::DataLayout, typ::LLVMType) =
API.LLVMCallFrameAlignmentOfType(data, typ)
frame_alignment(dl::DataLayout, typ::LLVMType) =
API.LLVMCallFrameAlignmentOfType(dl, typ)


"""
preferred_alignment(data::DataLayout, typ::LLVMType)
preferred_alignment(data::DataLayout, var::GlobalVariable)
preferred_alignment(dl::DataLayout, typ::LLVMType)
preferred_alignment(dl::DataLayout, var::GlobalVariable)
Get the preferred alignment of the given type or global variable in bytes for the target
data layout.
"""
preferred_alignment(::DataLayout, ::Union{LLVMType, GlobalVariable})

preferred_alignment(data::DataLayout, typ::LLVMType) =
API.LLVMPreferredAlignmentOfType(data, typ)
preferred_alignment(data::DataLayout, var::GlobalVariable) =
API.LLVMPreferredAlignmentOfGlobal(data, var)
preferred_alignment(dl::DataLayout, typ::LLVMType) =
API.LLVMPreferredAlignmentOfType(dl, typ)
preferred_alignment(dl::DataLayout, var::GlobalVariable) =
API.LLVMPreferredAlignmentOfGlobal(dl, var)

"""
element_at(data::DataLayout, typ::StructType, offset::Integer)
element_at(dl::DataLayout, typ::StructType, offset::Integer)
Get the element at the given offset in a struct type for the target data layout.
See also: [`offsetof`](@ref).
"""
element_at(data::DataLayout, typ::StructType, offset::Integer) =
API.LLVMElementAtOffset(data, typ, Culonglong(offset))
element_at(dl::DataLayout, typ::StructType, offset::Integer) =
API.LLVMElementAtOffset(dl, typ, Culonglong(offset))

"""
offsetof(data::DataLayout, typ::StructType, element::Integer)
offsetof(dl::DataLayout, typ::StructType, element::Integer)
Get the offset of the given element in a struct type for the target data layout.
See also: [`element_at`](@ref).
"""
offsetof(data::DataLayout, typ::StructType, element::Integer) =
API.LLVMOffsetOfElement(data, typ, element)
offsetof(dl::DataLayout, typ::StructType, element::Integer) =
API.LLVMOffsetOfElement(dl, typ, element)
5 changes: 3 additions & 2 deletions src/irbuilder.jl
Original file line number Diff line number Diff line change
Expand Up @@ -523,14 +523,15 @@ not!(builder::IRBuilder, V::Value, Name::String="") =

# re-implementation for flexibility (exposing addrspace, add_null)
function globalstring!(mod::LLVM.Module, str::String, name::String="";
addrspace::Integer=0, add_null::Bool=true)
addrspace::Union{Integer,Nothing}=nothing, add_null::Bool=true)
bytes = Vector{UInt8}(str)
if add_null
push!(bytes, 0x00)
end
constant = ConstantDataArray(bytes)

gv = GlobalVariable(mod, value_type(constant), name, addrspace)
gv = GlobalVariable(mod, value_type(constant), name,
something(addrspace, globals_addrspace(datalayout(mod))))
alignment!(gv, 1)
unnamed_addr!(gv, true)
initializer!(gv, constant)
Expand Down
37 changes: 21 additions & 16 deletions test/datalayout_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,44 @@
dlstr = "E-p:32:32-f128:128:128"

let
data = DataLayout(dlstr)
dispose(data)
dl = DataLayout(dlstr)
dispose(dl)
end

DataLayout(dlstr) do data
DataLayout(dlstr) do dl
end

@dispose ctx=Context() data=DataLayout(dlstr) begin
@test string(data) == dlstr
@dispose ctx=Context() dl=DataLayout(dlstr) begin
@test string(dl) == dlstr

@test occursin(dlstr, sprint(io->show(io,data)))
@test occursin(dlstr, sprint(io->show(io,dl)))

@test byteorder(data) == LLVM.API.LLVMBigEndian
@test pointersize(data) == pointersize(data, 0) == 4
@test byteorder(dl) == LLVM.API.LLVMBigEndian
@test pointersize(dl) == pointersize(dl, 0) == 4

@test intptr(data) == intptr(data, 0) == LLVM.Int32Type()
@test intptr(dl) == intptr(dl, 0) == LLVM.Int32Type()

@test sizeof(data, LLVM.Int32Type()) == storage_size(data, LLVM.Int32Type()) == abi_size(data, LLVM.Int32Type()) == 4
@test sizeof(dl, LLVM.Int32Type()) == storage_size(dl, LLVM.Int32Type()) == abi_size(dl, LLVM.Int32Type()) == 4

@test abi_alignment(data, LLVM.Int32Type()) == frame_alignment(data, LLVM.Int32Type()) == preferred_alignment(data, LLVM.Int32Type()) == 4
@test abi_alignment(dl, LLVM.Int32Type()) == frame_alignment(dl, LLVM.Int32Type()) == preferred_alignment(dl, LLVM.Int32Type()) == 4

@dispose mod=LLVM.Module("SomeModule") begin
gv = GlobalVariable(mod, LLVM.Int32Type(), "SomeGlobal")
@test preferred_alignment(data, gv) == 4
@test preferred_alignment(dl, gv) == 4

datalayout!(mod, data)
@test string(datalayout(mod)) == string(data)
datalayout!(mod, dl)
@test string(datalayout(mod)) == string(dl)
end

elem = [LLVM.Int32Type(), LLVM.FloatType()]
let st = LLVM.StructType(elem)
@test element_at(data, st, 4) == 1
@test offsetof(data, st, 1) == 4
@test element_at(dl, st, 4) == 1
@test offsetof(dl, st, 1) == 4
end

@test globals_addrspace(dl) == 0
@dispose dl2=DataLayout(dlstr*"-G1") begin
@test globals_addrspace(dl2) == 1
end
end

Expand Down
Loading