lib/std/lang/gen/labels.rad 2.3 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 = MAX_FUNCS * 2;
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
    assert blockIdx < l.blockOffsets.len, "recordBlock: block index out of range";
42
    l.blockOffsets[blockIdx] = offset;
43
    l.blockCount += 1;
44
}
45
46
/// Look up a block's byte offset by index. O(1).
47
pub fn blockOffset(l: *Labels, blockIdx: u32) -> i32 {
48
    assert blockIdx < l.blockCount, "blockOffset: block not recorded";
49
    return l.blockOffsets[blockIdx];
50
}
51
52
/// Look up a function's byte offset by name.
53
pub fn funcOffset(l: *Labels, name: *[u8]) -> i32 {
54
    if let offset = dict::get(&l.funcs, name) {
55
        return offset;
56
    }
57
    panic "funcOffset: unknown function";
58
}
59
60
/// Compute branch offset to a block given source instruction index.
61
pub fn branchToBlock(l: *Labels, srcIndex: u32, blockIdx: u32, instrSize: i32) -> i32 {
62
    let targetOffset = blockOffset(l, blockIdx);
63
    let srcOffset = srcIndex as i32 * instrSize;
64
65
    return targetOffset - srcOffset;
66
}
67
68
/// Compute branch offset to a function given source instruction index.
69
pub fn branchToFunc(l: *Labels, srcIndex: u32, name: *[u8], instrSize: i32) -> i32 {
70
    let targetOffset = funcOffset(l, name);
71
    let srcOffset = srcIndex as i32 * instrSize;
72
73
    return targetOffset - srcOffset;
74
}