Skip to content

Commit 8c77e21

Browse files
authored
Add --mutable-bytes flag to enable possibly unsound optimizations (#962)
This PR adds a flag to `llvm-kompile` that enables semantics used by the LLVM backend that are unsound in certain scenarios, but are useful for performance (making objects of sort `Bytes` copy-on-write rather than mutable). The numerous edge cases from my initial attempt to fix this issue in #950 are retained as test cases here. Fixes #930 Blocked until we have propagated runtimeverification/k#3934 appropriately to downstream semantics.
1 parent 2fdcb59 commit 8c77e21

37 files changed

+16160
-25
lines changed

bin/llvm-kompile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ Options:
3434
be called from kompile. Only meaningful in "c" mode.
3535
-fno-omit-frame-pointer Keep the frame pointer in compiled code for debugging purposes.
3636
--proof-hint-instrumentation Enable instrumentation for generation of proof hints.
37+
--mutable-bytes Use the faster, unsound (mutable) semantics for objects of sort
38+
Bytes at run time, rather than the slower, sound
39+
(immutable) that are enabled by default.
3740
-O[0123] Set the optimization level for code generation.
3841
3942
Any option not listed above will be passed through to clang; use '--' to
@@ -167,6 +170,10 @@ while [[ $# -gt 0 ]]; do
167170
codegen_flags+=("--proof-hint-instrumentation")
168171
shift
169172
;;
173+
--mutable-bytes)
174+
codegen_flags+=("--mutable-bytes")
175+
shift
176+
;;
170177
-O*)
171178
codegen_flags+=("$1")
172179
kompile_clang_flags+=("$1")

bindings/c/include/kllvm-c/kllvm-c.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ void kore_symbol_add_formal_argument(kore_symbol *, kore_sort const *);
158158
void kllvm_init(void);
159159
void kllvm_free_all_memory(void);
160160

161+
/* Sort-specific functions */
162+
163+
bool kllvm_mutable_bytes_enabled(void);
164+
161165
#ifdef __cplusplus
162166
}
163167
#endif

