diff --git a/include/kllvm/codegen/ApplyPasses.h b/include/kllvm/codegen/ApplyPasses.h index 247e225af..4d5a40b0e 100644 --- a/include/kllvm/codegen/ApplyPasses.h +++ b/include/kllvm/codegen/ApplyPasses.h @@ -6,10 +6,12 @@ namespace kllvm { -void do_bitcode_linking(llvm::Module &); +void do_bitcode_linking(llvm::Module &, char *, unsigned); void apply_kllvm_opt_passes(llvm::Module &, bool hidden_visibility); +void apply_inline_pass(llvm::Module &); + void generate_object_file(llvm::Module &, llvm::raw_ostream &); } // namespace kllvm diff --git a/include/kllvm/codegen/CreateTerm.h b/include/kllvm/codegen/CreateTerm.h index d28e66050..39f40162f 100644 --- a/include/kllvm/codegen/CreateTerm.h +++ b/include/kllvm/codegen/CreateTerm.h @@ -164,6 +164,8 @@ llvm::Value *allocate_term( llvm::Value *allocate_term( llvm::Type *alloc_type, llvm::BasicBlock *block, char const *alloc_fn = "kore_alloc", bool mergeable = false); +llvm::Value *addrspace_cast0_to0( + llvm::Module *module, llvm::Value *val, llvm::BasicBlock *block); } // namespace kllvm #endif // CREATE_TERM_H diff --git a/include/runtime/opaque_cpp.h b/include/runtime/opaque_cpp.h new file mode 100644 index 000000000..235502b57 --- /dev/null +++ b/include/runtime/opaque_cpp.h @@ -0,0 +1,13 @@ +#ifndef OPAQUE_CPP_H +#define OPAQUE_CPP_H + +/* This header file declares a string containing the textual bitcode of + * runtime/opaque/opaque.ll. The reason we use a separate IR file for the + * functions in opaque.ll is that the instructions they include confuse the + * RewriteStatepointsForGC pass. Therefore, we first perform all the regular + * optimization passes, then link, and then run the inline pass again. + */ +extern unsigned char opaque_ll[]; +extern unsigned int opaque_ll_len; + +#endif // define OPAQUE_CPP_H diff --git a/lib/codegen/ApplyPasses.cpp b/lib/codegen/ApplyPasses.cpp index 59e165e84..072e05af3 100644 --- a/lib/codegen/ApplyPasses.cpp +++ b/lib/codegen/ApplyPasses.cpp @@ -4,7 +4,6 @@ #include #include -#include "runtime/alloc_cpp.h" #include "runtime/header.h" #if LLVM_VERSION_MAJOR >= 17 @@ -16,6 +15,7 @@ #endif #include "llvm/IRReader/IRReader.h" +#include "llvm/Transforms/IPO/AlwaysInliner.h" #include #include #include @@ -114,6 +114,38 @@ void apply_kllvm_opt_passes(llvm::Module &mod, bool hidden_visibility) { mpm.run(mod, mam); } +void apply_inline_pass(llvm::Module &mod) { + // Create the analysis managers. + // These must be declared in this order so that they are destroyed in the + // correct order due to inter-analysis-manager references. + LoopAnalysisManager lam; + FunctionAnalysisManager fam; + CGSCCAnalysisManager cgam; + ModuleAnalysisManager mam; + + // Create the new pass manager builder. + // Take a look at the PassBuilder constructor parameters for more + // customization, e.g. specifying a TargetMachine or various debugging + // options. + PassBuilder pb; + + // Register all the basic analyses with the managers. + pb.registerModuleAnalyses(mam); + pb.registerCGSCCAnalyses(cgam); + pb.registerFunctionAnalyses(fam); + pb.registerLoopAnalyses(lam); + pb.crossRegisterProxies(lam, fam, cgam, mam); + + // Create the pass manager. + ModulePassManager mpm; + + // Add always inline pass + mpm.addPass(AlwaysInlinerPass()); + + // Run always inline pass + mpm.run(mod, mam); +} + void generate_object_file(llvm::Module &mod, llvm::raw_ostream &os) { if (keep_frame_pointer) { mod.setFramePointer(FramePointerKind::All); @@ -167,14 +199,13 @@ void generate_object_file(llvm::Module &mod, llvm::raw_ostream &os) { * is done currently with only a single file: runtime/lto/alloc.cpp. We do this * so that inlining can occur across the functions in each file. */ -void do_bitcode_linking(llvm::Module &mod) { +void do_bitcode_linking(llvm::Module &mod, char *bc, unsigned bc_len) { Linker linker(mod); llvm::SMDiagnostic err; - auto alloc_cpp_mod = llvm::parseIR( - *llvm::MemoryBuffer::getMemBuffer( - std::string((char *)alloc_cpp_o_ll, alloc_cpp_o_ll_len)), - err, mod.getContext()); - bool error = linker.linkInModule(std::move(alloc_cpp_mod)); + auto cpp_mod = llvm::parseIR( + *llvm::MemoryBuffer::getMemBuffer(std::string(bc, bc_len)), err, + mod.getContext()); + bool error = linker.linkInModule(std::move(cpp_mod)); if (error) { throw std::runtime_error( "Bitcode linking failed. Please report this as a bug."); diff --git a/lib/codegen/CMakeLists.txt b/lib/codegen/CMakeLists.txt index 98392b4a0..c1e8d3c70 100644 --- a/lib/codegen/CMakeLists.txt +++ b/lib/codegen/CMakeLists.txt @@ -13,5 +13,5 @@ add_library(Codegen ) target_link_libraries(Codegen - PUBLIC AST fmt::fmt-header-only alloc-cpp + PUBLIC AST fmt::fmt-header-only alloc-cpp opaque-cpp PRIVATE base64) diff --git a/lib/codegen/CreateTerm.cpp b/lib/codegen/CreateTerm.cpp index 8141d9256..37b066542 100644 --- a/lib/codegen/CreateTerm.cpp +++ b/lib/codegen/CreateTerm.cpp @@ -64,7 +64,8 @@ llvm::Type *get_param_type(value_type sort, llvm::Module *module) { case sort_category::RangeMap: case sort_category::List: case sort_category::Set: - type = llvm::PointerType::getUnqual(module->getContext()); + type = use_gcstrategy ? llvm::PointerType::get(module->getContext(), 0) + : llvm::PointerType::getUnqual(module->getContext()); break; default: break; } @@ -94,6 +95,9 @@ llvm::Type *getvalue_type(value_type sort, llvm::Module *module) { case sort_category::StringBuffer: case sort_category::Symbol: case sort_category::Variable: + if (use_gcstrategy) { + return llvm::PointerType::get(module->getContext(), 0); + } return llvm::PointerType::getUnqual(module->getContext()); case sort_category::MapIter: case sort_category::SetIter: @@ -169,6 +173,24 @@ llvm::Value *get_block_header( llvm::Type::getInt64Ty(module->getContext()), header_val)); } +static llvm::Value *addrspace_cast( + llvm::Module *module, llvm::Value *val, llvm::BasicBlock *block, int from, + int to) { + std::string name + = "addrspace_" + std::to_string(from) + "_to_" + std::to_string(to); + auto *addrspace = llvm::CallInst::Create( + get_or_insert_function( + module, name, llvm::PointerType::get(module->getContext(), to), + llvm::PointerType::get(module->getContext(), from)), + {val}, "", block); + return addrspace; +} + +llvm::Value *addrspace_cast0_to0( + llvm::Module *module, llvm::Value *val, llvm::BasicBlock *block) { + return addrspace_cast(module, val, block, 0, 0); +} + template requires std::same_as || std::same_as @@ -910,12 +932,17 @@ llvm::Value *create_term::create_function_call( alloc_sret = allocate_term( return_type, current_block_, get_collection_alloc_fn(return_cat.cat), true); + auto *alloc_sret_cast + = use_gcstrategy + ? addrspace_cast0_to0(module_, alloc_sret, current_block_) + : alloc_sret; sret_type = return_type; - real_args.insert(real_args.begin(), alloc_sret); - types.insert(types.begin(), alloc_sret->getType()); + real_args.insert(real_args.begin(), alloc_sret_cast); + types.insert(types.begin(), alloc_sret_cast->getType()); return_type = llvm::Type::getVoidTy(ctx_); } else if (collection) { - return_type = llvm::PointerType::getUnqual(ctx_); + return_type = use_gcstrategy ? llvm::PointerType::get(ctx_, 0) + : llvm::PointerType::getUnqual(ctx_); } llvm::FunctionType *func_type @@ -1003,15 +1030,20 @@ llvm::Value *create_term::not_injection_case( new llvm::StoreInst(child_value, child_ptr, current_block_); } - auto *block_ptr = llvm::PointerType::getUnqual(module_->getContext()); + auto *block_ptr = use_gcstrategy + ? llvm::PointerType::get(module_->getContext(), 0) + : llvm::PointerType::getUnqual(module_->getContext()); + auto *block_cast = use_gcstrategy + ? addrspace_cast0_to0(module_, block, current_block_) + : block; if (symbol_decl->attributes().contains(attribute_set::key::Binder)) { auto *call = llvm::CallInst::Create( get_or_insert_function(module_, "debruijnize", block_ptr, block_ptr), - block, "withIndices", current_block_); + block_cast, "withIndices", current_block_); set_debug_loc(call); return call; } - return block; + return block_cast; } // returns a value and a boolean indicating whether that value could be an @@ -1190,7 +1222,9 @@ bool make_function( std::vector param_types; std::vector param_names; std::vector debug_args; - auto *ptr_ty = llvm::PointerType::getUnqual(module->getContext()); + auto *ptr_ty = use_gcstrategy + ? llvm::PointerType::get(module->getContext(), 0) + : llvm::PointerType::getUnqual(module->getContext()); for (auto &entry : vars) { auto *sort = dynamic_cast(entry.second->get_sort().get()); @@ -1359,7 +1393,9 @@ std::string make_apply_rule_function( case sort_category::RangeMap: case sort_category::List: case sort_category::Set: - param_type = llvm::PointerType::getUnqual(module->getContext()); + param_type = use_gcstrategy + ? llvm::PointerType::get(module->getContext(), 0) + : llvm::PointerType::getUnqual(module->getContext()); break; default: break; } @@ -1415,8 +1451,11 @@ std::string make_apply_rule_function( auto *ptr = allocate_term( arg->getType(), creator.get_current_block(), get_collection_alloc_fn(cat.cat), true); - new llvm::StoreInst(arg, ptr, creator.get_current_block()); - arg = ptr; + auto *ptr_cast = use_gcstrategy ? addrspace_cast0_to0( + module, ptr, creator.get_current_block()) + : ptr; + new llvm::StoreInst(arg, ptr_cast, creator.get_current_block()); + arg = ptr_cast; } break; default: break; diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index d89eb3815..b2c4f2a2f 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -2,7 +2,10 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/main) -configure_file(main/main.ll ${CMAKE_CURRENT_BINARY_DIR}/main @ONLY) +configure_file(main/main.ll ${CMAKE_CURRENT_BINARY_DIR}/main @ONLY) + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/opaque) +configure_file(opaque/opaque.ll ${CMAKE_CURRENT_BINARY_DIR}/opaque @ONLY) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/main/main.ll main/search.cpp @@ -17,6 +20,7 @@ add_subdirectory(io) add_subdirectory(json) add_subdirectory(lto) add_subdirectory(meta) +add_subdirectory(opaque) add_subdirectory(strings) add_subdirectory(util) add_subdirectory(timer) diff --git a/runtime/opaque/CMakeLists.txt b/runtime/opaque/CMakeLists.txt new file mode 100644 index 000000000..2fa3e6c2d --- /dev/null +++ b/runtime/opaque/CMakeLists.txt @@ -0,0 +1,11 @@ +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/runtime/opaque/opaque_cpp.cpp + COMMAND xxd -i opaque.ll opaque_cpp.cpp + DEPENDS opaque.ll + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/runtime/opaque +) + +add_library(opaque-cpp STATIC + ${CMAKE_BINARY_DIR}/runtime/opaque/opaque_cpp.cpp +) + +set_target_properties(opaque-cpp PROPERTIES EXPORT_COMPILE_COMMANDS Off) diff --git a/runtime/opaque/opaque.ll b/runtime/opaque/opaque.ll new file mode 100644 index 000000000..f1b5b8748 --- /dev/null +++ b/runtime/opaque/opaque.ll @@ -0,0 +1,10 @@ +target datalayout = "@BACKEND_TARGET_DATALAYOUT@" +target triple = "@BACKEND_TARGET_TRIPLE@" + +define ptr addrspace(0) @addrspace_0_to_0(ptr %in) #0 { + ; %out = addrspacecast ptr %in to ptr addrspace(0) + ; ret ptr addrspace(0) %out + ret ptr addrspace(0) %in +} + +attributes #0 = { alwaysinline } diff --git a/test/defn/imp.kore b/test/defn/imp.kore index bccd8575e..4ac67067f 100644 --- a/test/defn/imp.kore +++ b/test/defn/imp.kore @@ -1,8 +1,6 @@ // RUN: %interpreter // RUN: %check-grep // RUN: %check-statistics -// RUN: %gcs-interpreter -// RUN: %check-grep // RUN: %proof-interpreter // RUN: %check-proof-out [topCellInitializer{}(LblinitGeneratedTopCell{}()), org'Stop'kframework'Stop'attributes'Stop'Source{}("Source(/home/robertorosmaninho/rv/k/llvm-backend/src/main/native/llvm-backend/test/defn/k-files/imp.md)")] diff --git a/tools/llvm-kompile-codegen/main.cpp b/tools/llvm-kompile-codegen/main.cpp index f98f7a9c9..75c2e54dd 100644 --- a/tools/llvm-kompile-codegen/main.cpp +++ b/tools/llvm-kompile-codegen/main.cpp @@ -11,6 +11,9 @@ #include #include +#include "runtime/alloc_cpp.h" +#include "runtime/opaque_cpp.h" + #include #include #include @@ -239,12 +242,16 @@ int main(int argc, char **argv) { finalize_debug_info(); } - do_bitcode_linking(*mod); + do_bitcode_linking(*mod, (char *)alloc_cpp_o_ll, alloc_cpp_o_ll_len); if (!no_optimize) { apply_kllvm_opt_passes(*mod, hidden_visibility); } + do_bitcode_linking(*mod, (char *)opaque_ll, opaque_ll_len); + + apply_inline_pass(*mod); + perform_output([&](auto &os) { if (emit_object) { generate_object_file(*mod, os);