Skip to content

Commit 6757d77

Browse files
Introducing Ordinal KORE Attribute (#1053)
Closes Pi-Squared-Inc/pi2#1432 This PR introduces a new attribute specific to the LLVM Backend. It includes the `ordinal` attribute to the KORE definition when `preprocess` is called after parsing a definition. The content of the attribute is a `string_sort` with the value of the computed `axiom_ordinal`. A new C++ tool is planned to consume this feature instead of reading a definition with a bash script. The main intention of this feature is to expose this information to the Python bindings to be used in Proof Hints integration tests.
1 parent bf9b0cc commit 6757d77

File tree

10 files changed

+78
-28
lines changed

10 files changed

+78
-28
lines changed

bindings/python/ast.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ void bind_ast(py::module_ &m) {
218218
std::shared_ptr<kore_composite_pattern> const &arg) {
219219
decl.attributes().add(arg);
220220
})
221+
.def("preprocess", &kore_definition::preprocess)
222+
.def("get_axiom_by_ordinal", &kore_definition::get_axiom_by_ordinal)
221223
.def_property_readonly("attributes", [](kore_definition &decl) {
222224
return decl.attributes().underlying();
223225
});

include/kllvm/ast/AST.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,9 +1023,9 @@ class kore_definition {
10231023
[[nodiscard]] std::list<kore_axiom_declaration *> const &get_axioms() const {
10241024
return axioms_;
10251025
}
1026-
[[nodiscard]] kore_axiom_declaration *
1026+
[[nodiscard]] kore_axiom_declaration const &
10271027
get_axiom_by_ordinal(size_t ordinal) const {
1028-
return ordinals_.at(ordinal);
1028+
return *ordinals_.at(ordinal);
10291029
}
10301030
[[nodiscard]] kore_symbolStringMapType const &get_fresh_functions() const {
10311031
return fresh_functions_;

include/kllvm/ast/attribute_set.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class attribute_set {
5858
MacroRec,
5959
Nat,
6060
NonExecutable,
61+
Ordinal,
6162
Priorities,
6263
Priority,
6364
Right,

include/kllvm/codegen/ProofEvent.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class proof_event {
104104
llvm::BasicBlock *current_block);
105105

106106
[[nodiscard]] llvm::BasicBlock *rewrite_event_pre(
107-
kore_axiom_declaration *axiom, uint64_t arity,
107+
kore_axiom_declaration const &axiom, uint64_t arity,
108108
std::map<std::string, kore_variable_pattern *> vars,
109109
llvm::StringMap<llvm::Value *> const &subst,
110110
llvm::BasicBlock *current_block);
@@ -121,11 +121,11 @@ class proof_event {
121121
function_event_post(llvm::BasicBlock *current_block);
122122

123123
[[nodiscard]] llvm::BasicBlock *side_condition_event_pre(
124-
kore_axiom_declaration *axiom, std::vector<llvm::Value *> const &args,
125-
llvm::BasicBlock *current_block);
124+
kore_axiom_declaration const &axiom,
125+
std::vector<llvm::Value *> const &args, llvm::BasicBlock *current_block);
126126

127127
[[nodiscard]] llvm::BasicBlock *side_condition_event_post(
128-
kore_axiom_declaration *axiom, llvm::Value *check_result,
128+
kore_axiom_declaration const &axiom, llvm::Value *check_result,
129129
llvm::BasicBlock *current_block);
130130

131131
proof_event(kore_definition *definition, llvm::Module *module)

lib/ast/attribute_set.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ std::unordered_map<attribute_set::key, std::string> const &attribute_table() {
3535
{attribute_set::key::MacroRec, "macro-rec"},
3636
{attribute_set::key::Nat, "nat"},
3737
{attribute_set::key::NonExecutable, "non-executable"},
38+
{attribute_set::key::Ordinal, "ordinal"},
3839
{attribute_set::key::Priorities, "priorities"},
3940
{attribute_set::key::Priority, "priority"},
4041
{attribute_set::key::Right, "right"},

lib/ast/definition.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ void kore_definition::preprocess() {
190190
} else {
191191
++iter;
192192
}
193+
auto ordinal_att = kore_composite_pattern::create("ordinal");
194+
auto pattern
195+
= kore_string_pattern::create(std::to_string(axiom->get_ordinal()));
196+
ordinal_att->add_argument(std::move(pattern));
197+
axiom->attributes().add(std::move(ordinal_att));
193198
}
194199
for (auto &module : modules_) {
195200
auto const &declarations = module->get_declarations();

lib/codegen/Decision.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,7 @@ void function_node::codegen(decision *d) {
431431
if (is_side_condition) {
432432
proof_event p(d->definition_, d->module_);
433433
size_t ordinal = std::stoll(function_.substr(15));
434-
kore_axiom_declaration *axiom
435-
= d->definition_->get_axiom_by_ordinal(ordinal);
434+
auto axiom = d->definition_->get_axiom_by_ordinal(ordinal);
436435
d->current_block_
437436
= p.side_condition_event_pre(axiom, args, d->current_block_);
438437
}
@@ -447,8 +446,7 @@ void function_node::codegen(decision *d) {
447446
if (is_side_condition) {
448447
proof_event p(d->definition_, d->module_);
449448
size_t ordinal = std::stoll(function_.substr(15));
450-
kore_axiom_declaration *axiom
451-
= d->definition_->get_axiom_by_ordinal(ordinal);
449+
auto axiom = d->definition_->get_axiom_by_ordinal(ordinal);
452450
d->current_block_
453451
= p.side_condition_event_post(axiom, call, d->current_block_);
454452
}
@@ -461,11 +459,10 @@ void function_node::codegen(decision *d) {
461459
+ function_.substr(function_.find_first_of('_', 5) + 1);
462460
} else if (is_side_condition) {
463461
size_t ordinal = std::stoll(function_.substr(15));
464-
kore_axiom_declaration *axiom
465-
= d->definition_->get_axiom_by_ordinal(ordinal);
466-
if (axiom->attributes().contains(attribute_set::key::Label)) {
462+
auto axiom = d->definition_->get_axiom_by_ordinal(ordinal);
463+
if (axiom.attributes().contains(attribute_set::key::Label)) {
467464
debug_name
468-
= axiom->attributes().get_string(attribute_set::key::Label) + ".sc";
465+
= axiom.attributes().get_string(attribute_set::key::Label) + ".sc";
469466
}
470467
}
471468
std::vector<llvm::Value *> function_args;
@@ -595,13 +592,13 @@ void leaf_node::codegen(decision *d) {
595592
// retrieve the corresponding ordinal we drop the apply_rule_ prefix.
596593
auto ordinal = std::stoll(name_.substr(11));
597594
auto arity = apply_rule->arg_end() - apply_rule->arg_begin();
598-
auto *axiom = d->definition_->get_axiom_by_ordinal(ordinal);
595+
auto axiom = d->definition_->get_axiom_by_ordinal(ordinal);
599596

600597
auto vars = std::map<std::string, kore_variable_pattern *>{};
601-
for (kore_pattern *lhs : axiom->get_left_hand_side()) {
598+
for (kore_pattern *lhs : axiom.get_left_hand_side()) {
602599
lhs->mark_variables(vars);
603600
}
604-
axiom->get_right_hand_side()->mark_variables(vars);
601+
axiom.get_right_hand_side()->mark_variables(vars);
605602

606603
auto subst = llvm::StringMap<llvm::Value *>{};
607604
auto i = 0;

lib/codegen/ProofEvent.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ llvm::BasicBlock *proof_event::argument(
230230
*/
231231

232232
llvm::BasicBlock *proof_event::rewrite_event_pre(
233-
kore_axiom_declaration *axiom, uint64_t arity,
233+
kore_axiom_declaration const &axiom, uint64_t arity,
234234
std::map<std::string, kore_variable_pattern *> vars,
235235
llvm::StringMap<llvm::Value *> const &subst,
236236
llvm::BasicBlock *current_block) {
@@ -242,7 +242,7 @@ llvm::BasicBlock *proof_event::rewrite_event_pre(
242242
= event_prelude("rewrite_pre", current_block);
243243

244244
emit_write_uint64(outputFile, detail::word(0x22), true_block);
245-
emit_write_uint64(outputFile, axiom->get_ordinal(), true_block);
245+
emit_write_uint64(outputFile, axiom.get_ordinal(), true_block);
246246
emit_write_uint64(outputFile, arity, true_block);
247247
for (auto entry = subst.begin(); entry != subst.end(); ++entry) {
248248
auto key = entry->getKey();
@@ -321,7 +321,7 @@ proof_event::function_event_post(llvm::BasicBlock *current_block) {
321321
}
322322

323323
llvm::BasicBlock *proof_event::side_condition_event_pre(
324-
kore_axiom_declaration *axiom, std::vector<llvm::Value *> const &args,
324+
kore_axiom_declaration const &axiom, std::vector<llvm::Value *> const &args,
325325
llvm::BasicBlock *current_block) {
326326
if (!proof_hint_instrumentation) {
327327
return current_block;
@@ -330,14 +330,14 @@ llvm::BasicBlock *proof_event::side_condition_event_pre(
330330
auto [true_block, merge_block, outputFile]
331331
= event_prelude("side_condition_pre", current_block);
332332

333-
size_t ordinal = axiom->get_ordinal();
333+
size_t ordinal = axiom.get_ordinal();
334334
size_t arity = args.size();
335335

336336
emit_write_uint64(outputFile, detail::word(0xEE), true_block);
337337
emit_write_uint64(outputFile, ordinal, true_block);
338338
emit_write_uint64(outputFile, arity, true_block);
339339

340-
kore_pattern *pattern = axiom->get_requires();
340+
kore_pattern *pattern = axiom.get_requires();
341341
std::map<std::string, kore_variable_pattern *> vars;
342342
pattern->mark_variables(vars);
343343

@@ -360,7 +360,7 @@ llvm::BasicBlock *proof_event::side_condition_event_pre(
360360
}
361361

362362
llvm::BasicBlock *proof_event::side_condition_event_post(
363-
kore_axiom_declaration *axiom, llvm::Value *check_result,
363+
kore_axiom_declaration const &axiom, llvm::Value *check_result,
364364
llvm::BasicBlock *current_block) {
365365
if (!proof_hint_instrumentation) {
366366
return current_block;
@@ -369,7 +369,7 @@ llvm::BasicBlock *proof_event::side_condition_event_post(
369369
auto [true_block, merge_block, outputFile]
370370
= event_prelude("side_condition_post", current_block);
371371

372-
size_t ordinal = axiom->get_ordinal();
372+
size_t ordinal = axiom.get_ordinal();
373373

374374
emit_write_uint64(outputFile, detail::word(0x33), true_block);
375375
emit_write_uint64(outputFile, ordinal, true_block);

test/python/test_proof_trace.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515

1616

1717
class TestParser(unittest.TestCase):
18+
def get_pattern_from_ordinal(self, definition_text, ordinal):
19+
axiom_ordinal = 'ordinal{}("' + str(ordinal) + '")'
20+
line = next((i+1 for i, l in enumerate(definition_text) if axiom_ordinal in l), None)
21+
return definition_text[line-1].strip()
1822

1923
def test_file(self):
2024
binary_proof_trace = os.path.join(
@@ -24,6 +28,18 @@ def test_file(self):
2428
os.path.dirname(os.path.realpath(__file__)),
2529
"Output", "test_proof_trace.py.tmp", "header.bin")
2630
header = kllvm.prooftrace.kore_header(binary_header_path)
31+
32+
definition_file = os.path.join(
33+
os.path.dirname(os.path.realpath(__file__)),
34+
"Inputs", "proof-trace.kore")
35+
36+
with open(definition_file, 'rb') as f:
37+
data = f.read()
38+
definition = kllvm.parser.Parser.from_string(data).definition()
39+
40+
definition.preprocess()
41+
definition_text = repr(definition).split("\n")
42+
2743
with open(binary_proof_trace, 'rb') as f:
2844
data = f.read()
2945
trace = kllvm.prooftrace.llvm_rewrite_trace.parse(data, header)
@@ -37,11 +53,17 @@ def test_file(self):
3753

3854
# check that the first event is the rewrite a() => b()
3955
self.assertTrue(trace.trace[0].is_step_event())
40-
self.assertEqual(trace.trace[0].step_event.rule_ordinal, 95)
56+
rule_ordinal = trace.trace[0].step_event.rule_ordinal
57+
axiom = repr(definition.get_axiom_by_ordinal(rule_ordinal))
58+
axiom_expected = self.get_pattern_from_ordinal(definition_text, rule_ordinal)
59+
self.assertEqual(axiom, axiom_expected)
4160

4261
# check that the second event is the rewrite b() => c()
4362
self.assertTrue(trace.trace[1].is_step_event())
44-
self.assertEqual(trace.trace[1].step_event.rule_ordinal, 96)
63+
rule_ordinal = trace.trace[1].step_event.rule_ordinal
64+
axiom = repr(definition.get_axiom_by_ordinal(rule_ordinal))
65+
axiom_expected = self.get_pattern_from_ordinal(definition_text, rule_ordinal)
66+
self.assertEqual(axiom, axiom_expected)
4567

4668
# check that the third event is a configuration
4769
self.assertTrue(trace.trace[2].is_kore_pattern())

test/python/test_proof_trace_slow.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515

1616

1717
class TestParser(unittest.TestCase):
18+
def get_pattern_from_ordinal(self, definition_text, ordinal):
19+
axiom_ordinal = 'ordinal{}("' + str(ordinal) + '")'
20+
line = next((i+1 for i, l in enumerate(definition_text) if axiom_ordinal in l), None)
21+
return definition_text[line-1].strip()
1822

1923
def test_file(self):
2024
binary_proof_trace = os.path.join(
@@ -24,6 +28,18 @@ def test_file(self):
2428
os.path.dirname(os.path.realpath(__file__)),
2529
"Output", "test_proof_trace_slow.py.tmp", "header.bin")
2630
header = kllvm.prooftrace.kore_header(binary_header_path)
31+
32+
definition_file = os.path.join(
33+
os.path.dirname(os.path.realpath(__file__)),
34+
"Inputs", "proof-trace.kore")
35+
36+
with open(definition_file, 'rb') as f:
37+
data = f.read()
38+
definition = kllvm.parser.Parser.from_string(data).definition()
39+
40+
definition.preprocess()
41+
definition_text = repr(definition).split("\n")
42+
2743
with open(binary_proof_trace, 'rb') as f:
2844
data = f.read()
2945
trace = kllvm.prooftrace.llvm_rewrite_trace.parse(data, header)
@@ -37,14 +53,20 @@ def test_file(self):
3753

3854
# check that the first event is the rewrite a() => b()
3955
self.assertTrue(trace.trace[0].is_step_event())
40-
self.assertEqual(trace.trace[0].step_event.rule_ordinal, 95)
56+
rule_ordinal = trace.trace[0].step_event.rule_ordinal
57+
axiom = repr(definition.get_axiom_by_ordinal(rule_ordinal))
58+
axiom_expected = self.get_pattern_from_ordinal(definition_text, rule_ordinal)
59+
self.assertEqual(axiom, axiom_expected)
4160

4261
# check that the second event is a configuration
4362
self.assertTrue(trace.trace[1].is_kore_pattern())
4463

4564
# check that the third event is the rewrite b() => c()
4665
self.assertTrue(trace.trace[2].is_step_event())
47-
self.assertEqual(trace.trace[2].step_event.rule_ordinal, 96)
66+
rule_ordinal = trace.trace[2].step_event.rule_ordinal
67+
axiom = repr(definition.get_axiom_by_ordinal(rule_ordinal))
68+
axiom_expected = self.get_pattern_from_ordinal(definition_text, rule_ordinal)
69+
self.assertEqual(axiom, axiom_expected)
4870

4971
# check that the fourth event is a configuration
5072
self.assertTrue(trace.trace[3].is_kore_pattern())

0 commit comments

Comments
 (0)