From 37ec63c7e3b0932e748836060fbccbd0cfb39fc2 Mon Sep 17 00:00:00 2001 From: Roberto Rosmaninho Date: Mon, 17 Apr 2023 15:42:17 -0300 Subject: [PATCH 1/5] Lookup for debug function instead of side function o gdb k match --- debug/kgdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debug/kgdb.py b/debug/kgdb.py index 0ece04c7e..f4347a704 100644 --- a/debug/kgdb.py +++ b/debug/kgdb.py @@ -761,7 +761,7 @@ def invoke(self, arg, from_tty): print('Match succeeds') elif entry['kind'] == self.FUNCTION: print(entry['debugName'].string("iso-8859-1") + '(', end='') - function = gdb.lookup_global_symbol(entry['function'].string("iso-8859-1")).value().type + function = gdb.lookup_global_symbol(entry['debugName'].string("iso-8859-1")).value().type front = gdb.lookup_global_symbol("getMatchFnArgs").value()(entry.address) conn = "" for i in range(len(function.fields())): From 3dde15299d771fec5ed0a7f97de4011c233f4b98 Mon Sep 17 00:00:00 2001 From: Roberto Rosmaninho Date: Tue, 18 Apr 2023 17:21:41 -0300 Subject: [PATCH 2/5] Ordering function lt and equality, for KElem, in C instead of llvm. WIP. --- include/runtime/header.h | 1 + runtime/collections/CMakeLists.txt | 1 + runtime/collections/kelemle.cpp | 216 +++++++++++++++++++++++++++++ runtime/equality.ll | 118 +--------------- 4 files changed, 219 insertions(+), 117 deletions(-) create mode 100644 runtime/collections/kelemle.cpp diff --git a/include/runtime/header.h b/include/runtime/header.h index 057760b8f..168b79339 100644 --- a/include/runtime/header.h +++ b/include/runtime/header.h @@ -31,6 +31,7 @@ #define size_hdr(s) ((((s) >> 32) & 0xff) * 8) #define layout(s) layout_hdr((s)->h.hdr) #define layout_hdr(s) ((s) >> LAYOUT_OFFSET) +#define tag(s) tag_hdr((s)->h.hdr) #define tag_hdr(s) (s & TAG_MASK) #define is_in_young_gen_hdr(s) (!((s)&NOT_YOUNG_OBJECT_BIT)) #define is_in_old_gen_hdr(s) (((s)&NOT_YOUNG_OBJECT_BIT) && ((s)&AGE_MASK)) diff --git a/runtime/collections/CMakeLists.txt b/runtime/collections/CMakeLists.txt index 8ea4543a3..5bc8cb4ac 100644 --- a/runtime/collections/CMakeLists.txt +++ b/runtime/collections/CMakeLists.txt @@ -1,4 +1,5 @@ add_library(collections STATIC + kelemle.cpp lists.cpp maps.cpp sets.cpp diff --git a/runtime/collections/kelemle.cpp b/runtime/collections/kelemle.cpp new file mode 100644 index 000000000..ce0830b99 --- /dev/null +++ b/runtime/collections/kelemle.cpp @@ -0,0 +1,216 @@ +#include "runtime/header.h" + +extern "C" { +bool hook_MAP_eq(SortMap, SortMap); +bool hook_LIST_eq(SortList, SortList); +bool hook_SET_eq(SortSet, SortSet); +bool hook_INT_eq(SortInt, SortInt); +bool hook_FLOAT_trueeq(SortFloat, SortFloat); +bool hook_STRING_lt(SortString, SortString); + +bool hook_KEQUAL_eq(block *arg1, block *arg2) { + uint64_t arg1intptr = (uint64_t)arg1; + uint64_t arg2intptr = (uint64_t)arg2; + bool arg1lb = is_leaf_block(arg1intptr); + bool arg2lb = is_leaf_block(arg2intptr); + if (arg1lb == arg2lb) { + if (arg1lb) { + // Both arg1 and arg2 are constants. + return arg1intptr == arg2intptr; + } else { + // Both arg1 and arg2 are blocks. + uint64_t arg1hdrcanon = arg1->h.hdr & HDR_MASK; + uint64_t arg2hdrcanon = arg2->h.hdr & HDR_MASK; + if (arg1hdrcanon == arg2hdrcanon) { + // Canonical headers of arg1 and arg2 are equal. + // Both arg1 and arg2 are either strings or symbols. + uint64_t arglayout = layout(arg1); + if (arglayout == 0) { + // Both arg1 and arg2 are strings. + return hook_STRING_eq((string *)arg1, (string *)arg2); + } else { // arglayout != 0 + // Both arg1 and arg2 are blocks. + uint16_t arglayoutshort = (uint16_t)arglayout; + layout *layoutPtr = getLayoutData(arglayoutshort); + uint8_t length = layoutPtr->nargs; + for (uint8_t i = 0; i < length; i++) { + uint64_t offset = layoutPtr->args[i].offset; + uint64_t child1intptr = arg1intptr + offset; + uint64_t child2intptr = arg2intptr + offset; + uint16_t cat = layoutPtr->args[i].cat; + switch (cat) { + case MAP_LAYOUT: { + map *map1ptr = (map *)(child1intptr); + map *map2ptr = (map *)(child2intptr); + bool cmp = hook_MAP_eq(map1ptr, map2ptr); + if (!cmp) { + return false; + } + break; + } + case LIST_LAYOUT: { + list *list1ptr = (list *)(child1intptr); + list *list2ptr = (list *)(child2intptr); + bool cmp = hook_LIST_eq(list1ptr, list2ptr); + if (!cmp) { + return false; + } + break; + } + case SET_LAYOUT: { + set *set1ptr = (set *)(child1intptr); + set *set2ptr = (set *)(child2intptr); + bool cmp = hook_SET_eq(set1ptr, set2ptr); + if (!cmp) { + return false; + } + break; + } + case INT_LAYOUT: { + mpz_ptr *int1ptrptr = (mpz_ptr *)(child1intptr); + mpz_ptr *int2ptrptr = (mpz_ptr *)(child2intptr); + bool cmp = hook_INT_eq(*int1ptrptr, *int2ptrptr); + if (!cmp) { + return false; + } + break; + } + case FLOAT_LAYOUT: { + floating **float1ptrptr = (floating **)(child1intptr); + floating **float2ptrptr = (floating **)(child2intptr); + bool cmp = hook_FLOAT_trueeq(*float1ptrptr, *float2ptrptr); + if (!cmp) { + return false; + } + break; + } + case STRINGBUFFER_LAYOUT: { + abort(); + } + case BOOL_LAYOUT: { + bool *bool1ptr = (bool *)(child1intptr); + bool *bool2ptr = (bool *)(child2intptr); + bool cmp = *bool1ptr == *bool2ptr; + if (!cmp) { + return false; + } + break; + } + case SYMBOL_LAYOUT: { + block **child1ptrptr = (block **)(child1intptr); + block **child2ptrptr = (block **)(child2intptr); + bool cmp = hook_KEQUAL_eq(*child1ptrptr, *child2ptrptr); + if (!cmp) { + return false; + } + break; + } + case VARIABLE_LAYOUT: { + block **var1ptrptr = (block **)(child1intptr); + block **var2ptrptr = (block **)(child2intptr); + bool cmp = hook_STRING_eq( + (string *)*var1ptrptr, (string *)*var2ptrptr); + if (!cmp) { + return false; + } + break; + } + default: abort(); + } + } + return true; + } + } else { // arg1hdrcanon != arg2hdrcanon + return false; + } + } + } else { // arg1lb != arg2lb + // Between arg1 and arg2, one is a constant and one is a block. + return false; + } +} + +// We arbitrarily impose the following ordering betwene different types of +// blocks: +// - Constants < Blocks. +// - Symbols < Strings. +// - Symbols with different tags are ordered based on their tags. +// - Symbols with same tags are ordered be lexicographically comparing their +// childen. +bool hook_KEQUAL_lt(block *arg1, block *arg2) { + uint64_t arg1intptr = (uint64_t)arg1; + uint64_t arg2intptr = (uint64_t)arg2; + bool isconstant1 = is_leaf_block(arg1intptr); + bool isconstant2 = is_leaf_block(arg2intptr); + if (isconstant1 != isconstant2) { + // Between arg1 and arg2, one is a constant and one is not. + return isconstant1; + } else if (isconstant1) { + // Both arg1 and arg2 are constants. + return arg1intptr < arg2intptr; + } else { + // Both arg1 and arg2 are blocks. + uint16_t arg1layout = layout(arg1); + uint16_t arg2layout = layout(arg2); + if (arg1layout == 0 && arg2layout == 0) { + // Both arg1 and arg2 are strings. + return hook_STRING_lt((string *)arg1, (string *)arg2); + } else if (arg1layout == 0 || arg2layout == 0) { + // One of arg1, arg2 is a string, the other is a symbol. + return arg2layout == 0; + } else { + // Both arg1 and arg2 are symbols. + uint32_t arg1tag = tag(arg1); + uint32_t arg2tag = tag(arg2); + if (arg1tag != arg2tag) { + return arg1tag < arg2tag; + } else { + assert(arg1layout == arg2layout); + layout *layoutPtr = getLayoutData(arg1layout); + uint8_t length = layoutPtr->nargs; + for (uint8_t i = 0; i < length; i++) { + uint64_t offset = layoutPtr->args[i].offset; + uint16_t cat = layoutPtr->args[i].cat; + switch (cat) { + case MAP_LAYOUT: { + abort(); // Implement when needed. + } + case LIST_LAYOUT: { + abort(); // Implement when needed. + } + case SET_LAYOUT: { + abort(); // Implement when needed. + } + case INT_LAYOUT: { + mpz_ptr *int1ptrptr = (mpz_ptr *)(arg1intptr + offset); + mpz_ptr *int2ptrptr = (mpz_ptr *)(arg2intptr + offset); + int cmp = mpz_cmp(*int1ptrptr, *int2ptrptr); + if (cmp != 0) { + return cmp < 0; + } + break; + } + case FLOAT_LAYOUT: { + abort(); // Implement when needed. + } + case STRINGBUFFER_LAYOUT: { + abort(); // Implement when needed. + } + case BOOL_LAYOUT: { + abort(); // Implement when needed. + } + case SYMBOL_LAYOUT: { + abort(); // Implement when needed. + } + case VARIABLE_LAYOUT: { + abort(); // Implement when needed. + } + default: abort(); + } + } + return false; + } + } + } +} +} diff --git a/runtime/equality.ll b/runtime/equality.ll index 933366171..384772485 100644 --- a/runtime/equality.ll +++ b/runtime/equality.ll @@ -21,123 +21,7 @@ declare i1 @hook_SET_eq(%set*, %set*) declare i1 @hook_INT_eq(%mpz*, %mpz*) declare i1 @hook_FLOAT_trueeq(%floating*, %floating*) declare i1 @hook_STRING_eq(%block*, %block*) - -define i1 @hook_KEQUAL_eq(%block* %arg1, %block* %arg2) { -entry: - %arg1intptr = ptrtoint %block* %arg1 to i64 - %arg2intptr = ptrtoint %block* %arg2 to i64 - %arg1leastbit = trunc i64 %arg1intptr to i1 - %arg2leastbit = trunc i64 %arg2intptr to i1 - %eq = icmp eq i1 %arg1leastbit, %arg2leastbit - br i1 %eq, label %getTag, label %exit -getTag: - br i1 %arg1leastbit, label %constant, label %block -constant: - %eqconstant = icmp eq i64 %arg1intptr, %arg2intptr - br label %exit -block: - %arg1hdrptr = getelementptr inbounds %block, %block* %arg1, i64 0, i32 0, i32 0 - %arg2hdrptr = getelementptr inbounds %block, %block* %arg2, i64 0, i32 0, i32 0 - %arg1hdr = load i64, i64* %arg1hdrptr - %arg2hdr = load i64, i64* %arg2hdrptr - %arg1len = and i64 %arg1hdr, @HDR_MASK@ - %arg2len = and i64 %arg2hdr, @HDR_MASK@ - %eqblock = icmp eq i64 %arg1len, %arg2len - br i1 %eqblock, label %getChildren, label %exit -getChildren: - %arglayout = lshr i64 %arg1hdr, @LAYOUT_OFFSET@ - %isString = icmp eq i64 %arglayout, 0 - br i1 %isString, label %eqString, label %compareChildren -eqString: - %eqcontents = call i1 @hook_STRING_eq(%block* %arg1, %block* %arg2) - br label %exit -compareChildren: - %arglayoutshort = trunc i64 %arglayout to i16 - %layoutPtr = call %layout* @getLayoutData(i16 %arglayoutshort) - %layoutData = load %layout, %layout* %layoutPtr - %length = extractvalue %layout %layoutData, 0 - %children = extractvalue %layout %layoutData, 1 - br label %loop -loop: - %counter = phi i8 [ %length, %compareChildren ], [ %sub1, %compareMap ], [ %sub1, %compareList ], [ %sub1, %compareSet ], [ %sub1, %compareInt ], [ %sub1, %compareFloat ], [ %sub1, %compareBool ], [ %sub1, %compareSymbol ], [ %sub1, %compareVariable ] - %index = sub i8 %length, %counter - %indexlong = zext i8 %index to i64 - %sub1 = sub i8 %counter, 1 - %finished = icmp eq i8 %counter, 0 - br i1 %finished, label %exit, label %compareChild -compareChild: - %offsetPtr = getelementptr %layoutitem, %layoutitem* %children, i64 %indexlong, i32 0 - %offset = load i64, i64* %offsetPtr - %kindPtr = getelementptr %layoutitem, %layoutitem* %children, i64 %indexlong, i32 1 - %kind = load i16, i16* %kindPtr - %child1intptr = add i64 %arg1intptr, %offset - %child2intptr = add i64 %arg2intptr, %offset - switch i16 %kind, label %stuck [ i16 @MAP_LAYOUT@, label %compareMap - i16 @LIST_LAYOUT@, label %compareList - i16 @SET_LAYOUT@, label %compareSet - i16 @INT_LAYOUT@, label %compareInt - i16 @FLOAT_LAYOUT@, label %compareFloat - i16 @STRINGBUFFER_LAYOUT@, label %stuck - i16 @BOOL_LAYOUT@, label %compareBool - i16 @SYMBOL_LAYOUT@, label %compareSymbol - i16 @VARIABLE_LAYOUT@, label %compareVariable ] -compareMap: - %map1ptr = inttoptr i64 %child1intptr to %map* - %map2ptr = inttoptr i64 %child2intptr to %map* - %comparedMap = call i1 @hook_MAP_eq(%map* %map1ptr, %map* %map2ptr) - br i1 %comparedMap, label %loop, label %exit -compareList: - %list1ptr = inttoptr i64 %child1intptr to %list* - %list2ptr = inttoptr i64 %child2intptr to %list* - %comparedList = call i1 @hook_LIST_eq(%list* %list1ptr, %list* %list2ptr) - br i1 %comparedList, label %loop, label %exit -compareSet: - %set1ptr = inttoptr i64 %child1intptr to %set* - %set2ptr = inttoptr i64 %child2intptr to %set* - %comparedSet = call i1 @hook_SET_eq(%set* %set1ptr, %set* %set2ptr) - br i1 %comparedSet, label %loop, label %exit -compareInt: - %int1ptrptr = inttoptr i64 %child1intptr to %mpz** - %int2ptrptr = inttoptr i64 %child2intptr to %mpz** - %int1ptr = load %mpz*, %mpz** %int1ptrptr - %int2ptr = load %mpz*, %mpz** %int2ptrptr - %comparedInt = call i1 @hook_INT_eq(%mpz* %int1ptr, %mpz* %int2ptr) - br i1 %comparedInt, label %loop, label %exit -compareFloat: - %float1ptrptr = inttoptr i64 %child1intptr to %floating** - %float2ptrptr = inttoptr i64 %child2intptr to %floating** - %float1ptr = load %floating*, %floating** %float1ptrptr - %float2ptr = load %floating*, %floating** %float2ptrptr - %comparedFloat = call i1 @hook_FLOAT_trueeq(%floating* %float1ptr, %floating* %float2ptr) - br i1 %comparedFloat, label %loop, label %exit -compareBool: - %bool1ptr = inttoptr i64 %child1intptr to i1* - %bool2ptr = inttoptr i64 %child2intptr to i1* - %bool1 = load i1, i1* %bool1ptr - %bool2 = load i1, i1* %bool2ptr - %comparedBool = icmp eq i1 %bool1, %bool2 - br i1 %comparedBool, label %loop, label %exit -compareSymbol: - %child1ptrptr = inttoptr i64 %child1intptr to %block** - %child2ptrptr = inttoptr i64 %child2intptr to %block** - %child1ptr = load %block*, %block** %child1ptrptr - %child2ptr = load %block*, %block** %child2ptrptr - %comparedSymbol = call i1 @hook_KEQUAL_eq(%block* %child1ptr, %block* %child2ptr) - br i1 %comparedSymbol, label %loop, label %exit -compareVariable: - %var1ptrptr = inttoptr i64 %child1intptr to %block** - %var2ptrptr = inttoptr i64 %child2intptr to %block** - %var1ptr = load %block*, %block** %var1ptrptr - %var2ptr = load %block*, %block** %var2ptrptr - %comparedVar = call i1 @hook_STRING_eq(%block* %var1ptr, %block* %var2ptr) - br i1 %comparedVar, label %loop, label %exit -exit: - %phi = phi i1 [ 0, %entry ], [ %eqconstant, %constant ], [ 0, %block ], [ %eqcontents, %eqString ], [ 1, %loop ], [ 0, %compareMap ], [ 0, %compareList ], [ 0, %compareSet ], [ 0, %compareInt ], [ 0, %compareFloat ], [ 0, %compareBool ], [ 0, %compareSymbol ], [ 0, %compareVariable ] - ret i1 %phi -stuck: - call void @abort() - unreachable -} +declare i1 @hook_KEQUAL_eq(%block* %arg1, %block* %arg2) define i1 @hook_KEQUAL_ne(%block* %arg1, %block* %arg2) { %eq = call i1 @hook_KEQUAL_eq(%block* %arg1, %block* %arg2) From 67c4a41b283dbfdbbd92b8b34b9fa0e64fcc2eb8 Mon Sep 17 00:00:00 2001 From: Roberto Rosmaninho Date: Tue, 18 Apr 2023 17:34:29 -0300 Subject: [PATCH 3/5] Setting the correct function name to lookup globally on the symbol table --- debug/kgdb.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/debug/kgdb.py b/debug/kgdb.py index f4347a704..924f59c7c 100644 --- a/debug/kgdb.py +++ b/debug/kgdb.py @@ -760,8 +760,11 @@ def invoke(self, arg, from_tty): if entry['kind'] == self.SUCCESS: print('Match succeeds') elif entry['kind'] == self.FUNCTION: - print(entry['debugName'].string("iso-8859-1") + '(', end='') - function = gdb.lookup_global_symbol(entry['debugName'].string("iso-8859-1")).value().type + debugFunctionName = entry['debugName'].string("iso-8859-1") + functionName = entry['function'].string("iso-8859-1") + print(debugFunctionName + '(', end='') + name = functionName if functionName[:5] == 'hook_' else debugFunctionName + function = gdb.lookup_global_symbol(name).value().type front = gdb.lookup_global_symbol("getMatchFnArgs").value()(entry.address) conn = "" for i in range(len(function.fields())): From 7e1f69743451707db93e57b883cbfd9c6f5f2290 Mon Sep 17 00:00:00 2001 From: Roberto Rosmaninho Date: Mon, 24 Apr 2023 18:36:23 -0300 Subject: [PATCH 4/5] Implementing `hook_KEQUAL_ne` and `hook_BOOL_eq` in C++ and deleting equality.ll --- runtime/CMakeLists.txt | 1 - runtime/collections/kelemle.cpp | 9 ++++++++ runtime/equality.ll | 38 --------------------------------- 3 files changed, 9 insertions(+), 39 deletions(-) delete mode 100644 runtime/equality.ll diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index b8d4827fe..87c0fb24d 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -3,7 +3,6 @@ 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(equality.ll ${CMAKE_CURRENT_BINARY_DIR} @ONLY) configure_file(finish_rewriting.ll ${CMAKE_CURRENT_BINARY_DIR} @ONLY) configure_file(fresh.ll ${CMAKE_CURRENT_BINARY_DIR} @ONLY) configure_file(getTag.ll ${CMAKE_CURRENT_BINARY_DIR} @ONLY) diff --git a/runtime/collections/kelemle.cpp b/runtime/collections/kelemle.cpp index ce0830b99..069d43d99 100644 --- a/runtime/collections/kelemle.cpp +++ b/runtime/collections/kelemle.cpp @@ -213,4 +213,13 @@ bool hook_KEQUAL_lt(block *arg1, block *arg2) { } } } + +bool hook_KEQUAL_ne(block *arg1, block *arg2) { + return !hook_KEQUAL_eq(arg1, arg2); +} + +bool hook_BOOL_eq(bool arg1, bool arg2) { + return arg1 == arg2; +} + } diff --git a/runtime/equality.ll b/runtime/equality.ll deleted file mode 100644 index 384772485..000000000 --- a/runtime/equality.ll +++ /dev/null @@ -1,38 +0,0 @@ -target datalayout = "@BACKEND_TARGET_DATALAYOUT@" -target triple = "@BACKEND_TARGET_TRIPLE@" - -%blockheader = type { i64 } -%block = type { %blockheader, [0 x i64 *] } ; 16-bit layout, 8-bit length, 32-bit tag, children -%map = type { i8 *, i64 } ; immer::map -%set = type { i8 *, i64 } ; immer::set -%list = type { i64, i32, i8 *, i8 * } ; immer::flex_vector -%mpz = type { i32, i32, i64 * } ; mpz_t -%floating = type { i64, { i64, i32, i64, i64 * } } ; exp, mpfr_t -%layoutitem = type { i64, i16 } -%layout = type { i8, %layoutitem* } - -declare i32 @memcmp(i8* %ptr1, i8* %ptr2, i64 %num) -declare void @abort() #0 -declare %layout* @getLayoutData(i16) - -declare i1 @hook_MAP_eq(%map*, %map*) -declare i1 @hook_LIST_eq(%list*, %list*) -declare i1 @hook_SET_eq(%set*, %set*) -declare i1 @hook_INT_eq(%mpz*, %mpz*) -declare i1 @hook_FLOAT_trueeq(%floating*, %floating*) -declare i1 @hook_STRING_eq(%block*, %block*) -declare i1 @hook_KEQUAL_eq(%block* %arg1, %block* %arg2) - -define i1 @hook_KEQUAL_ne(%block* %arg1, %block* %arg2) { - %eq = call i1 @hook_KEQUAL_eq(%block* %arg1, %block* %arg2) - %ne = xor i1 %eq, 1 - ret i1 %ne -} - -define i1 @hook_BOOL_eq(i1 %arg1, i1 %arg2) #1 { - %eq = icmp eq i1 %arg1, %arg2 - ret i1 %eq -} - -attributes #0 = { noreturn } -attributes #1 = { alwaysinline } From d65a6e135b2b243c9a87352e9f6fafbd76f38ee8 Mon Sep 17 00:00:00 2001 From: Roberto Rosmaninho Date: Mon, 24 Apr 2023 18:38:50 -0300 Subject: [PATCH 5/5] Fix format check --- runtime/collections/kelemle.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/collections/kelemle.cpp b/runtime/collections/kelemle.cpp index 069d43d99..420f0895d 100644 --- a/runtime/collections/kelemle.cpp +++ b/runtime/collections/kelemle.cpp @@ -221,5 +221,4 @@ bool hook_KEQUAL_ne(block *arg1, block *arg2) { bool hook_BOOL_eq(bool arg1, bool arg2) { return arg1 == arg2; } - }