4
4
#include " kllvm/ast/AST.h"
5
5
#include " kllvm/codegen/Decision.h"
6
6
#include " kllvm/codegen/DecisionParser.h"
7
+ #include " kllvm/codegen/Options.h"
7
8
#include " kllvm/codegen/Util.h"
8
9
9
10
#include " llvm/IR/Instructions.h"
10
11
12
+ #include < fmt/format.h>
13
+
11
14
#include < map>
12
15
#include < tuple>
13
16
@@ -21,31 +24,58 @@ class proof_event {
21
24
22
25
/*
23
26
* Load the boolean flag that controls whether proof hint output is enabled or
24
- * not, then create a branch at the end of this basic block depending on the
25
- * result.
27
+ * not, then create a branch at the specified location depending on the
28
+ * result. The location can be before a given instruction or at the end of a
29
+ * given basic block.
26
30
*
27
31
* Returns a pair of blocks [proof enabled, merge]; the first of these is
28
32
* intended for self-contained behaviour only relevant in proof output mode,
29
33
* while the second is for the continuation of the interpreter's previous
30
34
* behaviour.
31
35
*/
36
+ template <typename Location>
32
37
std::pair<llvm::BasicBlock *, llvm::BasicBlock *>
33
- proof_branch (std::string const &label, llvm::BasicBlock *insert_at_end);
34
- std::pair<llvm::BasicBlock *, llvm::BasicBlock *>
35
- proof_branch (std::string const &label, llvm::Instruction *insert_before);
38
+ proof_branch (std::string const &label, Location *insert_loc);
39
+
40
+ /*
41
+ * Return the parent function of the given location.
42
+
43
+ * Template specializations for llvm::Instruction and llvm::BasicBlock.
44
+ */
45
+ template <typename Location>
46
+ llvm::Function *get_parent_function (Location *loc);
47
+
48
+ /*
49
+ * Return the parent basic block of the given location.
50
+
51
+ * Template specializations for llvm::Instruction and llvm::BasicBlock.
52
+ */
53
+ template <typename Location>
54
+ llvm::BasicBlock *get_parent_block (Location *loc);
55
+
56
+ /*
57
+ * If the given location is an Instruction, this method moves the instruction
58
+ * to the merge block.
59
+ * If the given location is a BasicBlock, this method simply emits a no-op
60
+ * instruction to the merge block.
61
+
62
+ * Template specializations for llvm::Instruction and llvm::BasicBlock.
63
+ */
64
+ template <typename Location>
65
+ void fix_insert_loc (Location *loc, llvm::BasicBlock *merge_block);
36
66
37
67
/*
38
68
* Set up a standard event prelude by creating a pair of basic blocks for the
39
69
* proof output and continuation, then loading the output filename from its
40
- * global.
70
+ * global. The location for the prelude can be before a given instruction or
71
+ * at the end of a given basic block.
41
72
*
42
73
* Returns a triple [proof enabled, merge, proof_writer]; see `proofBranch`
43
74
* and `emitGetOutputFileName`.
44
75
*/
76
+ template <typename Location>
45
77
std::tuple<llvm::BasicBlock *, llvm::BasicBlock *, llvm::Value *>
46
- event_prelude (std::string const &label, llvm::BasicBlock *insert_at_end);
47
- std::tuple<llvm::BasicBlock *, llvm::BasicBlock *, llvm::Value *>
48
- event_prelude (std::string const &label, llvm::Instruction *insert_before);
78
+ event_prelude (std::string const &label, Location *insert_loc);
49
79
50
80
/*
51
81
* Set up a check of whether a new proof hint chunk should be started. The
@@ -239,9 +269,9 @@ class proof_event {
239
269
[[nodiscard]] llvm::BasicBlock *pattern_matching_failure (
240
270
kore_composite_pattern const &pattern, llvm::BasicBlock *current_block);
241
271
242
- [[nodiscard]] llvm::BasicBlock * function_exit (
243
- uint64_t ordinal, bool is_tail, llvm::Instruction *insert_before,
244
- llvm::BasicBlock *current_block );
272
+ template < typename Location>
273
+ [[nodiscard]] llvm::BasicBlock *
274
+ function_exit ( uint64_t ordinal, bool is_tail, Location *insert_loc );
245
275
246
276
proof_event (kore_definition *definition, llvm::Module *module )
247
277
: definition_(definition)
@@ -251,4 +281,57 @@ class proof_event {
251
281
252
282
} // namespace kllvm
253
283
284
+ // ===----------------------------------------------------------------------===//
285
+ // Implementation for method templates
286
+ // ===----------------------------------------------------------------------===//
287
+
288
+ template <typename Location>
289
+ std::pair<llvm::BasicBlock *, llvm::BasicBlock *>
290
+ kllvm::proof_event::proof_branch (
291
+ std::string const &label, Location *insert_loc) {
292
+ auto *i1_ty = llvm::Type::getInt1Ty (ctx_);
293
+
294
+ auto *proof_output_flag = module_->getOrInsertGlobal (" proof_output" , i1_ty);
295
+ auto *proof_output = new llvm::LoadInst (
296
+ i1_ty, proof_output_flag, " proof_output" , insert_loc);
297
+
298
+ auto *f = get_parent_function (insert_loc);
299
+ auto *true_block
300
+ = llvm::BasicBlock::Create (ctx_, fmt::format (" if_{}" , label), f);
301
+ auto *merge_block
302
+ = llvm::BasicBlock::Create (ctx_, fmt::format (" tail_{}" , label), f);
303
+
304
+ llvm::BranchInst::Create (true_block, merge_block, proof_output, insert_loc);
305
+
306
+ fix_insert_loc (insert_loc, merge_block);
307
+
308
+ return {true_block, merge_block};
309
+ }
310
+
311
+ template <typename Location>
312
+ std::tuple<llvm::BasicBlock *, llvm::BasicBlock *, llvm::Value *>
313
+ kllvm::proof_event::event_prelude (
314
+ std::string const &label, Location *insert_loc) {
315
+ auto [true_block, merge_block] = proof_branch (label, insert_loc);
316
+ return {true_block, merge_block, emit_get_proof_trace_writer (true_block)};
317
+ }
318
+
319
+ template <typename Location>
320
+ llvm::BasicBlock *kllvm::proof_event::function_exit (
321
+ uint64_t ordinal, bool is_tail, Location *insert_loc) {
322
+
323
+ if (!proof_hint_instrumentation) {
324
+ return get_parent_block (insert_loc);
325
+ }
326
+
327
+ auto [true_block, merge_block, proof_writer]
328
+ = event_prelude (" function_exit" , insert_loc);
329
+
330
+ emit_write_function_exit (proof_writer, ordinal, is_tail, true_block);
331
+
332
+ llvm::BranchInst::Create (merge_block, true_block);
333
+
334
+ return merge_block;
335
+ }
336
+
254
337
#endif // PROOF_EVENT_H
0 commit comments