Skip to content
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

Add and test cosmopolitan executables #91

Closed
wants to merge 2 commits into from
Closed
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
16 changes: 16 additions & 0 deletions Artifacts.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[cosmopolitan]
git-tree-sha1 = "ff58fd6cb9c94ea11b67c78841af5018902214c9"
lazy = true

[[cosmopolitan.download]]
url = "https://github.com/brenhinkeller/cosmopolitan-artifact-mirror/raw/main/archives/cosmopolitan-amalgamation-2.1.1.tar.gz"
sha256 = "efd09628404ab7bb70605796d66703ba16eb0271263ed0b77fc19c18ed5fee10"


[cosmopolitan-tiny]
git-tree-sha1 = "9032c427d4221119ebc562f6299540f2113a3f44"
lazy = true

[[cosmopolitan-tiny.download]]
url = "https://github.com/brenhinkeller/cosmopolitan-artifact-mirror/raw/main/archives/cosmopolitan-amalgamation-tiny-2.1.1.tar.gz"
sha256 = "d91db150a5d9ceb54bcb21e968b33ed27b77778f23980d267734a2bb3813dc76"
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ version = "0.4.6"
Clang_jll = "0ee61d77-7f21-5576-8119-9fcc46b10100"
GPUCompiler = "61eb1bfa-7361-4325-ad38-22787b887f55"
LLVM = "929cbde3-209d-540e-8aea-75f648917ca0"
LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

Expand Down
73 changes: 73 additions & 0 deletions src/StaticCompiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ using Libdl: Libdl, dlsym, dlopen
using Base: RefValue
using Serialization: serialize, deserialize
using Clang_jll: clang
using LazyArtifacts

