lib/std/lang/gen/labels.rad 2.4 KiB raw
1
//! Label tracking and branch resolution.
2
//!
3
//! Provides target-independent block/label tracking for branch resolution.
4
5
use std::collections::dict;
6
7
/// Maximum number of blocks per function.
8
pub const MAX_BLOCKS_PER_FN: u32 = 4096;
9
/// Maximum number of functions.
10
pub const MAX_FUNCS: u32 = 8192;
11
/// Size of the function hash table. Must be a power of two.
12
pub const FUNC_TABLE_SIZE: u32 = 16384;
13
14
/// Label tracking for code emission.
15
pub record Labels {
16
    /// Block offsets indexed by block index.
17
    /// Per-function, reset each function.
18
    blockOffsets: *mut [i32],
19
    /// Number of blocks recorded in current function.
20
    blockCount: u32,
21
    /// Function name to byte offset mapping.
22
    funcs: dict::Dict,
23
}
24
25
/// Create a new labels tracker with caller-provided storage.
26
pub fn init(blockOffsets: *mut [i32], funcEntries: *mut [dict::Entry]) -> Labels {
27
    return Labels {
28
        blockOffsets,
29
        blockCount: 0,
30
        funcs: dict::init(funcEntries),
31
    };
32
}
33
34
/// Reset block count for a new function.
35
pub fn resetBlocks(l: *mut Labels) {
36
    l.blockCount = 0;
37
}
38
39
/// Record a block's code offset by its index. O(1).
40
pub fn recordBlock(l: *mut Labels, blockIdx: u32, offset: i32) {
41
    if blockIdx >= l.blockOffsets.len {
42
        panic "recordBlock: block index out of range";
43
    }
44
    l.blockOffsets[blockIdx] = offset;
45
    l.blockCount += 1;
46
}
47
48
/// Look up a block's byte offset by index. O(1).
49
pub fn blockOffset(l: *Labels, blockIdx: u32) -> i32 {
50
    if blockIdx >= l.blockCount {
51
        panic "blockOffset: block not recorded";
52
    }
53
    return l.blockOffsets[blockIdx];
54
}
55
56
/// Look up a function's byte offset by name.
57
pub fn funcOffset(l: *Labels, name: *[u8]) -> i32 {
58
    if let offset = dict::get(&l.funcs, name) {
59
        return offset;
60
    }
61
    panic "funcOffset: unknown function";
62
}
63
64
/// Compute branch offset to a block given source instruction index.
65
pub fn branchToBlock(l: *Labels, srcIndex: u32, blockIdx: u32, instrSize: i32) -> i32 {
66
    let targetOffset = blockOffset(l, blockIdx);
67
    let srcOffset = srcIndex as i32 * instrSize;
68
69
    return targetOffset - srcOffset;
70
}
71
72
/// Compute branch offset to a function given source instruction index.
73
pub fn branchToFunc(l: *Labels, srcIndex: u32, name: *[u8], instrSize: i32) -> i32 {
74
    let targetOffset = funcOffset(l, name);
75
    let srcOffset = srcIndex as i32 * instrSize;
76
77
    return targetOffset - srcOffset;
78
}