From b85edf69b4a4e1f97c15fd1f0bb2886dfddac85b Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Fri, 15 Oct 2021 15:46:22 -0500 Subject: [PATCH 01/12] update to runtimeverification/immer master branch containing iter fix --- deps/immer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/immer b/deps/immer index 198c2ae26..b18b13c28 160000 --- a/deps/immer +++ b/deps/immer @@ -1 +1 @@ -Subproject commit 198c2ae260d49ef1800a2fe4433e07d7dec20059 +Subproject commit b18b13c283627d38e5a3bce0c3c559d6d4174b75 From a95efe552fced0680b99ad4b54fe27ec8b72aaf7 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Mon, 18 Oct 2021 15:50:32 -0500 Subject: [PATCH 02/12] add SetIterator and MapIterator sort categories --- CMakeLists.txt | 2 ++ config/macros.h | 2 ++ include/kllvm/ast/AST.h | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 426e6aa85..4321a18d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -207,6 +207,8 @@ set(STRINGBUFFER_LAYOUT 6) set(BOOL_LAYOUT 7) set(SYMBOL_LAYOUT 8) set(VARIABLE_LAYOUT 9) +set(SETITER_LAYOUT 11) +set(MAPITER_LAYOUT 12) get_filename_component(INSTALL_DIR_ABS_PATH "${CMAKE_INSTALL_PREFIX}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") diff --git a/config/macros.h b/config/macros.h index f05e4c0ab..2bee14511 100644 --- a/config/macros.h +++ b/config/macros.h @@ -21,6 +21,8 @@ #define BOOL_LAYOUT @BOOL_LAYOUT@ #define SYMBOL_LAYOUT @SYMBOL_LAYOUT@ #define VARIABLE_LAYOUT @VARIABLE_LAYOUT@ +#define SETITER_LAYOUT @SETITER_LAYOUT@ +#define MAPITER_LAYOUT @MAPITER_LAYOUT@ #define STRINGIFY(x) #x #define TOSTRING(X) STRINGIFY(X) diff --git a/include/kllvm/ast/AST.h b/include/kllvm/ast/AST.h index c0091d691..27c001c02 100644 --- a/include/kllvm/ast/AST.h +++ b/include/kllvm/ast/AST.h @@ -107,7 +107,9 @@ enum class SortCategory { Bool, Symbol, Variable, - MInt + MInt, + SetIterator, + MapIterator, }; // represents the syntactic category of an LLVM backend term at runtime From 338d55fed3eb7c8ca19c43f8d916acabf69a33f8 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Mon, 18 Oct 2021 15:52:53 -0500 Subject: [PATCH 03/12] refactor search to use global variable to store results of stepAll --- include/kllvm/codegen/Decision.h | 10 ++---- lib/codegen/Decision.cpp | 55 ++++++-------------------------- runtime/util/search.cpp | 32 ++++++++----------- 3 files changed, 25 insertions(+), 72 deletions(-) diff --git a/include/kllvm/codegen/Decision.h b/include/kllvm/codegen/Decision.h index e360d2fdf..b8f4b439e 100644 --- a/include/kllvm/codegen/Decision.h +++ b/include/kllvm/codegen/Decision.h @@ -366,7 +366,6 @@ class Decision { llvm::LLVMContext &Ctx; ValueType Cat; llvm::PHINode *FailSubject, *FailPattern, *FailSort; - llvm::Value *ResultBuffer, *ResultCount, *ResultCapacity; std::map symbols; @@ -383,9 +382,7 @@ class Decision { llvm::BasicBlock *FailureBlock, llvm::IndirectBrInst *FailJump, llvm::AllocaInst *ChoiceBuffer, llvm::AllocaInst *ChoiceDepth, llvm::Module *Module, ValueType Cat, llvm::PHINode *FailSubject, - llvm::PHINode *FailPattern, llvm::PHINode *FailSort, - llvm::Value *ResultBuffer, llvm::Value *ResultCount, - llvm::Value *ResultCapacity) + llvm::PHINode *FailPattern, llvm::PHINode *FailSort) : Definition(Definition) , CurrentBlock(EntryBlock) , FailureBlock(FailureBlock) @@ -398,10 +395,7 @@ class Decision { , Cat(Cat) , FailSubject(FailSubject) , FailPattern(FailPattern) - , FailSort(FailSort) - , ResultBuffer(ResultBuffer) - , ResultCount(ResultCount) - , ResultCapacity(ResultCapacity) { } + , FailSort(FailSort) { } /* adds code to the specified basic block to take a single step based on the specified decision tree and return the result of taking that step. */ diff --git a/lib/codegen/Decision.cpp b/lib/codegen/Decision.cpp index da6fee7d9..b67419f59 100644 --- a/lib/codegen/Decision.cpp +++ b/lib/codegen/Decision.cpp @@ -474,14 +474,8 @@ void LeafNode::codegen(Decision *d) { getOrInsertFunction( d->Module, "addSearchResult", llvm::FunctionType::get( - llvm::Type::getVoidTy(d->Ctx), - {type, - llvm::PointerType::getUnqual(llvm::PointerType::get(type, 1)), - llvm::Type::getInt64PtrTy(d->Ctx), - llvm::Type::getInt64PtrTy(d->Ctx)}, - false)), - {Call, d->ResultBuffer, d->ResultCount, d->ResultCapacity}, "", - d->CurrentBlock); + llvm::Type::getVoidTy(d->Ctx), {type}, false)), + {Call}, "", d->CurrentBlock); setDebugLoc(Call2); if (child != FailNode::get()) { child->codegen(d); @@ -646,7 +640,7 @@ void makeEvalOrAnywhereFunction( int i = 0; Decision codegen( definition, block, fail, jump, choiceBuffer, choiceDepth, module, - returnSort, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); + returnSort, nullptr, nullptr, nullptr); for (auto val = matchFunc->arg_begin(); val != matchFunc->arg_end(); ++val, ++i) { val->setName("_" + std::to_string(i + 1)); @@ -798,7 +792,6 @@ void makeStepFunction( KOREDefinition *definition, llvm::Module *module, DecisionNode *dt, bool search) { auto blockType = getValueType({SortCategory::Symbol, 0}, module); - auto bufType = llvm::PointerType::get(blockType, 1); auto debugType = getDebugType({SortCategory::Symbol, 0}, "SortGeneratedTopCell{}"); llvm::FunctionType *funcType; @@ -806,8 +799,7 @@ void makeStepFunction( if (search) { name = "stepAll"; funcType = llvm::FunctionType::get( - bufType, {blockType, llvm::Type::getInt64PtrTy(module->getContext())}, - false); + llvm::Type::getVoidTy(module->getContext()), {blockType}, false); } else { name = "step"; funcType = llvm::FunctionType::get(blockType, {blockType}, false); @@ -817,10 +809,7 @@ void makeStepFunction( resetDebugLoc(); if (search) { initDebugFunction( - name, name, - getDebugFunctionType( - getPointerDebugType(debugType, "block **"), - {debugType, getPointerDebugType(getLongDebugType(), "uint64_t *")}), + name, name, getDebugFunctionType(getVoidDebugType(), {debugType}), definition, matchFunc); } else { initDebugFunction( @@ -841,30 +830,8 @@ void makeStepFunction( llvm::AllocaInst *choiceBuffer, *choiceDepth; llvm::IndirectBrInst *jump; - llvm::Value *resultBuffer = nullptr, *resultCount = nullptr, - *resultCapacity = nullptr; - if (search) { - resultBuffer = new llvm::AllocaInst(bufType, 0, "resultBuffer", block); - resultCount = matchFunc->arg_begin() + 1; - resultCapacity = new llvm::AllocaInst( - llvm::Type::getInt64Ty(module->getContext()), 0, "resultCapacity", - block); - } - insertCallToClear(block); - if (search) { - llvm::Value *initialBuffer = allocateTerm( - {SortCategory::Symbol, 0}, blockType, block, "koreAllocAlwaysGC"); - new llvm::StoreInst(initialBuffer, resultBuffer, block); - new llvm::StoreInst( - llvm::ConstantInt::get(llvm::Type::getInt64Ty(module->getContext()), 0), - resultCount, block); - new llvm::StoreInst( - llvm::ConstantInt::get(llvm::Type::getInt64Ty(module->getContext()), 1), - resultCapacity, block); - } - initChoiceBuffer( dt, module, block, pre_stuck, fail, &choiceBuffer, &choiceDepth, &jump); @@ -877,12 +844,10 @@ void makeStepFunction( val->setName("_1"); Decision codegen( definition, result, fail, jump, choiceBuffer, choiceDepth, module, - {SortCategory::Symbol, 0}, nullptr, nullptr, nullptr, resultBuffer, - resultCount, resultCapacity); + {SortCategory::Symbol, 0}, nullptr, nullptr, nullptr); codegen.store(std::make_pair(val->getName().str(), val->getType()), val); if (search) { - auto result = new llvm::LoadInst(bufType, resultBuffer, "", stuck); - llvm::ReturnInst::Create(module->getContext(), result, stuck); + llvm::ReturnInst::Create(module->getContext(), stuck); } else { llvm::ReturnInst::Create(module->getContext(), val, stuck); } @@ -949,8 +914,7 @@ void makeMatchReasonFunction( val->setName("_1"); Decision codegen( definition, block, fail, jump, choiceBuffer, choiceDepth, module, - {SortCategory::Symbol, 0}, FailSubject, FailPattern, FailSort, nullptr, - nullptr, nullptr); + {SortCategory::Symbol, 0}, FailSubject, FailPattern, FailSort); codegen.store(std::make_pair(val->getName().str(), val->getType()), val); llvm::ReturnInst::Create(module->getContext(), stuck); @@ -1065,8 +1029,7 @@ void makeStepFunction( i = 0; Decision codegen( definition, header, fail, jump, choiceBuffer, choiceDepth, module, - {SortCategory::Symbol, 0}, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr); + {SortCategory::Symbol, 0}, nullptr, nullptr, nullptr); for (auto val : args) { val->setName(res.residuals[i].occurrence.substr(0, max_name_length)); codegen.store(std::make_pair(val->getName().str(), val->getType()), val); diff --git a/runtime/util/search.cpp b/runtime/util/search.cpp index 0f1951dbe..a6dff54e6 100644 --- a/runtime/util/search.cpp +++ b/runtime/util/search.cpp @@ -6,22 +6,15 @@ #include "runtime/collect.h" #include "runtime/header.h" +static std::vector stepResults; + extern "C" { -void addSearchResult( - block *result, block ***bufPtr, uint64_t *count, uint64_t *capacity) { - if (*count == *capacity) { - size_t len = *count * sizeof(block *) * 2; - block **newBuf = (block **)koreAllocAlwaysGC(len); - memcpy(newBuf, *bufPtr, len); - *bufPtr = newBuf; - *capacity = *capacity * 2; - } - (*bufPtr)[*count] = result; - (*count)++; +void addSearchResult(block *result) { + stepResults.push_back(result); } -block **take_search_step(block *, uint64_t *); +void take_search_step(block *); } static std::list states; @@ -38,6 +31,9 @@ blockEnumerator() { blocks.push_back(const_cast(&(keyVal))); } blocks.push_back(&state); + for (auto &keyVal : stepResults) { + blocks.push_back(const_cast(&(keyVal))); + } return std::make_pair(blocks.begin(), blocks.end()); } @@ -60,15 +56,15 @@ take_search_steps(int64_t depth, block *subject) { states_set.erase(state); if (depth > 0) depth--; - uint64_t count; - block **stepResults = take_search_step(state, &count); - if (count == 0) { + stepResults.clear(); + take_search_step(state); + if (stepResults.size() == 0) { results.insert(state); } else { - for (uint64_t i = 0; i < count; i++) { - auto dirty = states_set.insert(stepResults[i]); + for (block *result : stepResults) { + auto dirty = states_set.insert(result); if (dirty.second) { - states.push_back(stepResults[i]); + states.push_back(result); } } } From 469ff8fb5db10c4c70982d551d920baf9376363e Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Mon, 18 Oct 2021 15:53:51 -0500 Subject: [PATCH 04/12] split %iter into %setiter and %mapiter --- lib/codegen/CreateTerm.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/codegen/CreateTerm.cpp b/lib/codegen/CreateTerm.cpp index 7b5ab2fcf..db8a7b84e 100644 --- a/lib/codegen/CreateTerm.cpp +++ b/lib/codegen/CreateTerm.cpp @@ -64,7 +64,8 @@ target triple = "x86_64-unknown-linux-gnu" %stringbuffer = type { i64, i64, %string* } ; 10-bit layout, 4-bit gc flags, 10 unused bits, 40-bit length, string length, current contents %map = type { { i8 *, i64 } } ; immer::map %set = type { { i8 *, i64 } } ; immer::set -%iter = type { { i8 *, i8 *, i32, [14 x i8**] }, { { i8 *, i64 } } } ; immer::map_iter / immer::set_iter +%setiter = type { { i8 *, i8 *, i32, [14 x i8**] }, { { i8 *, i64 } } } ; immer::set_iter +%mapiter = type { { i8 *, i8 *, i32, [14 x i8**] }, { { i8 *, i64 } } } ; immer::map_iter %list = type { { i64, i32, i8 *, i8 * } } ; immer::flex_vector %mpz = type { i32, i32, i64 * } ; mpz_t %mpz_hdr = type { %blockheader, %mpz } ; 10-bit layout, 4-bit gc flags, 10 unused bits, 40-bit length, mpz_t From ec1465ffc93412e63ea0a1369ce44887347f0ab8 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Mon, 18 Oct 2021 15:54:25 -0500 Subject: [PATCH 05/12] handle SetIterator and MapIterator SortCategory in several places --- lib/ast/AST.cpp | 2 ++ lib/codegen/CreateTerm.cpp | 8 ++++++++ lib/codegen/Debug.cpp | 2 ++ lib/codegen/EmitConfigParser.cpp | 8 ++++++++ lib/llvm/EmitGCLayoutInfo.cpp | 4 ++++ 5 files changed, 24 insertions(+) diff --git a/lib/ast/AST.cpp b/lib/ast/AST.cpp index 94652340d..88f45486f 100644 --- a/lib/ast/AST.cpp +++ b/lib/ast/AST.cpp @@ -220,6 +220,8 @@ std::string KORESymbol::layoutString(KOREDefinition *definition) const { result.append("_" + std::to_string(cat.bits) + "_"); case SortCategory::Symbol: result.push_back('0'); break; case SortCategory::Uncomputed: abort(); + case SortCategory::SetIterator: abort(); + case SortCategory::MapIterator: abort(); } } return result; diff --git a/lib/codegen/CreateTerm.cpp b/lib/codegen/CreateTerm.cpp index db8a7b84e..230a2d246 100644 --- a/lib/codegen/CreateTerm.cpp +++ b/lib/codegen/CreateTerm.cpp @@ -138,6 +138,8 @@ void addKompiledDirSymbol( static std::string MAP_STRUCT = "map"; static std::string LIST_STRUCT = "list"; static std::string SET_STRUCT = "set"; +static std::string SETITER_STRUCT = "setiter"; +static std::string MAPITER_STRUCT = "mapiter"; static std::string INT_WRAPPER_STRUCT = "mpz_hdr"; static std::string INT_STRUCT = "mpz"; static std::string FLOAT_WRAPPER_STRUCT = "floating_hdr"; @@ -149,6 +151,8 @@ static std::string BLOCKHEADER_STRUCT = "blockheader"; llvm::Type *getParamType(ValueType sort, llvm::Module *Module) { llvm::Type *type = getValueType(sort, Module); switch (sort.cat) { + case SortCategory::SetIterator: + case SortCategory::MapIterator: case SortCategory::Map: case SortCategory::List: case SortCategory::Set: type = llvm::PointerType::get(type, 1); break; @@ -162,6 +166,8 @@ llvm::Type *getValueType(ValueType sort, llvm::Module *Module) { case SortCategory::Map: return getTypeByName(Module, MAP_STRUCT); case SortCategory::List: return getTypeByName(Module, LIST_STRUCT); case SortCategory::Set: return getTypeByName(Module, SET_STRUCT); + case SortCategory::SetIterator: return getTypeByName(Module, SETITER_STRUCT); + case SortCategory::MapIterator: return getTypeByName(Module, MAPITER_STRUCT); case SortCategory::Int: return llvm::PointerType::get(getTypeByName(Module, INT_STRUCT), 1); case SortCategory::Float: @@ -341,6 +347,8 @@ llvm::Value *CreateTerm::createToken(ValueType sort, std::string contents) { case SortCategory::Map: case SortCategory::List: case SortCategory::Set: + case SortCategory::SetIterator: + case SortCategory::MapIterator: assert(false && "cannot create tokens of collection category"); case SortCategory::Int: { llvm::Constant *global = Module->getOrInsertGlobal( diff --git a/lib/codegen/Debug.cpp b/lib/codegen/Debug.cpp index 146818a3b..48f9c5ecc 100644 --- a/lib/codegen/Debug.cpp +++ b/lib/codegen/Debug.cpp @@ -180,6 +180,8 @@ llvm::DIType *getDebugType(ValueType type, std::string typeName) { types[typeName] = symbol; return symbol; case SortCategory::Uncomputed: abort(); + case SortCategory::SetIterator: abort(); + case SortCategory::MapIterator: abort(); } } diff --git a/lib/codegen/EmitConfigParser.cpp b/lib/codegen/EmitConfigParser.cpp index 82cc7d727..9c1c9c6cd 100644 --- a/lib/codegen/EmitConfigParser.cpp +++ b/lib/codegen/EmitConfigParser.cpp @@ -306,6 +306,8 @@ static llvm::Value *getArgValue( CaseBlock); break; case SortCategory::Uncomputed: abort(); + case SortCategory::MapIterator: abort(); + case SortCategory::SetIterator: abort(); } return arg; } @@ -362,6 +364,8 @@ static std::pair getEval( break; } case SortCategory::Uncomputed: abort(); + case SortCategory::MapIterator: abort(); + case SortCategory::SetIterator: abort(); } creator.getCurrentBlock()->getInstList().push_back(inst); return std::make_pair(retval, creator.getCurrentBlock()); @@ -590,6 +594,8 @@ static void emitGetToken(KOREDefinition *definition, llvm::Module *module) { case SortCategory::Variable: case SortCategory::Symbol: break; case SortCategory::Uncomputed: abort(); + case SortCategory::MapIterator: abort(); + case SortCategory::SetIterator: abort(); } CurrentBlock = FalseBlock; } @@ -981,6 +987,8 @@ static void getVisitor( break; } case SortCategory::Uncomputed: abort(); + case SortCategory::MapIterator: abort(); + case SortCategory::SetIterator: abort(); } if (i != symbol->getArguments().size() - 1) { llvm::CallInst::Create( diff --git a/lib/llvm/EmitGCLayoutInfo.cpp b/lib/llvm/EmitGCLayoutInfo.cpp index 2d71c1ca3..81e29ac52 100644 --- a/lib/llvm/EmitGCLayoutInfo.cpp +++ b/lib/llvm/EmitGCLayoutInfo.cpp @@ -74,6 +74,10 @@ struct EmitGCLayoutInfo : public ModulePass { cat.cat = SortCategory::List; } else if (name == "set") { cat.cat = SortCategory::Set; + } else if (name == "setiter") { + cat.cat = SortCategory::SetIterator; + } else if (name == "mapiter") { + cat.cat = SortCategory::SetIterator; } else if (name == "mpz") { cat.cat = SortCategory::Int; } else if (name == "floating") { From a3d94fcd97dde0d5b026cc2fabc3555851f3be0e Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Mon, 18 Oct 2021 15:54:57 -0500 Subject: [PATCH 06/12] handle setiter and mapiter struct types during pattern matching codegen --- lib/codegen/Decision.cpp | 8 ++++++-- lib/codegen/DecisionParser.cpp | 19 ++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/lib/codegen/Decision.cpp b/lib/codegen/Decision.cpp index b67419f59..b8317aba3 100644 --- a/lib/codegen/Decision.cpp +++ b/lib/codegen/Decision.cpp @@ -394,8 +394,12 @@ void MakeIteratorNode::codegen(Decision *d) { llvm::Value *arg = d->load(std::make_pair(collection, collectionType)); args.push_back(arg); types.push_back(arg->getType()); - llvm::Type *sretType = getTypeByName(d->Module, "iter"); - llvm::Value *AllocSret = allocateTermNoReloc(sretType, d->CurrentBlock); + llvm::Type *sretType = type->getPointerElementType(); + llvm::Value *AllocSret = allocateTerm( + {hookName == "set_iterator" ? SortCategory::SetIterator + : SortCategory::MapIterator, + 0}, + sretType, d->CurrentBlock, "koreAllocAlwaysGC"); AllocSret->setName(name.substr(0, max_name_length)); args.insert(args.begin(), AllocSret); types.insert(types.begin(), AllocSret->getType()); diff --git a/lib/codegen/DecisionParser.cpp b/lib/codegen/DecisionParser.cpp index 604c6d03b..32574ce13 100644 --- a/lib/codegen/DecisionParser.cpp +++ b/lib/codegen/DecisionParser.cpp @@ -197,27 +197,32 @@ class DTPreprocessor { DecisionNode *makeIterator(yaml_node_t *node) { std::string name = to_string(vec(get(node, "collection"))); - llvm::Type *type = getParamType( - KORECompositeSort::getCategory(str(get(node, "sort"))), mod); + std::string cat = str(get(node, "sort")); + llvm::Type *type = getParamType(KORECompositeSort::getCategory(cat), mod); std::string function = str(get(node, "function")); auto child = (*this)(get(node, "next")); return MakeIteratorNode::Create( name, type, name + "_iter", - llvm::PointerType::getUnqual(getTypeByName(mod, "iter")), function, - child); + llvm::PointerType::get( + getTypeByName(mod, cat == "SET.Set" ? "setiter" : "mapiter"), 1), + function, child); } DecisionNode *iterNext(yaml_node_t *node) { std::string iterator = to_string(vec(get(node, "iterator"))) + "_iter"; std::string name = to_string(vec(get(node, "binding"))); - llvm::Type *type = getParamType( - KORECompositeSort::getCategory(str(get(node, "sort"))), mod); + std::string cat = str(get(node, "sort")); + llvm::Type *type = getParamType(KORECompositeSort::getCategory(cat), mod); std::string function = str(get(node, "function")); auto child = (*this)(get(node, "next")); return IterNextNode::Create( - iterator, llvm::PointerType::getUnqual(getTypeByName(mod, "iter")), + iterator, + llvm::PointerType::get( + getTypeByName( + mod, function == "set_iterator_next" ? "setiter" : "mapiter"), + 1), name, type, function, child); } From dc824e07ac8ed869c2b9f38a3f085e1d2b02e189 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Mon, 18 Oct 2021 15:55:17 -0500 Subject: [PATCH 07/12] koreAllocAlwaysGC wrappers for %setiter and %mapiter --- runtime/alloc/alloc.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/runtime/alloc/alloc.cpp b/runtime/alloc/alloc.cpp index afc4ae2ac..9cef88474 100644 --- a/runtime/alloc/alloc.cpp +++ b/runtime/alloc/alloc.cpp @@ -100,6 +100,16 @@ koreAllocAlwaysGC_p1s_lists(size_t requested) { return (list *)koreAllocAlwaysGC(requested); } +__attribute__((always_inline)) setiter * +koreAllocAlwaysGC_p1s_setiters(size_t requested) { + return (setiter *)koreAllocAlwaysGC(requested); +} + +__attribute__((always_inline)) mapiter * +koreAllocAlwaysGC_p1s_mapiters(size_t requested) { + return (mapiter *)koreAllocAlwaysGC(requested); +} + __attribute__((always_inline)) block * koreAllocAlwaysGC_p1s_blocks(size_t requested) { return (block *)koreAllocAlwaysGC(requested); From 89a2cbd269bbec738e40ff536165ea168cc5535b Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Mon, 18 Oct 2021 15:55:41 -0500 Subject: [PATCH 08/12] when migrating regular blocks, write offset to base pointer into cells --- runtime/collect/collect.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/runtime/collect/collect.cpp b/runtime/collect/collect.cpp index 714333656..ee6023646 100644 --- a/runtime/collect/collect.cpp +++ b/runtime/collect/collect.cpp @@ -69,6 +69,29 @@ void migrate(block **blockPtr) { memcpy(newBlock, currBlock, lenInBytes); migrate_header(newBlock); *forwardingAddress = newBlock; + + // if this is a regular block (not a string), then we know the size is a + // multiple of 8. The first word is the block header, and the next word (we + // always know it is at least 16 bytes in length) is the forwarding address. + // However, in order to be able to evacuate set or map iterators, it is + // helpful that we need to know the offset of a particular map or set + // pointer within its parent block. Since blocks in the llvm backend can be + // at most 256 words long, and since a number less than 256 is never a valid + // heap pointer, we can simply write the number of words since the base of + // the object to every word in the block after the forwarding pointer. To + // find the base of the object, then, from the pointer to the root of the + // collection, we first compare the value located at that root to 256. If it + // is greater or equal, we interpret it as the forwarding address and know + // that the offset is precisely 8 bytes. If it is less, we interpret it as + // the offset and subtract offset-1 in order to get the address of the + // forwarding pointer. + if (layout) { + size_t lenInWords = lenInBytes / sizeof(size_t); + for (size_t i = 2; i < lenInWords; i++) { + size_t *word = (size_t *)(currBlock + i); + *word = i; + } + } currBlock->h.hdr |= FWD_PTR_BIT; *blockPtr = newBlock; } else { From 3c54cccd2bda65c4666c0c2cb0fdbc5204d2c7b4 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Mon, 18 Oct 2021 15:56:25 -0500 Subject: [PATCH 09/12] track set and map iterator evacuations --- runtime/collect/collect.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/runtime/collect/collect.cpp b/runtime/collect/collect.cpp index ee6023646..6d31a12b6 100644 --- a/runtime/collect/collect.cpp +++ b/runtime/collect/collect.cpp @@ -227,6 +227,8 @@ static void migrate_floating(floating **floatingPtr) { *floatingPtr = *(floating **)(flt->f.f->_mpfr_d); } +static std::vector setiter_evacuations, mapiter_evacuations; + static void migrate_child(void *currBlock, layoutitem *args, unsigned i, bool ptr) { layoutitem *argData = args + i; @@ -240,6 +242,8 @@ migrate_child(void *currBlock, layoutitem *args, unsigned i, bool ptr) { case VARIABLE_LAYOUT: migrate((block **)arg); break; case INT_LAYOUT: migrate_mpz((mpz_ptr *)arg); break; case FLOAT_LAYOUT: migrate_floating((floating **)arg); break; + case SETITER_LAYOUT: setiter_evacuations.push_back(currBlock); break; + case MAPITER_LAYOUT: mapiter_evacuations.push_back(currBlock); break; case BOOL_LAYOUT: default: // mint break; @@ -341,6 +345,8 @@ void koreCollect(void) { MEM_LOG("Starting garbage collection\n"); std::vector roots = scanStackRoots(); + setiter_evacuations.clear(); + mapiter_evacuations.clear(); #ifdef GC_DBG if (!last_alloc_ptr) { From 89d32cbb2c547724cc1d2c562b1a64d41617076f Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Mon, 18 Oct 2021 16:03:24 -0500 Subject: [PATCH 10/12] evacuate map and set iterators in alwaysgc space --- include/runtime/collect.h | 2 + runtime/collect/collect.cpp | 7 +++ runtime/collect/migrate_collection.cpp | 68 ++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/include/runtime/collect.h b/include/runtime/collect.h index 784c866ce..79c333777 100644 --- a/include/runtime/collect.h +++ b/include/runtime/collect.h @@ -44,6 +44,8 @@ void migrate_once(block **); void migrate_list(void *l); void migrate_map(void *m); void migrate_set(void *s); +void evacuate_setiter(void *s); +void evacuate_mapiter(void *s); void migrate_collection_node(void **nodePtr); void setKoreMemoryFunctionsForGMP(void); void koreCollect(void); diff --git a/runtime/collect/collect.cpp b/runtime/collect/collect.cpp index 6d31a12b6..13b7ef14f 100644 --- a/runtime/collect/collect.cpp +++ b/runtime/collect/collect.cpp @@ -424,6 +424,13 @@ void koreCollect(void) { sizeof(numBytesLiveAtCollection) / sizeof(numBytesLiveAtCollection[0]), stderr); #endif + MEM_LOG("Evacuating alwaysgc space\n"); + for (void *ptr : setiter_evacuations) { + evacuate_setiter(*(setiter **)ptr); + } + for (void *ptr : mapiter_evacuations) { + evacuate_mapiter(*(mapiter **)ptr); + } MEM_LOG("Finishing garbage collection\n"); is_gc = false; } diff --git a/runtime/collect/migrate_collection.cpp b/runtime/collect/migrate_collection.cpp index c22240ed5..ccc38a705 100644 --- a/runtime/collect/migrate_collection.cpp +++ b/runtime/collect/migrate_collection.cpp @@ -116,3 +116,71 @@ void migrate_map(void *m) { migrate_collection_node((void **)&impl.root); migrate_champ_traversal(impl.root, 0, migrate_map_leaf); } + +template +void evacuate_iter(void *i) { + auto it = (Iter *)i; + struct iter { + Elem *cur_; + Elem *end_; + immer::detail::hamts::count_t depth_; + immer::detail::hamts::count_t cur_off_; + Node *const + *path_[immer::detail::hamts::max_depth + 1]; + std::uint8_t + path_off_[immer::detail::hamts::max_depth]; + }; + auto impl = (iter *)&it->curr; + // impl->path_[0] always points to the same address at which the root of the + // map or set is located. This is because impl->path_[0] is always taken to be + // equal to a pointer to the pointer to the root of the collection. Because + // this map/list/set is always allocated in the kore heap inline to the block + // that it is a child of, and because of the particular behavior of the + // migrate function when migrating regular blocks, we know that + // *impl->path_[0] can be used in order to compute the base pointer and the + // derived offset of the map pointer within its parent block + block **root_ptr = (block **)impl->path_[0]; + if ((uintptr_t)*root_ptr >= 256) { + impl->path_[0] = (Node *const *)(*root_ptr + 1); + } else { + // in words + auto derived_offset = (size_t)*root_ptr; + auto relocated_base_ptr = *(root_ptr - derived_offset - 1); + impl->path_[0] = (Node *const *)(relocated_base_ptr + derived_offset); + } + for (size_t i = 1; i <= impl->depth_; i++) { + auto derived_ptr = impl->path_[i]; + auto buffer_ptr = derived_ptr - impl->path_off_[i - 1]; + auto base_ptr = struct_base(Node, impl.d.data.inner.buffer, buffer_ptr); + auto derived_offset = (char *)derived_ptr - (char *)base_ptr; + migrate_collection_node((void **)&base_ptr); + auto relocated_derived_ptr + = (Node *const *)((char *)base_ptr + derived_offset); + impl->path_[i] = relocated_derived_ptr; + } + auto derived_ptr = impl->cur_; + if (derived_ptr) { + auto base_ptr = derived_ptr - impl->cur_off_; + auto derived_offset = (char *)derived_ptr - (char *)base_ptr; + auto end_offset = impl->end_ - impl->cur_; + auto child = *impl->path_[impl->depth_]; + Elem *relocated_base_ptr; + if (impl->depth_ < immer::detail::hamts::max_depth) { + relocated_base_ptr = child->values(); + } else { + relocated_base_ptr = child->collisions(); + } + auto relocated_derived_ptr + = (Elem *)((char *)relocated_base_ptr + derived_offset); + impl->cur_ = relocated_derived_ptr; + impl->end_ = impl->cur_ + end_offset; + } +} + +void evacuate_setiter(void *i) { + evacuate_iter(i); +} + +void evacuate_mapiter(void *i) { + evacuate_iter, map::iterator::node_t>(i); +} From 42267b23d3ae6dd37c2e5ebaebd298ae12fd506a Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Tue, 19 Oct 2021 10:56:16 -0500 Subject: [PATCH 11/12] add assertions about decision trees with iterators --- lib/codegen/Decision.cpp | 1 + lib/codegen/DecisionParser.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lib/codegen/Decision.cpp b/lib/codegen/Decision.cpp index b8317aba3..73946ff40 100644 --- a/lib/codegen/Decision.cpp +++ b/lib/codegen/Decision.cpp @@ -395,6 +395,7 @@ void MakeIteratorNode::codegen(Decision *d) { args.push_back(arg); types.push_back(arg->getType()); llvm::Type *sretType = type->getPointerElementType(); + assert(hookName == "set_iterator" || hookName == "map_iterator"); llvm::Value *AllocSret = allocateTerm( {hookName == "set_iterator" ? SortCategory::SetIterator : SortCategory::MapIterator, diff --git a/lib/codegen/DecisionParser.cpp b/lib/codegen/DecisionParser.cpp index 32574ce13..0ac727107 100644 --- a/lib/codegen/DecisionParser.cpp +++ b/lib/codegen/DecisionParser.cpp @@ -217,6 +217,8 @@ class DTPreprocessor { std::string function = str(get(node, "function")); auto child = (*this)(get(node, "next")); + assert(function == "set_iterator_next" || function == "map_iterator_next"); + return IterNextNode::Create( iterator, llvm::PointerType::get( From b9a36493014dc40d36fe06d870f6063f2b23c380 Mon Sep 17 00:00:00 2001 From: Dwight Guth Date: Wed, 20 Oct 2021 11:26:56 -0500 Subject: [PATCH 12/12] Add another assertion --- lib/codegen/DecisionParser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/codegen/DecisionParser.cpp b/lib/codegen/DecisionParser.cpp index 0ac727107..d652b3164 100644 --- a/lib/codegen/DecisionParser.cpp +++ b/lib/codegen/DecisionParser.cpp @@ -202,6 +202,8 @@ class DTPreprocessor { std::string function = str(get(node, "function")); auto child = (*this)(get(node, "next")); + assert(cat == "SET.Set" || cat == "MAP.Map"); + return MakeIteratorNode::Create( name, type, name + "_iter", llvm::PointerType::get(