compiler: Check package symbol collection sequencing

9e6185409d2e0bedf18daeb29cbd9053b85906473ca79484632e26748a74130b
Alexis Sellier committed ago 1 parent da81577b
lib/std/lang/il/binary/collect.rad +18 -5
230 230
    owner: *[u8],
231 231
    program: il::Program,
232 232
    exports: &[binary::Export],
233 233
    entry: ?*[u8]
234 234
) -> binary::Package throws (binary::Error) {
235 +
    try collectNames(names, owner, &program, exports, entry);
236 +
    return binary::Package {
237 +
        symbols: &names.symbols[..names.symbolCount], name: owner,
238 +
        dependencies: &names.dependencies[..names.dependencyCount], exports: exports as *unsafe [binary::Export], entry, program,
239 +
    };
240 +
}
241 +
242 +
/// Collect package metadata before data and function references.
243 +
fn collectNames 'tables (
244 +
    names: &mut Names 'tables,
245 +
    owner: *[u8],
246 +
    program: &il::Program,
247 +
    exports: &[binary::Export],
248 +
    entry: ?*[u8],
249 +
) throws (binary::Error) {
235 250
    try add(names, owner);
236 251
    for item in exports {
237 252
        try definition(names, owner, item.name);
238 253
    }
239 254
    if let name = entry {
240 255
        try definition(names, owner, name);
241 256
    }
242 257
    try collectData(names, owner, &program.data[..]);
243 -
    try collectFunctions(names, owner, program.fns);
244 -
    return binary::Package {
245 -
        symbols: &names.symbols[..names.symbolCount], name: owner,
246 -
        dependencies: &names.dependencies[..names.dependencyCount], exports: exports as *unsafe [binary::Export], entry, program,
247 -
    };
258 +
    unsafe {
259 +
        try collectFunctions(names, owner, program.fns);
260 +
    }
248 261
}
lib/std/lang/il/binary/decodeTests.rad +32 -0
564 564
        }
565 565
        for i in capacity..symbols.len { assert symbols[i].len == 0; }
566 566
    }
567 567
}
568 568
569 +
/// Exports precede the entry name, and entry definitions belong to the package.
570 +
@test unsafe fn entryCollectionOrder() throws (testing::TestError) {
571 +
    let local = il::Program { data: &[], fns: &[] };
572 +
    let exports = [
573 +
        binary::Export { name: "p::second", kind: binary::ExportKind::Function },
574 +
        binary::Export { name: "p::first", kind: binary::ExportKind::Function },
575 +
        binary::Export { name: "p::second", kind: binary::ExportKind::Function },
576 +
    ];
577 +
    let entries: [?*[u8]; 5] = [nil, "p::first", "p::start", "other::start", "p::"];
578 +
    for entry, index in entries {
579 +
        let mut symbols: [*[u8]; 4] = [""; 4];
580 +
        let mut dependencies: [*[u8]; 1] = [""; 1];
581 +
        let symbolTable: 'tables = &mut symbols[..], dependencyTable = &mut dependencies[..] in {
582 +
            let mut names = collect::new(symbolTable, dependencyTable);
583 +
            let package = try collect::package(&mut names, "p", local, &exports[..], entry) catch err {
584 +
                assert index >= 3;
585 +
                assert err == binary::Error::Invalid;
586 +
                continue;
587 +
            };
588 +
            assert index < 3;
589 +
            assert package.symbols.len == (4 if index == 2 else 3);
590 +
            for name, i in ["p", "p::second", "p::first"] {
591 +
                try testing::expectBytesEq(package.symbols[i], name);
592 +
            }
593 +
            if index == 2 { try testing::expectBytesEq(package.symbols[3], "p::start"); }
594 +
            assert package.dependencies.len == 0;
595 +
            assert package.exports.len == 3;
596 +
            assert package.entry == entry;
597 +
        }
598 +
    }
599 +
}
600 +
569 601
/// Data collection retains first-use order and unique dependencies.
570 602
@test unsafe fn dataCollectionOrder() throws (testing::TestError) {
571 603
    let item = il::Data {
572 604
        name: "p::data", size: 64, alignment: 8, readOnly: true, isZeroInit: false,
573 605
        values: &[