@@ -434,7 +434,6 @@ function generate_shlib(f, tt, path::String = tempname(), name = GPUCompiler.saf
434434 path, name
435435end
436436
437-
438437function native_code_llvm (@nospecialize (func), @nospecialize (types); kwargs... )
439438 job, kwargs = native_job (func, types; kwargs... )
440439 GPUCompiler. code_llvm (stdout , job; kwargs... )
@@ -457,9 +456,77 @@ function native_code_native(@nospecialize(f), @nospecialize(tt), name = GPUCompi
457456 GPUCompiler. code_native (stdout , job; kwargs... )
458457end
459458
459+ # Return an LLVM module for multiple functions
460+ function native_llvm_module (funcs:: Array ; mangle_names = false , kwargs... )
461+ f,tt = funcs[1 ]
462+ mod = native_llvm_module (f,tt, kwargs... )
463+ if length (funcs) > 1
464+ for func in funcs[2 : end ]
465+ @show f,tt = func
466+ tmod = native_llvm_module (f,tt, kwargs... )
467+ link! (mod,tmod)
468+ end
469+ end
470+ if mangle_names
471+ for func in functions (mod)
472+ fname = name (func)
473+ name! (func,fname[7 : end ])
474+ end
475+ end
476+ return mod
477+ end
460478
479+ function generate_obj (funcs:: Array , path:: String = tempname (), filenamebase:: String = " obj" ,
480+ mangle_names = false ;
481+ strip_llvm = false ,
482+ strip_asm = true ,
483+ opt_level= 3 ,
484+ kwargs... )
485+ f,tt = funcs[1 ]
486+ mkpath (path)
487+ obj_path = joinpath (path, " $filenamebase .o" )
488+ fakejob, kwargs = native_job (f,tt, kwargs... )
489+ mod = native_llvm_module (funcs, kwargs... )
490+ obj, _ = GPUCompiler. emit_asm (fakejob, mod; strip= strip_asm, validate= false , format= LLVM. API. LLVMObjectFile)
491+ open (obj_path, " w" ) do io
492+ write (io, obj)
493+ end
494+ path, obj_path
495+ end
461496
497+ function generate_shlib (funcs:: Array , path:: String = tempname (), filename:: String = " libfoo" , mangle_names= false ; kwargs... )
498+
499+ lib_path = joinpath (path, " $filename .$(Libdl. dlext) " )
462500
501+ _,obj_path = generate_obj (funcs, path, kwargs... )
502+ # Pick a Clang
503+ cc = Sys. isapple () ? ` cc` : clang ()
504+ # Compile!
505+ run (` $cc -shared -o $lib_path $obj_path ` )
506+
507+ path, name
508+ end
509+
510+ function compile_shlib (funcs:: Array , path:: String = " ./" ;
511+ filename= " libfoo" ,
512+ mangle_names= false ,
513+ kwargs... )
514+ for func in funcs
515+ f, types = func
516+ tt = Base. to_tuple_type (types)
517+ isconcretetype (tt) || error (" input type signature $types is not concrete" )
518+
519+ rt = only (native_code_typed (f, tt))[2 ]
520+ isconcretetype (rt) || error (" $f$types did not infer to a concrete type. Got $rt " )
521+ end
522+
523+ # Would be nice to use a compiler pass or something to check if there are any heap allocations or references to globals
524+ # Keep an eye on https://github.com/JuliaLang/julia/pull/43747 for this
525+
526+ generate_shlib (funcs, path, filename, mangle_names, kwargs... )
527+
528+ joinpath (abspath (path), filename * " ." * Libdl. dlext)
529+ end
463530
464531
465532end # module
0 commit comments