compiler: Calculate array layouts from resolved element layouts

9f38500b2c125967ecd0cd65a387e615d94e0848009fdd8c5194249b09004cd0
Alexis Sellier committed ago 1 parent 560d04a3
lib/std/lang/resolver.rad +5 -6
2020 2020
        case Type::U64, Type::I64 => return Layout { size: 8, alignment: 8 },
2021 2021
        case Type::Fn(_) => return Layout { size: PTR_SIZE, alignment: PTR_SIZE },
2022 2022
        case Type::Cell { .. } => return Layout {
2023 2023
            size: PTR_SIZE, alignment: PTR_SIZE
2024 2024
        },
2025 -
        case Type::Array(arr) => return getArrayLayout(arr),
2025 +
        case Type::Array(arr) => return getArrayLayout(getTypeLayout(*arr.item), arr.length),
2026 2026
        case Type::Optional(inner) => return getOptionalLayout(*inner),
2027 2027
        case Type::Nominal(info) => return getNominalLayout(*info),
2028 2028
        else => {
2029 2029
            panic "getTypeLayout: the given type cannot be layed out";
2030 2030
        }
2043 2043
        }
2044 2044
    }
2045 2045
    return layout;
2046 2046
}
2047 2047
2048 -
/// Get the layout of an array type.
2049 -
export unsafe fn getArrayLayout(arr: ArrayType) -> Layout {
2050 -
    let itemLayout = getTypeLayout(*arr.item);
2048 +
/// Get an array layout from its element layout and length.
2049 +
export fn getArrayLayout(item: Layout, length: u32) -> Layout {
2051 2050
    return Layout {
2052 -
        size: itemLayout.size * arr.length,
2053 -
        alignment: itemLayout.alignment,
2051 +
        size: item.size * length,
2052 +
        alignment: item.alignment,
2054 2053
    };
2055 2054
}
2056 2055
2057 2056
/// Get the layout of an optional type.
2058 2057
export unsafe fn getOptionalLayout(inner: Type) -> Layout {
lib/std/lang/resolver/tests.rad +12 -0
11 11
use std::lang::parser;
12 12
use std::lang::scanner;
13 13
use std::lang::module;
14 14
use std::lang::strings;
15 15
16 +
/// Array layouts retain element alignment for empty and populated arrays.
17 +
@test fn testArrayLayoutFromElementLayout() throws (testing::TestError) {
18 +
    for alignment in [1 as u32, 2, 4, 8, 16] {
19 +
        let item = super::Layout { size: alignment, alignment };
20 +
        for count in [0 as u32, 1, 3] {
21 +
            let result = super::getArrayLayout(item, count);
22 +
            assert result.size == alignment * count;
23 +
            assert result.alignment == alignment;
24 +
        }
25 +
    }
26 +
}
27 +
16 28
/// Synthetic file path used for resolver tests.
17 29
constant MODULE_PATH: *[u8] = "/dev/test.rad";
18 30
19 31
/// AST arena storage used by resolver tests.
20 32
static AST_ARENA: [u8; 2097152] = [0; 2097152];