Line | Branch | Exec | Source |
---|---|---|---|
1 | #include <gyoji-analysis.hpp> | ||
2 | #include <stdio.h> | ||
3 | |||
4 | using namespace Gyoji::mir; | ||
5 | using namespace Gyoji::context; | ||
6 | using namespace Gyoji::analysis; | ||
7 | |||
8 | /** | ||
9 | * This class indicates an operation | ||
10 | * inside a basic block. The block | ||
11 | * is the ID of the basic block | ||
12 | * and operation is the index into | ||
13 | * that basic block indicating | ||
14 | * a specific operation. | ||
15 | */ | ||
16 | class BasicBlockOperation { | ||
17 | public: | ||
18 | BasicBlockOperation(size_t _blockid, size_t _operationid); | ||
19 | BasicBlockOperation(const BasicBlockOperation & _other); | ||
20 | ~BasicBlockOperation(); | ||
21 | size_t blockid; | ||
22 | size_t operationid; | ||
23 | }; | ||
24 | |||
25 | /** | ||
26 | * This class represents an edge in the control-flow | ||
27 | * graph with edges between operations and the 'next' | ||
28 | * operation in the graph. | ||
29 | */ | ||
30 | class CFGEdge { | ||
31 | public: | ||
32 | CFGEdge(const BasicBlockOperation & start, const BasicBlockOperation & end); | ||
33 | CFGEdge(const CFGEdge & _other); | ||
34 | ~CFGEdge(); | ||
35 | BasicBlockOperation start; | ||
36 | BasicBlockOperation end; | ||
37 | }; | ||
38 | /////////////////////////////// | ||
39 | // BasicBlockOperation | ||
40 | /////////////////////////////// | ||
41 | 724 | BasicBlockOperation::BasicBlockOperation(size_t _blockid, size_t _operationid) | |
42 | 724 | : blockid(_blockid) | |
43 | 724 | , operationid(_operationid) | |
44 | 724 | {} | |
45 | 1728 | BasicBlockOperation::BasicBlockOperation(const BasicBlockOperation & _other) | |
46 | 1728 | : blockid(_other.blockid) | |
47 | 1728 | , operationid(_other.operationid) | |
48 | 1728 | {} | |
49 | 2452 | BasicBlockOperation::~BasicBlockOperation() | |
50 | 2452 | {} | |
51 | /////////////////////////////// | ||
52 | // CFGEdge | ||
53 | /////////////////////////////// | ||
54 | 362 | CFGEdge::CFGEdge(const BasicBlockOperation & _start, const BasicBlockOperation & _end) | |
55 | 362 | : start(_start) | |
56 | 362 | , end(_end) | |
57 | 362 | {} | |
58 | 502 | CFGEdge::CFGEdge(const CFGEdge & _other) | |
59 | 502 | : start(_other.start) | |
60 | 502 | , end(_other.end) | |
61 | 502 | {} | |
62 | 864 | CFGEdge::~CFGEdge() | |
63 | 864 | {} | |
64 | |||
65 | /////////////////////////////// | ||
66 | // AnalysisPassBorrowChecker | ||
67 | /////////////////////////////// | ||
68 | 30 | AnalysisPassBorrowChecker::AnalysisPassBorrowChecker(CompilerContext & _compiler_context) | |
69 | 60 | : AnalysisPass(_compiler_context, "borrow checker") | |
70 | 30 | {} | |
71 | ✗ | AnalysisPassBorrowChecker::~AnalysisPassBorrowChecker() | |
72 | ✗ | {} | |
73 | |||
74 | void | ||
75 | 30 | AnalysisPassBorrowChecker::check(const MIR & mir) const | |
76 | { | ||
77 | // Here, we follow the basic plan of the 'Polonius' algorithm | ||
78 | // for borrow checking. | ||
79 | |||
80 |
2/2✓ Branch 7 taken 266 times.
✓ Branch 8 taken 30 times.
|
296 | for (const auto & function : mir.get_functions().get_functions()) { |
81 | 266 | check(*function); | |
82 | } | ||
83 | |||
84 | 30 | } | |
85 | |||
86 | 266 | void AnalysisPassBorrowChecker::check(const Function & function) const | |
87 | { | ||
88 | // We start with mapping the "edges" of the graph | ||
89 | // from the basic-blocks of the function. | ||
90 | 266 | const auto & blocks = function.get_blocks(); | |
91 | |||
92 | 266 | std::vector<CFGEdge> cfg_edges; | |
93 | |||
94 |
2/2✓ Branch 5 taken 362 times.
✓ Branch 6 taken 266 times.
|
628 | for (const auto & block_it : blocks) { |
95 | 362 | const BasicBlock & block = *block_it.second; | |
96 | 362 | const std::vector<Gyoji::owned<Operation>> & operations = block.get_operations(); | |
97 | |||
98 | // Each basic block must have at least one operation. | ||
99 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 362 times.
|
362 | if (operations.size() == 0) { |
100 | ✗ | get_compiler_context() | |
101 | ✗ | .get_errors() | |
102 | ✗ | .add_simple_error(function.get_source_ref(), | |
103 | "Compiler bug! Please report this message(borrow)", | ||
104 | ✗ | std::string("Function ") + function.get_name() + std::string(" found with empty Basic Block") | |
105 | ); | ||
106 | ✗ | break; | |
107 | } | ||
108 | |||
109 | // TODO: Finish the logic of | ||
110 | // tying blocks together in a graph | ||
111 | // by traversing it. | ||
112 | 362 | BasicBlockOperation startblock(block_it.first, 0); | |
113 | 362 | BasicBlockOperation endblock(block_it.first, 1); | |
114 | 362 | cfg_edges.push_back(CFGEdge(startblock, endblock)); | |
115 |
2/2✓ Branch 6 taken 3994 times.
✓ Branch 7 taken 362 times.
|
4356 | for (const auto & operation_ptr : block.get_operations()) { |
116 | 3994 | const Operation & operation = *operation_ptr; | |
117 | } | ||
118 | 362 | } | |
119 | |||
120 | // TODO: | ||
121 | // We need to finish the CFG above | ||
122 | // and also extract the 'loans', the 'regions', | ||
123 | // and the 'live/killed' status of each variable from the MIR. | ||
124 | |||
125 | // Finally, we perform the graph-traversal | ||
126 | // to solve this. It should mainly take the form of | ||
127 | // a Hornsat solver, I think. | ||
128 | 266 | } | |
129 |