Skip to content

Commit

Permalink
WIP: Gc addressspace 0 (#1193)
Browse files Browse the repository at this point in the history
This PR adds
- the explicit use/casting to address space 0 in CreateTerm.cpp.
- the infrastructure to define the functions that contain the
`addrspacecast` instructions for the various address spaces (a separate
file, linked after the regular passes, and the always inline pass
executed afterwards).

Current status: The tests work as expected when the conditional
compilation flag `use_gcstrategy` that enables the use of the LLVM
backend strategy is disabled.

Enabling the flag, e.g. by adding the tests
```
// RUN: %gcs-interpreter
// RUN: %check-grep
```
in defn/imp.kore, results in the test failing (that interpreter fails
with segfault).

This is WIP, and is merged in order to keep the code up to date until we
revisit this, to
- address the segfault
- replace address space 0 with the actual address space needed in each
place
- similarly edit the other files
  • Loading branch information
mariaKt authored Jan 17, 2025
1 parent af29ee5 commit c2e8094
Show file tree
Hide file tree
Showing 11 changed files with 141 additions and 24 deletions.
4 changes: 3 additions & 1 deletion include/kllvm/codegen/ApplyPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions include/kllvm/codegen/CreateTerm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
13 changes: 13 additions & 0 deletions include/runtime/opaque_cpp.h
Original file line number Diff line number Diff line change
@@ -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
45 changes: 38 additions & 7 deletions lib/codegen/ApplyPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <kllvm/codegen/RemoveDeadKFunctions.h>
#include <kllvm/codegen/SetVisibilityHidden.h>

#include "runtime/alloc_cpp.h"
#include "runtime/header.h"

#if LLVM_VERSION_MAJOR >= 17
Expand All @@ -16,6 +15,7 @@
#endif

#include "llvm/IRReader/IRReader.h"
#include "llvm/Transforms/IPO/AlwaysInliner.h"
#include <llvm/Bitcode/BitcodeReader.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/Linker/Linker.h>
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.");
Expand Down
2 changes: 1 addition & 1 deletion lib/codegen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
61 changes: 50 additions & 11 deletions lib/codegen/CreateTerm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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 <typename T>
requires std::same_as<T, llvm::BasicBlock>
|| std::same_as<T, llvm::Instruction>
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1190,7 +1222,9 @@ bool make_function(
std::vector<llvm::Type *> param_types;
std::vector<std::string> param_names;
std::vector<llvm::Metadata *> 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<kore_composite_sort *>(entry.second->get_sort().get());
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 5 additions & 1 deletion runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
11 changes: 11 additions & 0 deletions runtime/opaque/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
10 changes: 10 additions & 0 deletions runtime/opaque/opaque.ll
Original file line number Diff line number Diff line change
@@ -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 }
2 changes: 0 additions & 2 deletions test/defn/imp.kore
Original file line number Diff line number Diff line change
@@ -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)")]
Expand Down
9 changes: 8 additions & 1 deletion tools/llvm-kompile-codegen/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include <kllvm/parser/KOREParser.h>
#include <kllvm/parser/location.h>

#include "runtime/alloc_cpp.h"
#include "runtime/opaque_cpp.h"

#include <llvm/Bitcode/BitcodeWriter.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit c2e8094

Please sign in to comment.