bindings/c/lib.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ auto managed(kore_symbol *ptr) {
6767
*/
6868

6969
extern "C" {
70-
void initStaticObjects(void);
71-
void freeAllKoreMem(void);
70+
void initStaticObjects();
71+
void freeAllKoreMem();
72+
bool hook_BYTES_mutableBytesEnabled();
7273
}
7374

7475
extern "C" {
@@ -426,6 +427,10 @@ void kllvm_init(void) {
426427
void kllvm_free_all_memory(void) {
427428
freeAllKoreMem();
428429
}
430+
431+
bool kllvm_mutable_bytes_enabled(void) {
432+
return hook_BYTES_mutableBytesEnabled();
433+
}
429434
}
430435

431436
namespace {

include/kllvm/codegen/CreateTerm.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,6 @@ std::string escape(std::string const &str);
8282
llvm modules in the llvm backend. */
8383
std::unique_ptr<llvm::Module>
8484
newModule(std::string const &name, llvm::LLVMContext &Context);
85-
void addKompiledDirSymbol(
86-
llvm::LLVMContext &Context, std::string const &dir, llvm::Module *mod,
87-
bool debug);
8885

8986
llvm::StructType *getBlockType(
9087
llvm::Module *Module, KOREDefinition *definition, KORESymbol const *symbol);

include/kllvm/codegen/Metadata.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef KLLVM_CODEGEN_H
2+
#define KLLVM_CODEGEN_H
3+
4+
#include <llvm/IR/LLVMContext.h>
5+
#include <llvm/IR/Module.h>
6+
7+
#include <string>
8+
9+
namespace kllvm {
10+
11+
void addKompiledDirSymbol(
12+
llvm::Module &mod, std::string const &dir, bool debug);
13+
14+
void addMutableBytesFlag(llvm::Module &mod, bool enabled, bool debug);
15+
16+
} // namespace kllvm
17+
18+
#endif

lib/codegen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ add_library(Codegen
66
Decision.cpp
77
DecisionParser.cpp
88
EmitConfigParser.cpp
9+
Metadata.cpp
910
Options.cpp
1011
ProofEvent.cpp
1112
Util.cpp

lib/codegen/CreateTerm.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -129,23 +129,6 @@ newModule(std::string const &name, llvm::LLVMContext &Context) {
129129
return mod;
130130
}
131131

132-
static std::string KOMPILED_DIR = "kompiled_directory";
133-
134-
void addKompiledDirSymbol(
135-
llvm::LLVMContext &Context, std::string const &dir, llvm::Module *mod,
136-
bool debug) {
137-
auto *Str = llvm::ConstantDataArray::getString(Context, dir, true);
138-
auto *global = mod->getOrInsertGlobal(KOMPILED_DIR, Str->getType());
139-
auto *globalVar = llvm::cast<llvm::GlobalVariable>(global);
140-
if (!globalVar->hasInitializer()) {
141-
globalVar->setInitializer(Str);
142-
}
143-
144-
if (debug) {
145-
initDebugGlobal(KOMPILED_DIR, getCharDebugType(), globalVar);
146-
}
147-
}
148-
149132
std::string MAP_STRUCT = "map";
150133
std::string RANGEMAP_STRUCT = "rangemap";
151134
std::string LIST_STRUCT = "list";

lib/codegen/Metadata.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include <kllvm/codegen/Debug.h>
2+
#include <kllvm/codegen/Metadata.h>
3+
4+
#include <llvm/IR/Constants.h>
5+
#include <llvm/IR/LLVMContext.h>
6+
#include <llvm/IR/Module.h>
7+
#include <llvm/IR/Type.h>
8+
9+
namespace kllvm {
10+
11+
static std::string KOMPILED_DIR = "kompiled_directory";
12+
static std::string STRICT_BYTES = "enable_mutable_bytes";
13+
14+
void addKompiledDirSymbol(
15+
llvm::Module &mod, std::string const &dir, bool debug) {
16+
auto &ctx = mod.getContext();
17+
18+
auto *str = llvm::ConstantDataArray::getString(ctx, dir, true);
19+
20+
auto *global = mod.getOrInsertGlobal(KOMPILED_DIR, str->getType());
21+
auto *global_var = llvm::cast<llvm::GlobalVariable>(global);
22+
23+
if (!global_var->hasInitializer()) {
24+
global_var->setInitializer(str);
25+
}
26+
27+
if (debug) {
28+
initDebugGlobal(KOMPILED_DIR, getCharDebugType(), global_var);
29+
}
30+
}
31+
32+
void addMutableBytesFlag(llvm::Module &mod, bool enabled, bool debug) {
33+
auto &ctx = mod.getContext();
34+
35+
auto *i1_ty = llvm::Type::getInt1Ty(ctx);
36+
auto *enabled_cst = llvm::ConstantInt::getBool(ctx, enabled);
37+
38+
auto *global = mod.getOrInsertGlobal(STRICT_BYTES, i1_ty);
39+
auto *global_var = llvm::cast<llvm::GlobalVariable>(global);
40+
41+
if (!global_var->hasInitializer()) {
42+
global_var->setInitializer(enabled_cst);
43+
}
44+
45+
if (debug) {
46+
initDebugGlobal(STRICT_BYTES, getBoolDebugType(), global_var);
47+
}
48+
}
49+
50+
} // namespace kllvm

runtime/strings/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
add_library(strings STATIC
22
strings.cpp
33
bytes.cpp
4+
copy_on_write.cpp
45
)
56

67
target_link_libraries(strings

runtime/strings/bytes.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
#include <cstring>
55
#include <gmp.h>
66
#include <stdexcept>
7+
#include <unordered_set>
78

89
#include "runtime/alloc.h"
910
#include "runtime/header.h"
1011

12+
void copy_if_needed(SortBytes &b);
13+
1114
extern "C" {
1215

1316
#undef get_ui
@@ -153,6 +156,8 @@ SortInt hook_BYTES_get(SortBytes b, SortInt off) {
153156
}
154157

155158
SortBytes hook_BYTES_update(SortBytes b, SortInt off, SortInt val) {
159+
copy_if_needed(b);
160+
156161
unsigned long off_long = get_ui(off);
157162
if (off_long >= len(b)) {
158163
KLLVM_HOOK_INVALID_ARGUMENT(
@@ -168,6 +173,8 @@ SortBytes hook_BYTES_update(SortBytes b, SortInt off, SortInt val) {
168173
}
169174

170175
SortBytes hook_BYTES_replaceAt(SortBytes b, SortInt start, SortBytes b2) {
176+
copy_if_needed(b);
177+
171178
unsigned long start_long = get_ui(start);
172179
if (start_long + len(b2) > len(b)) {
173180
KLLVM_HOOK_INVALID_ARGUMENT(
@@ -180,6 +187,8 @@ SortBytes hook_BYTES_replaceAt(SortBytes b, SortInt start, SortBytes b2) {
180187

181188
SortBytes
182189
hook_BYTES_memset(SortBytes b, SortInt start, SortInt count, SortInt value) {
190+
copy_if_needed(b);
191+
183192
uint64_t ustart = get_ui(start);
184193
uint64_t ucount = get_ui(count);
185194
uint64_t uend = ustart + ucount;
@@ -244,6 +253,7 @@ SortBytes hook_BYTES_padLeft(SortBytes b, SortInt length, SortInt v) {
244253
}
245254

246255
SortBytes hook_BYTES_reverse(SortBytes b) {
256+
copy_if_needed(b);
247257
std::reverse(b->data, b->data + len(b));
248258
return b;
249259
}

runtime/strings/copy_on_write.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <runtime/header.h>
2+
3+
extern "C" bool enable_mutable_bytes;
4+
5+
namespace {
6+
7+
SortBytes copy_bytes(SortBytes b) {
8+
auto new_len = len(b);
9+
auto *ret = static_cast<string *>(koreAllocToken(sizeof(string) + new_len));
10+
init_with_len(ret, new_len);
11+
memcpy(&(ret->data), &(b->data), new_len * sizeof(char));
12+
return ret;
13+
}
14+
15+
} // namespace
16+
17+
extern "C" bool hook_BYTES_mutableBytesEnabled() {
18+
return enable_mutable_bytes;
19+
}
20+
21+
void copy_if_needed(SortBytes &b) {
22+
if (!hook_BYTES_mutableBytesEnabled()) {
23+
b = copy_bytes(b);
24+
}
25+
}

test/c/Inputs/api.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct kllvm_c_api load_c_api(char const *path) {
6262
API_FUNCTION(kore_symbol_add_formal_argument);
6363
API_FUNCTION(kllvm_init);
6464
API_FUNCTION(kllvm_free_all_memory);
65+
API_FUNCTION(kllvm_mutable_bytes_enabled);
6566

6667
return api;
6768
}

test/c/Inputs/api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct kllvm_c_api {
5252
void (*kore_symbol_add_formal_argument)(kore_symbol *, kore_sort const *);
5353
void (*kllvm_init)(void);
5454
void (*kllvm_free_all_memory)(void);
55+
bool (*kllvm_mutable_bytes_enabled)(void);
5556
};
5657

5758
struct kllvm_c_api load_c_api(char const *);

0 commit comments

Comments
 (0)