lower: Avoid redundant constant array layouts

45c563a2cb063ca486c722a93cff929889613682a455b8ad917e34f8f78947c1
Constant array element slots need no padding beyond their payloads.
Use payload lowering directly and calculate layouts only where they
are needed. Preserve padding within records and union payloads.

Assisted-by: Codex:gpt-6-astra
Alexis Sellier committed ago 1 parent ecdf6a84
lib/std/lang/lower.rad +9 -7
1406 1406
    }
1407 1407
    dataSliceHeader(b, dataName, arrInfo.length);
1408 1408
}
1409 1409
1410 1410
/// Lower a constant expression payload into a builder without slot padding.
1411 +
/// Compute the type layout only when undefined data needs a byte count.
1411 1412
fn lowerConstDataPayloadInto(
1412 1413
    self: *mut Lowerer,
1413 1414
    node: *ast::Node,
1414 1415
    ty: resolver::Type,
1415 1416
    dataPrefix: *[u8],
1434 1435
                try lowerConstUnionVariantInto(self, node, sym, ty, &mut [], dataPrefix, b);
1435 1436
                return;
1436 1437
            }
1437 1438
        }
1438 1439
    }
1439 -
    let layout = resolver::getTypeLayout(ty);
1440 -
1441 1440
    match node.value {
1442 1441
        case ast::NodeValue::Undef => {
1442 +
            let layout = resolver::getTypeLayout(ty);
1443 1443
            dataBuilderPush(b, il::DataValue {
1444 1444
                item: il::DataItem::Undef,
1445 1445
                count: layout.size
1446 1446
            });
1447 1447
        }
1508 1508
        dataBuilderPush(b, il::DataValue { item: il::DataItem::Undef, count: padding });
1509 1509
    }
1510 1510
}
1511 1511
1512 1512
/// Flatten a constant array literal `[a, b, c]` into a builder.
1513 +
/// Each element payload fills its type size; no extra slot padding is needed.
1513 1514
fn lowerConstArrayLitInto(
1514 1515
    self: *mut Lowerer,
1515 1516
    elems: *mut [*ast::Node],
1516 1517
    ty: resolver::Type,
1517 1518
    dataPrefix: *[u8],
1518 1519
    b: *mut DataValueBuilder
1519 1520
) throws (LowerError) {
1520 1521
    let case resolver::Type::Array(arrInfo) = ty
1521 1522
        else throw LowerError::ExpectedArray;
1522 1523
    let elemTy = *arrInfo.item;
1523 -
    let elemLayout = resolver::getTypeLayout(elemTy);
1524 1524
1525 1525
    for elem in elems {
1526 -
        try lowerConstDataInto(self, elem, elemTy, elemLayout.size, dataPrefix, b);
1526 +
        try lowerConstDataPayloadInto(self, elem, elemTy, dataPrefix, b);
1527 1527
    }
1528 1528
}
1529 1529
1530 1530
/// Build data values for a constant array repeat literal `[item; count]`.
1531 +
/// Repeat element payloads without extra slot padding. Undefined data uses
1532 +
/// the element layout to compute the total byte count.
1531 1533
fn lowerConstArrayRepeatInto(
1532 1534
    self: *mut Lowerer,
1533 1535
    repeat: ast::ArrayRepeatLit,
1534 1536
    ty: resolver::Type,
1535 1537
    dataPrefix: *[u8],
1537 1539
) throws (LowerError) {
1538 1540
    let case resolver::Type::Array(arrInfo) = ty
1539 1541
        else throw LowerError::ExpectedArray;
1540 1542
    let length = arrInfo.length;
1541 1543
    let elemTy = *arrInfo.item;
1542 -
    let elemLayout = resolver::getTypeLayout(elemTy);
1543 1544
1544 1545
    if let case ast::NodeValue::Undef = repeat.item.value {
1546 +
        let elemLayout = resolver::getTypeLayout(elemTy);
1545 1547
        dataBuilderPush(b, il::DataValue {
1546 1548
            item: il::DataItem::Undef,
1547 1549
            count: elemLayout.size * length
1548 1550
        });
1549 1551
    } else if let val = resolver::constValueEntry(self.resolver, repeat.item) {
1550 1552
        if let case resolver::ConstValue::String(_) = val {
1551 1553
            // A string used as a slice is represented by a three-word slice
1552 1554
            // header, not by the bytes of the string itself.
1553 1555
            for _ in 0..length {
1554 -
                try lowerConstDataInto(self, repeat.item, elemTy, elemLayout.size, dataPrefix, b);
1556 +
                try lowerConstDataPayloadInto(self, repeat.item, elemTy, dataPrefix, b);
1555 1557
            }
1556 1558
        } else {
1557 1559
            dataBuilderPush(b, il::DataValue {
1558 1560
                item: constValueToDataItem(self, val, elemTy),
1559 1561
                count: length
1560 1562
            });
1561 1563
        }
1562 1564
    } else {
1563 1565
        for _ in 0..length {
1564 -
            try lowerConstDataInto(self, repeat.item, elemTy, elemLayout.size, dataPrefix, b);
1566 +
            try lowerConstDataPayloadInto(self, repeat.item, elemTy, dataPrefix, b);
1565 1567
        }
1566 1568
    }
1567 1569
}
1568 1570
1569 1571
/// Build data values for a constant record literal.