export compile, load_function, compile_shlib, compile_executable
export native_code_llvm, native_code_typed, native_llvm_module, native_code_native
Expand Down Expand Up @@ -555,5 +556,77 @@ function compile_shlib(funcs::Array, path::String="./";
joinpath(abspath(path), filename * "." * Libdl.dlext)
end

# Cosmopolitan executables
"""
```julia
compile_cosmopolitan(f, types::Tuple, path::String, name::String=repr(f);
filename = name,
objcopy = `objcopy`,
gcc = `gcc`,
cflags = ``,
kwargs...
)
```
As `compile_executable`, but generating a [cosmopolitan executable](https://justine.lol/cosmopolitan/index.html).
"""
function compile_cosmopolitan(f, types=(), path::String="./", name=GPUCompiler.safe_name(repr(f));
filename=name,
objcopy = `objcopy`,
gcc = `gcc`,
cflags = ``,
kwargs...
)
tt = Base.to_tuple_type(types)
rt = only(native_code_typed(f, tt))[2]
isconcretetype(rt) || error("$f$types did not infer to a concrete type. Got $rt")
generate_cosmopolitan(f, tt, path, name, filename; objcopy, gcc, cflags, kwargs...)
joinpath(abspath(path), filename)
end

function generate_cosmopolitan(f, tt, path=tempname(), name=GPUCompiler.safe_name(repr(f)), filename=string(name);
objcopy = `objcopy`,
gcc = `gcc`,
cflags = ``,
kwargs...
)
mkpath(path)
obj_path = joinpath(path, "$filename.o")
exec_path = joinpath(path, filename)
job, kwargs = native_job(f, tt; name, kwargs...)
obj, _ = GPUCompiler.codegen(:obj, job; strip=true, only_entry=false, validate=false)

# Write to file
open(obj_path, "w") do io
write(io, obj)
end

# Write a minimal wrapper to avoid having to specify a custom entry
wrapper_path = joinpath(path, "wrapper.c")
f = open(wrapper_path, "w")
print(f, """int julia_$name(int argc, char** argv);
void* __stack_chk_guard = (void*) $(rand(UInt) >> 1);

int main(int argc, char** argv)
{
julia_$name(argc, argv);
return 0;
}""")
close(f)

# Compile
run(`$gcc $cflags -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \
-fno-omit-frame-pointer -pg -mnop-mcount -mno-tls-direct-seg-refs -gdwarf-4 \
$wrapper_path -o $(exec_path*".dbg") -fuse-ld=bfd -Wl,-T,$(archive"cosmopolitan/ape.lds") -Wl,--gc-sections \
-include $(archive"cosmopolitan/cosmopolitan.h") $obj_path $(archive"cosmopolitan/crt.o") \
$(archive"cosmopolitan/ape-no-modify-self.o") $(archive"cosmopolitan/cosmopolitan.a")`)

run(`$objcopy -S -O binary $(exec_path*".dbg") $exec_path`)

# Clean up intermediate files
run(`rm $exec_path*".dbg"`)
run(`rm $wrapper_path`)

path, name
end

end # module
16 changes: 16 additions & 0 deletions test/cosmopolitan_scripts/interop.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using StaticCompiler
using StaticTools

function interop(argc, argv)
lib = StaticTools.dlopen(c"libm")
printf(lib)
sin = StaticTools.dlsym(lib, c"sin")
printf(sin)
x = @ptrcall sin(5.0::Float64)::Float64
printf(x)
newline()
StaticTools.dlclose(lib)
end

# Attempt to compile
path = compile_cosmopolitan(interop, (Int64, Ptr{Ptr{UInt8}}), "./", cflags=`-ldl -lm`)
53 changes: 53 additions & 0 deletions test/cosmopolitan_scripts/loopvec_matrix.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using StaticCompiler
using StaticTools
using LoopVectorization

@inline function mul!(C::MallocArray, A::MallocArray, B::MallocArray)
@turbo for n ∈ indices((C,B), 2), m ∈ indices((C,A), 1)
Cmn = zero(eltype(C))
for k ∈ indices((A,B), (2,1))
Cmn += A[m,k] * B[k,n]
end
C[m,n] = Cmn
end
return C
end

function loopvec_matrix(argc::Int, argv::Ptr{Ptr{UInt8}})
argc == 3 || return printf(stderrp(), c"Incorrect number of command-line arguments\n")
rows = argparse(Int64, argv, 2) # First command-line argument
cols = argparse(Int64, argv, 3) # Second command-line argument

# LHS
A = MallocArray{Float64}(undef, rows, cols)
@turbo for i ∈ axes(A, 1)
for j ∈ axes(A, 2)
A[i,j] = i*j
end
end

# RHS
B = MallocArray{Float64}(undef, cols, rows)
@turbo for i ∈ axes(B, 1)
for j ∈ axes(B, 2)
B[i,j] = i*j
end
end

# # Matrix multiplication
C = MallocArray{Float64}(undef, cols, cols)
mul!(C, B, A)

# Print to stdout
printf(C)
# Also print to file
printdlm(c"table.tsv", C, '\t')
fwrite(c"table.b", C)
# Clean up matrices
free(A)
free(B)
free(C)
end

# Attempt to compile
path = compile_cosmopolitan(loopvec_matrix, (Int64, Ptr{Ptr{UInt8}}), "./")
49 changes: 49 additions & 0 deletions test/cosmopolitan_scripts/loopvec_matrix_stack.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using StaticCompiler
using StaticTools
using LoopVectorization

@inline function mul!(C::StackArray, A::StackArray, B::StackArray)
@turbo for n ∈ indices((C,B), 2), m ∈ indices((C,A), 1)
Cmn = zero(eltype(C))
for k ∈ indices((A,B), (2,1))
Cmn += A[m,k] * B[k,n]
end
C[m,n] = Cmn
end
return C
end

function loopvec_matrix_stack()
rows = 10
cols = 5

# LHS
A = StackArray{Float64}(undef, rows, cols)
@turbo for i ∈ axes(A, 1)
for j ∈ axes(A, 2)
A[i,j] = i*j
end
end

# RHS
B = StackArray{Float64}(undef, cols, rows)
@turbo for i ∈ axes(B, 1)
for j ∈ axes(B, 2)
B[i,j] = i*j
end
end

# # Matrix multiplication
C = StackArray{Float64}(undef, cols, cols)
mul!(C, B, A)

# Print to stdout
printf(C)
# Also print to file
fp = fopen(c"table.tsv",c"w")
printf(fp, C)
fclose(fp)
end

# Attempt to compile
path = compile_cosmopolitan(loopvec_matrix_stack, (), "./")
25 changes: 25 additions & 0 deletions test/cosmopolitan_scripts/loopvec_product.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using StaticCompiler
using StaticTools
using LoopVectorization

function loopvec_product(argc::Int, argv::Ptr{Ptr{UInt8}})
argc == 3 || return printf(stderrp(), c"Incorrect number of command-line arguments\n")
rows = argparse(Int64, argv, 2) # First command-line argument
cols = argparse(Int64, argv, 3) # Second command-line argument

s = 0
@turbo for i=1:rows
for j=1:cols
s += i*j
end
end
# Print result to stdout
printf(s)
# Also print to file
fp = fopen(c"product.tsv",c"w")
printf(fp, s)
fclose(fp)
end

# Attempt to compile
path = compile_cosmopolitan(loopvec_product, (Int64, Ptr{Ptr{UInt8}}), "./")
33 changes: 33 additions & 0 deletions test/cosmopolitan_scripts/print_args.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using StaticCompiler
using StaticTools

function print_args(argc::Int, argv::Ptr{Ptr{UInt8}})
printf(c"Argument count is %d:\n", argc)
for i=1:argc
# iᵗʰ input argument string
pᵢ = unsafe_load(argv, i) # Get pointer
strᵢ = MallocString(pᵢ) # Can wrap to get high-level interface
println(strᵢ)
# No need to `free` since we didn't allocate this memory
end
newline()
println(c"Testing string indexing and substitution")
m = m"Hello world!"
println(m[1:5])
println(m)
m[7:11] = c"there"
println(m)
free(m)

s = m"Hello world!"
println(s[1:5])
println(s)
s[7:11] = c"there"
println(s)

println(c"That was fun, see you next time!")
return 0
end

# Attempt to compile
path = compile_cosmopolitan(print_args, (Int64, Ptr{Ptr{UInt8}}), "./")
23 changes: 23 additions & 0 deletions test/cosmopolitan_scripts/rand_matrix.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using StaticCompiler
using StaticTools

function rand_matrix(argc::Int, argv::Ptr{Ptr{UInt8}})
argc == 3 || return printf(stderrp(), c"Incorrect number of command-line arguments\n")
rows = argparse(Int64, argv, 2) # First command-line argument
cols = argparse(Int64, argv, 3) # Second command-line argument

# Manually fil matrix
M = MallocArray{Float64}(undef, rows, cols)
rng = static_rng()
@inbounds for i=1:rows
for j=1:cols
M[i,j] = rand(rng)
end
end
printf(M)
free(M)
end

# Attempt to compile
# cflags=`-lm`: need to explicitly include libm math library on linux
path = compile_cosmopolitan(rand_matrix, (Int64, Ptr{Ptr{UInt8}}), "./", cflags=`-lm`)
22 changes: 22 additions & 0 deletions test/cosmopolitan_scripts/randn_matrix.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using StaticCompiler
using StaticTools

function randn_matrix(argc::Int, argv::Ptr{Ptr{UInt8}})
argc == 3 || return printf(stderrp(), c"Incorrect number of command-line arguments\n")
rows = argparse(Int64, argv, 2) # First command-line argument
cols = argparse(Int64, argv, 3) # Second command-line argument

M = MallocArray{Float64}(undef, rows, cols)
rng = MarsagliaPolar(static_rng())
@inbounds for i=1:rows
for j=1:cols
M[i,j] = randn(rng)
end
end
printf(M)
free(M)
end

# Attempt to compile
# cflags=`-lm`: need to explicitly include libm math library on linux
path = compile_cosmopolitan(randn_matrix, (Int64, Ptr{Ptr{UInt8}}), "./", cflags=`-lm`)
25 changes: 25 additions & 0 deletions test/cosmopolitan_scripts/times_table.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using StaticCompiler
using StaticTools

function times_table(argc::Int, argv::Ptr{Ptr{UInt8}})
argc == 3 || return printf(stderrp(), c"Incorrect number of command-line arguments\n")
rows = argparse(Int64, argv, 2) # First command-line argument
cols = argparse(Int64, argv, 3) # Second command-line argument

M = MallocArray{Int64}(undef, rows, cols)
@inbounds for i=1:rows
for j=1:cols
M[i,j] = i*j
end
end
# Print to stdout
printf(M)
# Also print to file
fwrite(c"table.b", M)
printdlm(c"table.tsv", M)
# Clean up matrix
free(M)
end

# Attempt to compile
path = compile_cosmopolitan(times_table, (Int64, Ptr{Ptr{UInt8}}), "./")
31 changes: 31 additions & 0 deletions test/cosmopolitan_scripts/withmallocarray.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using StaticCompiler
using StaticTools

function withmallocarray(argc::Int, argv::Ptr{Ptr{UInt8}})
argc == 3 || return printf(stderrp(), c"Incorrect number of command-line arguments\n")
rows = argparse(Int64, argv, 2) # First command-line argument
cols = argparse(Int64, argv, 3) # Second command-line argument

mzeros(rows, cols) do A
printf(A)
end
mones(Int, rows, cols) do A
printf(A)
end
mfill(3.141592, rows, cols) do A
printf(A)
end

# Random number generation
rng = MarsagliaPolar()
mrand(rng, rows, cols) do A
printf(A)
end
mrandn(rng, rows, cols) do A
printf(A)
end
end

# Attempt to compile
# cflags=`-lm`: need to explicitly include libm math library on linux
path = compile_cosmopolitan(withmallocarray, (Int64, Ptr{Ptr{UInt8}}), "./", cflags=`-lm`)
Loading