compiler: Calculate array layouts from resolved element layouts
9f38500b2c125967ecd0cd65a387e615d94e0848009fdd8c5194249b09004cd0
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]; |