@@ -817,7 +817,16 @@ class Savi::Compiler::CodeGen
817817
818818 def gen_func_impl (gtype, gfunc, llvm_func)
819819 return gen_intrinsic(gtype, gfunc, llvm_func) if gfunc.func.has_tag?(:compiler_intrinsic )
820- return gen_ffi_impl(gtype, gfunc, llvm_func) if gfunc.func.has_tag?(:ffi )
820+
821+ if gfunc.func.has_tag?(:ffi )
822+ if gfunc.func.has_tag?(:ffi_global_getter )
823+ return gen_ffi_global_getter_impl(gtype, gfunc, llvm_func)
824+ elsif gfunc.func.has_tag?(:ffi_global_setter )
825+ return gen_ffi_global_setter_impl(gtype, gfunc, llvm_func)
826+ else
827+ return gen_ffi_impl(gtype, gfunc, llvm_func)
828+ end
829+ end
821830
822831 # Fields with no initializer body can be skipped.
823832 return if gfunc.func.has_tag?(:field ) && gfunc.func.body.nil?
@@ -902,8 +911,6 @@ class Savi::Compiler::CodeGen
902911 end
903912
904913 def gen_ffi_impl (gtype, gfunc, llvm_func)
905- llvm_ffi_func = gen_ffi_decl(gfunc)
906-
907914 gen_func_start(llvm_func, gtype, gfunc)
908915
909916 param_count = llvm_func.params.size
@@ -957,12 +964,42 @@ class Savi::Compiler::CodeGen
957964 else
958965 raise NotImplementedError .new(gfunc.calling_convention)
959966 end
967+ end
960968
961- # And possibly cast the return type, for the same reasons
962- # that we possibly cast the argument types earlier above.
963- ret_type = llvm_type_of(gfunc.func.ret.not_nil!, gfunc)
969+ def gen_ffi_global_decl (gfunc )
970+ llvm_type = llvm_type_of(gfunc.func.ret.not_nil!, gfunc)
964971
965- value
972+ global = @mod .globals.add(llvm_type, gfunc.func.metadata[:ffi_link_name ].as(String ))
973+ global.linkage = LLVM ::Linkage ::External
974+ global.global_constant = gfunc.func.has_tag?(:ffi_global_constant )
975+ global.externally_initialized = true # TODO: false and set an initializer if this ffi var has an initializer
976+ global
977+ end
978+
979+ def gen_ffi_global_getter_impl (gtype, gfunc, llvm_func)
980+ gen_func_start(llvm_func, gtype, gfunc)
981+
982+ global = gen_ffi_global_decl(gfunc)
983+ llvm_type = llvm_type_of(gfunc.func.ret.not_nil!, gfunc)
984+
985+ value = @builder .load(llvm_type, global, " #{ global.name } .LOAD" )
986+
987+ @builder .ret(value)
988+
989+ gen_func_end(gfunc)
990+ end
991+
992+ def gen_ffi_global_setter_impl (gtype, gfunc, llvm_func)
993+ gen_func_start(llvm_func, gtype, gfunc)
994+
995+ global = @mod .globals[gfunc.func.metadata[:ffi_link_name ]]
996+
997+ value = llvm_func.params[0 ]
998+ @builder .store(value, global)
999+
1000+ @builder .ret(value)
1001+
1002+ gen_func_end(gfunc)
9661003 end
9671004
9681005 def gen_intrinsic_cpointer (gtype, gfunc, llvm_func)
@@ -1851,14 +1888,14 @@ class Savi::Compiler::CodeGen
18511888 args,
18521889 arg_exprs,
18531890 arg_frames,
1854- gfunc.func.has_tag?(:ffi ) ? gfunc : nil ,
1891+ gfunc.func.has_tag?(:ffi_call ) ? gfunc : nil ,
18551892 needs_virtual_call,
18561893 use_receiver,
18571894 ! cont.nil?,
18581895 )
18591896
18601897 # If this was an FFI call, skip calling-convention-specific handling.
1861- return result if gfunc.func.has_tag?(:ffi )
1898+ return result if gfunc.func.has_tag?(:ffi_call )
18621899
18631900 case gfunc.calling_convention
18641901 when GenFunc ::Simple
@@ -3201,7 +3238,6 @@ class Savi::Compiler::CodeGen
32013238 global.linkage = LLVM ::Linkage ::Private
32023239 global.initializer = const
32033240 global.global_constant = true
3204- global.unnamed_addr = true
32053241 global
32063242 end
32073243
0 commit comments