compiler/
lib/
examples/
std/
arch/
char/
collections/
graph/
lang/
alloc/
ast/
gen/
bitset/
regalloc/
liveness/
assign.rad
11.7 KiB
flow.rad
4.1 KiB
liveness.rad
9.0 KiB
spill.rad
12.4 KiB
bitset.rad
4.6 KiB
data.rad
8.6 KiB
labels.rad
2.4 KiB
regalloc.rad
2.4 KiB
types.rad
594 B
il/
module/
parser/
resolver/
scanner/
alloc.rad
7.1 KiB
ast.rad
26.9 KiB
gen.rad
513 B
il.rad
20.4 KiB
lower.rad
321.7 KiB
module.rad
17.3 KiB
package.rad
1.3 KiB
parser.rad
92.2 KiB
resolver.rad
511.1 KiB
scanner.rad
17.9 KiB
sexpr.rad
6.7 KiB
strings.rad
2.2 KiB
types.rad
1.6 KiB
sys/
arch.rad
68 B
char.rad
855 B
collections.rad
39 B
fmt.rad
8.3 KiB
graph.rad
4.3 KiB
intrinsics.rad
467 B
io.rad
1.7 KiB
lang.rad
276 B
mem.rad
2.3 KiB
sys.rad
179 B
testing.rad
2.4 KiB
tests.rad
15.7 KiB
vec.rad
3.2 KiB
std.rad
299 B
scripts/
seed/
sublime/
test/
vim/
.gitignore
336 B
.gitsigners
112 B
CELL_PERMISSIONS
6.8 KiB
CONTRIBUTING
2.1 KiB
LICENSE
1.1 KiB
Makefile
5.4 KiB
README
2.5 KiB
STYLE
2.5 KiB
std.lib
1.5 KiB
std.lib.test
808 B
lib/std/lang/gen/regalloc/flow.rad
raw
| 1 | //! Owned control-flow topology for dataflow analysis. |
| 2 | |
| 3 | use std::graph; |
| 4 | use std::lang::alloc; |
| 5 | use std::lang::il::published; |
| 6 | |
| 7 | /// Zero-state owner for authority over one flow topology. |
| 8 | export record Permission {} |
| 9 | |
| 10 | /// Stable block identity and private successor storage. |
| 11 | export opaque record Block: 'storage + 'permission + Copy { |
| 12 | /// Graph capability identity. |
| 13 | token: graph::Node 'storage, |
| 14 | /// Block position in the function's dataflow tables. |
| 15 | index: u32, |
| 16 | /// Successors published when construction is complete. |
| 17 | links: &'storage cell 'permission &'storage [Block 'storage 'permission], |
| 18 | } |
| 19 | |
| 20 | /// Immutable topology whose storage belongs to the analysis session. |
| 21 | export opaque record Flow: 'storage + 'permission + Copy { |
| 22 | /// Shared authority for every block in the topology. |
| 23 | frozen: graph::Frozen 'storage, |
| 24 | /// Stable block handles in function order. |
| 25 | blocks: &'storage [Block 'storage 'permission], |
| 26 | } |
| 27 | |
| 28 | /// Copy published successor topology into session-owned graph storage. |
| 29 | export fn snapshot 'input 'storage 'permission ( |
| 30 | blocks: &[published::Block 'input], |
| 31 | storage: &Session 'storage, |
| 32 | permission: &'permission mut Permission, |
| 33 | ) -> Flow 'storage 'permission throws (alloc::AllocError) { |
| 34 | let mut builder = try graph::new(storage); |
| 35 | let none: [Block 'storage 'permission; 0] = []; |
| 36 | let empty: &'storage [Block 'storage 'permission] = try storage.copy(&none[..]); |
| 37 | if blocks.len == 0 { |
| 38 | return Flow 'storage 'permission { |
| 39 | frozen: try! graph::freeze(builder), |
| 40 | blocks: empty, |
| 41 | }; |
| 42 | } |
| 43 | let first = try reserve(&mut builder, 0, empty, storage, permission); |
| 44 | let entries = try storage.fill(first, blocks.len); |
| 45 | for i in 1..blocks.len { |
| 46 | set entries[i] = try reserve(&mut builder, i, empty, storage, permission); |
| 47 | } |
| 48 | for block, i in blocks { |
| 49 | let instructions = block.instructions; |
| 50 | let mut links = empty; |
| 51 | if instructions.len > 0 { |
| 52 | let targets = published::successors(&instructions[instructions.len - 1]); |
| 53 | if targets.len > 0 { |
| 54 | let successors = try storage.fill(entries[targets[0]], targets.len); |
| 55 | for j in 1..targets.len { |
| 56 | set successors[j] = entries[targets[j]]; |
| 57 | } |
| 58 | set links = &successors[..]; |
| 59 | } |
| 60 | } |
| 61 | try! define(&mut builder, entries[i], links, permission); |
| 62 | } |
| 63 | return Flow 'storage 'permission { |
| 64 | frozen: try! graph::freeze(builder), |
| 65 | blocks: &entries[..], |
| 66 | }; |
| 67 | } |
| 68 | |
| 69 | /// Reserve a block before its outgoing links are known. |
| 70 | fn reserve 'storage 'permission ( |
| 71 | builder: &mut graph::Builder 'storage, |
| 72 | index: u32, |
| 73 | empty: &'storage [Block 'storage 'permission], |
| 74 | storage: &Session 'storage, |
| 75 | permission: &'permission mut Permission, |
| 76 | ) -> Block 'storage 'permission throws (alloc::AllocError) { |
| 77 | let links = try storage.new(empty); |
| 78 | let token = try graph::reserve(builder, storage); |
| 79 | return Block 'storage 'permission { |
| 80 | token, |
| 81 | index, |
| 82 | links: &cell 'permission *links, |
| 83 | }; |
| 84 | } |
| 85 | |
| 86 | /// Complete a block after all successors have been checked. |
| 87 | fn define 'storage 'permission ( |
| 88 | builder: &mut graph::Builder 'storage, |
| 89 | block: Block 'storage 'permission, |
| 90 | links: &'storage [Block 'storage 'permission], |
| 91 | permission: &'permission mut Permission, |
| 92 | ) throws (graph::Error) { |
| 93 | try graph::check(builder, block.token); |
| 94 | for successor in links { |
| 95 | try graph::check(builder, successor.token); |
| 96 | } |
| 97 | set *block.links = links; |
| 98 | try graph::complete(builder, block.token); |
| 99 | } |
| 100 | |
| 101 | /// Borrow the successors of a published block. |
| 102 | export fn successors 'storage 'permission ( |
| 103 | flow: &Flow 'storage 'permission, |
| 104 | index: u32, |
| 105 | permission: &'permission mut Permission, |
| 106 | ) -> &'storage [Block 'storage 'permission] { |
| 107 | let block = flow.blocks[index]; |
| 108 | try! graph::checkFrozen(&flow.frozen, block.token); |
| 109 | let authority: 'loan = &*permission, links = &*block.links in { |
| 110 | return *links; |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | /// Return the dataflow table position retained by a block identity. |
| 115 | export fn index 'storage 'permission (block: Block 'storage 'permission) -> u32 { |
| 116 | return block.index; |
| 117 | } |