diff --git a/include/xo/jit/type2llvm.hpp b/include/xo/jit/type2llvm.hpp index dffe155b..75f33576 100644 --- a/include/xo/jit/type2llvm.hpp +++ b/include/xo/jit/type2llvm.hpp @@ -41,6 +41,28 @@ namespace xo { TypeDescr fn_td, bool wrapper_flag = false); + /** establish llvm concrete representation for a closure. + * + * +-------+ + * [0] | o-------> fnptr T (*)(envptr, ...) + * +-------+ + * [1] | o-------\ + * +-------+ | + * | + * | + * v + * +-------+ + * parent_env [0] | o-------> _env_api* + * +-------+ + * unwind_fn [1] | o-------> env * (*)(env*, ctl) + * +-------+ + * + * @return struct type. typename will be @c c.foo for lambda with name @c foo + **/ + static llvm::StructType * + create_closure_lvtype(xo::ref::brw llvm_cx, + xo::ref::brw lambda); + /** establish llvm concrete representation for a particular lambda's * runtime local environment: * @@ -62,6 +84,8 @@ namespace xo { * * arg[] comprises the subset of lambda arg names arg[j] for which * lambda->is_captured(arg[j]) is true + * + * @return struct type. typename will be @c e.foo for lambda with name @c foo **/ static llvm::StructType * create_localenv_llvm_type(xo::ref::brw llvm_cx, diff --git a/src/jit/type2llvm.cpp b/src/jit/type2llvm.cpp index fdfda7d5..a5405f86 100644 --- a/src/jit/type2llvm.cpp +++ b/src/jit/type2llvm.cpp @@ -303,6 +303,36 @@ namespace xo { return localenv_llvm_type; } /*create_localenv_llvm_type*/ + llvm::StructType * + type2llvm::create_closure_lvtype(xo::ref::brw llvm_cx, + xo::ref::brw lambda) + { + constexpr const char * c_prefix = "c."; + + /* would be precisely correct to use create_localenv_llvm_type() + * here. However judged not sufficiently helpful. + * Would still + * need environment cast whenever closure in apply position is + * not known at compile time. + */ + llvm::PointerType * fn_lvtype = function_td_to_llvm_fnptr_type(llvm_cx, + lambda->valuetype()); + llvm::StructType * env_lvtype = env_api_llvm_type(llvm_cx); + + std::vector member_lvtype_v = { fn_lvtype, env_lvtype }; + + /* e.g. "c.foo" */ + std::string closure_name = std::string(c_prefix) + lambda->name(); + + llvm::StructType * closure_lvtype + = llvm::StructType::create(llvm_cx->llvm_cx_ref(), + member_lvtype_v, + llvm::StringRef(closure_name), + false /*!is_packed*/); + + return closure_lvtype; + } /*create_closure_lvtype*/ + } /*namespace jit*/ } /*namespace xo*/